# New Ticket Created by (Peter J. Acklam) # Please include the string: [perl #81170] # in the subject line of all future correspondence about this issue. # <URL: http://rt.perl.org/rt3/Ticket/Display.html?id=81170 > Why: Math::BigInt::Calc->_num() converts a big integer (in the internal format) to a Perl scalar. If the big integer is too large to be represented as a Perl scalar, it might return a Perl scalar numeric "nan", rather than "inf". The reason is that the current algorithm might multiply "inf" by "0", giving a "nan" which propagates. The following example illustrates the bug: perl -MMath::BigInt=lib,Calc -wle \ 'print Math::BigInt->new("1e999999")->numify()' How: This fix computes the output in a different way, never multiply "inf" by "0". Test: It is not obvious to me how to test this automatically in a portable way, since Perl has no standard way of stringifying a scalar numeric infinity. However the desired behaviour is verified manually and no existing tests fail with the new code. --- dist/Math-BigInt/lib/Math/BigInt/Calc.pm | 23 ++++++++++++++--------- 1 files changed, 14 insertions(+), 9 deletions(-) diff --git a/dist/Math-BigInt/lib/Math/BigInt/Calc.pm b/dist/Math-BigInt/lib/Math/BigInt/Calc.pm index 3cb2025..c778dcd 100644 --- a/dist/Math-BigInt/lib/Math/BigInt/Calc.pm +++ b/dist/Math-BigInt/lib/Math/BigInt/Calc.pm @@ -272,17 +272,22 @@ sub _str sub _num { - # Make a number (scalar int/float) from a BigInt object - my $x = $_[1]; + # Make a Perl scalar number (int/float) from a BigInt object. + my $x = $_[1]; - return 0+$x->[0] if scalar @$x == 1; # below $BASE - my $fac = 1; - my $num = 0; - foreach (@$x) - { - $num += $fac*$_; $fac *= $BASE; + return 0 + $x->[0] if scalar @$x == 1; # below $BASE + + # Start with the most significant element and work towards the least + # significant element. Avoid multiplying "inf" (which happens if the number + # overflows) with "0" (if there are zero elements in $x) since this gives + # "nan" which propagates to the output. + + my $num = 0; + for (my $i = $#$x ; $i >= 0 ; --$i) { + $num *= $BASE; + $num += $x -> [$i]; } - $num; + return $num; } ############################################################################## -- 1.7.2.3