From 53a61b46a714f04aa648f0c6fa67899bc51b5888 Mon Sep 17 00:00:00 2001 From: Benjamin Morel Date: Tue, 2 Jun 2015 22:08:56 +0200 Subject: [PATCH] Add BigDecimal::divideAndRemainder() --- src/BigDecimal.php | 32 +++++++++++++++ src/BigInteger.php | 2 + tests/BigDecimalTest.php | 87 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 121 insertions(+) diff --git a/src/BigDecimal.php b/src/BigDecimal.php index 0a9c987..45e3cf8 100644 --- a/src/BigDecimal.php +++ b/src/BigDecimal.php @@ -285,6 +285,38 @@ public function dividedBy($that, $scale = null, $roundingMode = RoundingMode::UN return new BigDecimal($result, $scale); } + /** + * Returns the quotient and remainder of the division of this number and the given one. + * + * The quotient has a scale of 0, and the remainder has the largest scale of the two numbers. + * + * @param BigDecimal|number|string $that The number to divide. + * + * @return BigDecimal[] An array containing the quotient and the remainder. + * + * @throws ArithmeticException If the divisor is zero. + */ + public function divideAndRemainder($that) + { + $that = BigDecimal::of($that); + + if ($that->isZero()) { + throw ArithmeticException::divisionByZero(); + } + + $p = $this->valueWithMinScale($that->scale); + $q = $that->valueWithMinScale($this->scale); + + list ($quotient, $remainder) = Calculator::get()->div($p, $q); + + $scale = max($this->scale, $that->scale); + + $quotient = new BigDecimal($quotient, 0); + $remainder = new BigDecimal($remainder, $scale); + + return [$quotient, $remainder]; + } + /** * Returns this number exponentiated. * diff --git a/src/BigInteger.php b/src/BigInteger.php index a054e1b..683e345 100644 --- a/src/BigInteger.php +++ b/src/BigInteger.php @@ -288,6 +288,8 @@ public function dividedBy($that, $roundingMode = RoundingMode::UNNECESSARY) } /** + * Returns the quotient and remainder of the division of this number and the given one. + * * @param BigInteger|integer|string $that The divisor. * * @return BigInteger[] An array containing the quotient and the remainder. diff --git a/tests/BigDecimalTest.php b/tests/BigDecimalTest.php index c6fb376..c112507 100644 --- a/tests/BigDecimalTest.php +++ b/tests/BigDecimalTest.php @@ -1139,6 +1139,93 @@ public function providerRoundingMode() [RoundingMode::UNNECESSARY, '-3.501', null, null, null], ]; } + /** + * @dataProvider providerDivideAndRemainder + * + * @param string $dividend The dividend. + * @param string $divisor The divisor. + * @param string $quotient The expected quotient. + * @param string $remainder The expected remainder. + */ + public function testDivideAndRemainder($dividend, $divisor, $quotient, $remainder) + { + list ($q, $r) = BigDecimal::of($dividend)->divideAndRemainder($divisor); + + $this->assertSame($quotient, (string) $q); + $this->assertSame($remainder, (string) $r); + } + + /** + * @return array + */ + public function providerDivideAndRemainder() + { + return [ + ['1', '123', '0', '1'], + ['1', '-123', '0', '1'], + ['-1', '123', '0', '-1'], + ['-1', '-123', '0', '-1'], + + ['1999999999999999999999999', '2000000000000000000000000', '0', '1999999999999999999999999'], + ['1999999999999999999999999', '-2000000000000000000000000', '0', '1999999999999999999999999'], + ['-1999999999999999999999999', '2000000000000000000000000', '0', '-1999999999999999999999999'], + ['-1999999999999999999999999', '-2000000000000000000000000', '0', '-1999999999999999999999999'], + + ['123', '1', '123', '0'], + ['123', '-1', '-123', '0'], + ['-123', '1', '-123', '0'], + ['-123', '-1', '123', '0'], + + ['123', '2', '61', '1'], + ['123', '-2', '-61', '1'], + ['-123', '2', '-61', '-1'], + ['-123', '-2', '61', '-1'], + + ['123', '123', '1', '0'], + ['123', '-123', '-1', '0'], + ['-123', '123', '-1', '0'], + ['-123', '-123', '1', '0'], + + ['123', '124', '0', '123'], + ['123', '-124', '0', '123'], + ['-123', '124', '0', '-123'], + ['-123', '-124', '0', '-123'], + + ['124', '123', '1', '1'], + ['124', '-123', '-1', '1'], + ['-124', '123', '-1', '-1'], + ['-124', '-123', '1', '-1'], + + ['1000000000000000000000000000000', '3', '333333333333333333333333333333', '1'], + ['1000000000000000000000000000000', '9', '111111111111111111111111111111', '1'], + ['1000000000000000000000000000000', '11', '90909090909090909090909090909', '1'], + ['1000000000000000000000000000000', '13', '76923076923076923076923076923', '1'], + ['1000000000000000000000000000000', '21', '47619047619047619047619047619', '1'], + + ['123456789123456789123456789', '987654321987654321', '124999998', '850308642973765431'], + ['123456789123456789123456789', '-87654321987654321', '-1408450676', '65623397056685793'], + ['-123456789123456789123456789', '7654321987654321', '-16129030020', '-1834176331740369'], + ['-123456789123456789123456789', '-654321987654321', '188678955396', '-205094497790673'], + + ['10.11', '3.3', '3', '0.21'], + ['1', '-0.0013', '-769', '0.0003'], + ['-1.000000000000000000001', '0.0000009298439898981609', '-1075449', '-0.0000002109080127582569'], + ['-1278438782896060000132323.32333', '-53.4836775545640521556878910541', '23903344746475158719036', '-30.0786684482104867175202241524'], + ['23999593472872987498347103908209387429846376', '-0.005', '-4799918694574597499669420781641877485969275200', '0.000'], + + ['1000000000000000000000000000000.0', '3', '333333333333333333333333333333', '1.0'], + ['1000000000000000000000000000000.0', '9', '111111111111111111111111111111', '1.0'], + ['1000000000000000000000000000000.0', '11', '90909090909090909090909090909', '1.0'], + ['1000000000000000000000000000000.0', '13', '76923076923076923076923076923', '1.0'], + ['0.9999999999999999999999999999999', '0.21', '4', '0.1599999999999999999999999999999'], + + ['1000000000000000000000000000000.0', '3.9', '256410256410256410256410256410', '1.0'], + ['-1000000000000000000000000000000.0', '9.8', '-102040816326530612244897959183', '-6.6'], + ['1000000000000000000000000000000.0', '-11.7', '-85470085470085470085470085470', '1.0'], + ['-1000000000000000000000000000000.0', '-13.7', '72992700729927007299270072992', '-9.6'], + ['0.99999999999999999999999999999999', '0.215', '4', '0.13999999999999999999999999999999'], + ]; + } /** * @dataProvider providerPower