Friday, May 6, 2011

Why do my Perl bigints have a decimal place?

If I do use a big integer in substr:

use BigInt;
$acct_hash = substr(('99999999999912345' + $data[1]),0,15);

why is the result still 9.9999999999912?

I was expecting 999999999999912. Is there something like:

$data[1] = substr(to_char('999999999999991234'),0,15);

in Perl?

From stackoverflow
  • I think what you're running into is a problem with string interpretation. Try this code:

    use bigint;
    print(99999999999912345 + 99999999999912345, "\n");
    

    And compare it to the very similar:

    use bigint;
    print('99999999999912345' + '99999999999912345', "\n");
    

    Using single quotes around your numbers is turning them into strings, and seems to get around bigint.

  • To get the first 15 digits of the sum of $a and $b, do this:

    use bigint;
    my $a = "99999999999912345";  # works with or without quotes
    my $b = "111";                # works with or without quotes
    print substr(0 + $a + $b, 0, 15), "\n";
    

    The reason why your code didn't work as expected is that Perl does a floating point addition for $a + $b if both $a and $b are strings, even if use bigint is in effect. Example:

    use bigint;
    print     1234567890123456789  +  2 , "\n";  #: 1234567890123456791
    print    "1234567890123456789" +  2 , "\n";  #: 1234567890123456791
    print     1234567890123456789  + "2", "\n";  #: 1234567890123456791
    print    "1234567890123456789" + "2", "\n";  #: 1.23456789012346e+18
    print 0 + 1234567890123456789  + "2", "\n";  #: 1234567890123456791
    

    This behavior is a quirk in the Perl bigint module. You can work it around by prepending a 0 + (as shown above), thus forcing bigint addition instead of floating point addition. Another workaround can be Math::BigInt->new($a) + $b instead of 0 + $a + $b.

    bubaker : Relying on Math::BigInt isn't a workaround - seems like the standard thing to do. Works both by using $a->badd($b) as well as the overridden '+';
    pts : Relying on Math::BigInt is indeed a workaround in my answer. It is a workaround for the quirk that Perl treats `"$a" + "$b"` as a floating point addition in `use bigint` mode.

0 comments:

Post a Comment