/** * Protected constructor. Use a factory method to obtain an instance. * * @param BigInteger $numerator The numerator. * @param BigInteger $denominator The denominator. * @param bool $checkDemominator Whether to check the denominator for negative and zero. * * @throws DivisionByZeroException If the denominator is zero. */ protected function __construct(BigInteger $numerator, BigInteger $denominator, $checkDemominator) { if ($checkDemominator) { if ($denominator->isZero()) { throw DivisionByZeroException::denominatorMustNotBeZero(); } if ($denominator->isNegative()) { $numerator = $numerator->negated(); $denominator = $denominator->negated(); } } $this->numerator = $numerator; $this->denominator = $denominator; }
/** * Creates a BigNumber of the given value. * * The concrete return type is dependent on the given value, with the following rules: * * - BigNumber instances are returned as is * - integer numbers are returned as BigInteger * - floating point numbers are returned as BigDecimal * - strings containing a `/` character are returned as BigRational * - strings containing a `.` character or using an exponentional notation are returned as BigDecimal * - strings containing only digits with an optional leading `+` or `-` sign are returned as BigInteger * * @param BigNumber|number|string $value * * @return BigNumber * * @throws NumberFormatException If the format of the number is not valid. * @throws DivisionByZeroException If the value represents a rational number with a denominator of zero. */ public static function of($value) { if ($value instanceof BigNumber) { return $value; } if (is_int($value)) { return new BigInteger((string) $value); } $value = (string) $value; if (preg_match(self::$regexp, $value, $matches) !== 1) { throw new NumberFormatException('The given value does not represent a valid number.'); } 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); }
/** * Returns the quotient and remainder of the division of this number by the given one. * * @param BigNumber|number|string $that The divisor. Must be convertible to a BigInteger. * * @return BigInteger[] An array containing the quotient and the remainder. * * @throws DivisionByZeroException If the divisor is zero. */ public function quotientAndRemainder($that) { $that = BigInteger::of($that); if ($that->value === '0') { throw DivisionByZeroException::divisionByZero(); } list($quotient, $remainder) = Calculator::get()->divQR($this->value, $that->value); return [new BigInteger($quotient), new BigInteger($remainder)]; }
/** * @return array */ public function providerDividedBy() { return [['123456789098765432101234567890987654321', 1, '123456789098765432101234567890987654321'], ['123456789098765432101234567890987654321', 2, RoundingNecessaryException::getNamespace()], ['123456789098765432101234567890987654321', 0, DivisionByZeroException::getNamespace()], ['123456789098765432101234567890987654321', 0.0, DivisionByZeroException::getNamespace()], ['123456789098765432101234567890987654321', 0.1, RoundingNecessaryException::getNamespace()], ['123456789098765432101234567890987654322', 2, '61728394549382716050617283945493827161'], ['123456789098765432101234567890987654322', 2.0, '61728394549382716050617283945493827161'], ['123456789098765432101234567890987654322', '2', '61728394549382716050617283945493827161'], ['123456789098765432101234567890987654322', '2.0', '61728394549382716050617283945493827161'], ['123456789098765432101234567890987654322', '14/7', '61728394549382716050617283945493827161'], ['61728394549382716050617283945493827161', '0.5', RoundingNecessaryException::getNamespace()], ['61728394549382716050617283945493827161', '1/2', RoundingNecessaryException::getNamespace()]]; }
/** * @return array */ public function providerExactlyDividedBy() { return [[1, 1, '1'], ['1.0', '1.00', '1'], [1, 2, '0.5'], [1, 3, RoundingNecessaryException::getNamespace()], [1, 4, '0.25'], [1, 5, '0.2'], [1, 6, RoundingNecessaryException::getNamespace()], [1, 7, RoundingNecessaryException::getNamespace()], [1, 8, '0.125'], [1, 9, RoundingNecessaryException::getNamespace()], [1, 10, '0.1'], ['1.0', 2, '0.5'], ['1.00', 2, '0.5'], ['1.0000', 8, '0.125'], [1, '4.000', '0.25'], ['1', '0.125', '8'], ['1.0', '0.125', '8'], ['1234.5678', '2', '617.2839'], ['1234.5678', '4', '308.64195'], ['1234.5678', '8', '154.320975'], ['1234.5678', '6.4', '192.90121875'], ['7', '3125', '0.00224'], ['4849709849456546549849846510128399', '18014398509481984', '269212976880902984.935786476657271160117801400701864622533321380615234375'], ['4849709849456546549849846510128399', '-18014398509481984', '-269212976880902984.935786476657271160117801400701864622533321380615234375'], ['-4849709849456546549849846510128399', '18014398509481984', '-269212976880902984.935786476657271160117801400701864622533321380615234375'], ['-4849709849456546549849846510128399', '-18014398509481984', '269212976880902984.935786476657271160117801400701864622533321380615234375'], ['123', '0', DivisionByZeroException::getNamespace()], [-789, '0.0', DivisionByZeroException::getNamespace()]]; }
/** * Returns the quotient and remainder of the division of this number by the given one. * * The quotient has a scale of `0`, and the remainder has a scale of `max($this->scale, $that->scale)`. * * @param BigNumber|number|string $that The divisor. Must be convertible to a BigDecimal. * * @return BigDecimal[] An array containing the quotient and the remainder. * * @throws ArithmeticException If the divisor is not a valid decimal number, or is zero. */ public function quotientAndRemainder($that) { $that = BigDecimal::of($that); if ($that->isZero()) { throw DivisionByZeroException::divisionByZero(); } $p = $this->valueWithMinScale($that->scale); $q = $that->valueWithMinScale($this->scale); list($quotient, $remainder) = Calculator::get()->divQR($p, $q); $scale = $this->scale > $that->scale ? $this->scale : $that->scale; $quotient = new BigDecimal($quotient, 0); $remainder = new BigDecimal($remainder, $scale); return [$quotient, $remainder]; }