|Subject:||Math::BigInt->new() wrongly converts large floats|
|X-Mailer:||MIME-tools 5.504 (Entity 5.504)|
|Message-ID:||<rt-4.0.18-10831-1394897983-212.0-0-0 [...] rt.cpan.org>|
A conversion of large integral floating-point numbers into BigInts can lose significant digits. Test case: 504403158265495552.0 == 7 * 2**56, which is exactly representable as a float/double. $ perl -MMath::BigInt -e 'print Math::BigInt->new(504403158265495552.0)->bstr(), "\n";' 504403158265496000 A test case that reqires more than 64 integer bits is 7 * 2**66 = 516508834063867445248.0. The cause is that the _split function in Math::BigInt treats its argument as a string and hereby triggers Perl's automatic conversion which does not output enough digits for large integers. A fix is to explicitly convert via sprintf("%f",..), which retains all digits before the decimal point. Doing this for non-floats is superfluous and possibly harmful, so we test the accuracy of a roundtrip with the automatic conversion first: @@ -3048,6 +3048,8 @@ # invalid input. my $x = shift; + $x= sprintf("%f", $x) unless "$x" == $x; # ensure enough digits from float + # strip white space at front, also extraneous leading zeros $x =~ s/^\s*([-]?)0*([0-9])/$1$2/g; # will not strip ' .2' $x =~ s/^\s+//; # but this will Line numbers refer to version 1.9991, which my distribution ships but CPAN does not yet (?!). This issue was first reported to the perlbug list, as [perl #121136].