Skip Menu |

This queue is for tickets about the Math-BigInt CPAN distribution.

Report information
The Basics
Id: 79060
Status: resolved
Priority: 0/
Queue: Math-BigInt

People
Owner: Nobody in particular
Requestors: mhasch-cpanbugs [...] cozap.com
Cc:
AdminCc:

Bug Information
Severity: Important
Broken in: 1.997
Fixed in: 1.999701



Subject: integer division result off by one in some cases
In integer arithmetic, a quotient and remainder pair should obey the condition: quotient * denominator + remainder == numerator. The Math::BigInt documentation states this fact and mentions in particular, how integer quotients are rounded (towards minus infinity) and how remainders are chosen (between zero and the denominator) out of a residue class to match with this condition. However, as of Math-BigInt-1.998, this is not correctly implemented. Quotients seem to be rounded towards zero, which means that negative division results are off by one if the remainder is not zero. The test script I have attached fails in cases 2 and 3. Curiously, in the bdiv paragraph of the CAVEATS section, the text describes what should happen but the numerical examples are neither consistent with the text nor the implementation: 1 / 4 => ( 0, 1) # correct 1 / -4 => (-1,-3) # correct but not as implemented -3 / 4 => (-1, 1) # correct but not as implemented -3 / -4 => ( 0,-3) # correct -11 / 2 => (-5,1) # wrong but as implemented 11 /-2 => (-5,-1) # wrong but as implemented The behaviour seems to be independent of the math library in use. I checked with GMP, FastCalc and Calc. To fix the problem, bdiv should be revised to round integer quotients with floor rather than truncate semantics and -5 should be replaced by -6 in the examples. -Martin
Subject: div.t
#!/usr/bin/perl # check whether integer bdiv and bmuladd are complementary # n should be equal to d * (n / d) + (n % d) use strict; use warnings; use Test::More tests => 4; use Math::BigInt; sub check { my ($n, $d) = map { Math::BigInt->new($_) } @_; my ($q, $r) = $n->copy->bdiv($d); my $n2 = $d * $q + $r; is $n2, $n, sprintf q["%3s = %2s * %2s + %2s"], $n, $d, $q, $r; } check( 22, 5); check( 22, -5); check(-22, 5); check(-22, -5);
Fixed in Math-BigInt-1.999701.