public static function of($value) : BigNumber
    {
        if ($value instanceof BigNumber) {
            return $value;
        }

        if (\is_int($value)) {
            return new BigInteger((string) $value);
        }

        if (is_float($value)) {
            $value = self::floatToString($value);
        } else {
            $value = (string) $value;
        }

        if (\preg_match(self::PARSE_REGEXP, $value, $matches) !== 1) {
            throw new NumberFormatException(\sprintf('The given value "%s" does not represent a valid number.', $value));
        }

        if (isset($matches['denominator'])) {
            $numerator   = self::cleanUp($matches['integral']);
            $denominator = \ltrim($matches['denominator'], '0');

            if ($denominator === '') {
                throw DivisionByZeroException::denominatorMustNotBeZero();
            }

            return new BigRational(new BigInteger($numerator), new BigInteger($denominator), false);
        }

        if (isset($matches['fractional']) || isset($matches['exponent'])) {
            $fractional = isset($matches['fractional']) ? $matches['fractional'] : '';
            $exponent = isset($matches['exponent']) ? (int) $matches['exponent'] : 0;

            $unscaledValue = self::cleanUp($matches['integral'] . $fractional);

            $scale = \strlen($fractional) - $exponent;

            if ($scale < 0) {
                if ($unscaledValue !== '0') {
                    $unscaledValue .= \str_repeat('0', - $scale);
                }
                $scale = 0;
            }

            return new BigDecimal($unscaledValue, $scale);
        }

        $integral = self::cleanUp($matches['integral']);

        return new BigInteger($integral);
    }