Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl: the Markov chain saw
 
PerlMonks  

Math With Big Numbers

by AlligatorStamp (Initiate)
on Feb 14, 2019 at 20:32 UTC ( [id://1229917]=perlquestion: print w/replies, xml ) Need Help??

AlligatorStamp has asked for the wisdom of the Perl Monks concerning the following question:

Hello. I am having trouble getting Perl to give me correct answers with large numbers. I am using Perl 5.14.2 on Windows.

6^25 = 28430288029929701376.

When I run the following:

my $bigNumber = 6**25; printf ("%.f", $bigNumber);

I get 28430288029929701000.

Assuming that this lack of accuracy was due to 32-bit Perl's trouble with numbers above 2^53, I tried the following:

use Math::BigInt; my $bigNumber = Math::BigInt->new(6**25); print "$bigNumber";

which gives me 28430288029929700000

I don't understand why BigInt is giving me an even less accurate answer.

Replies are listed 'Best First'.
Re: Math With Big Numbers
by tybalt89 (Monsignor) on Feb 14, 2019 at 20:44 UTC
    $bigNumber = Math::BigInt->new(6) ** Math::BigInt->new(25);
      $bigNumber = Math::BigInt->new(6) ** Math::BigInt->new(25);

      Or simply:
      $bigNumber = Math::BigInt->new(6) ** 25;
      Perl will print 6 ** 25 as 2.84302880299297e+019 and doing Math::BigInt->new(6 ** 25) therefore becomes Math::BigInt->new(2.84302880299297e+019), which Math::BigInt interprets literally as Math::BigInt->new(28430288029929700000). And that's how AlligatorStamp gets the value he observed.

      With perl, we can also see the actual value by doing:
      C:\>perl -le "printf '%0.f', 6 ** 25;" 28430288029929701376
      And the same should work with AlligatorStamp's perl-5.14.2 ... unless he's running ActivePerl, in which case it will be 28430288029929701000.

      Cheers,
      Rob
Re: Math With Big Numbers
by davido (Cardinal) on Feb 15, 2019 at 06:11 UTC

    Maybe this can shed some light. In this first example we see that the number is stored as an NV (numeric value) which is different from an IV (integer value) or UV (unsigned integer value). The reason is that 6**25 would overflow an IV or UV, so the only reasonable ways to store it would be as an NV (a double precision float) or a string. But there hasn't been any stringification, so you get the NV:

    perl -MDevel::Peek -e 'my $n = 6**25; Dump($n)' SV = NV(0x563681e7c888) at 0x563681e7c8a0 REFCNT = 1 FLAGS = (NOK,pNOK) NV = 2.84302880299297e+19

    You want full precision. So you try this:

    perl -MO=Deparse -MMath::BigInt -e 'my $bi = Math::BigInt->new(6**25); +' my $bi = 'Math::BigInt'->new(2.84302880299297e+19);

    Well, that didn't work. Why? Because 6**25 gets computed before Math::BigInt gets a chance to see it, so by the time Math::BigInt gets it, you've already lost precision.

    What else should we try? How about decomposing it to the constituent parts of the equation, passing those normal-sized ints to Math::BigInt, and then asking that module to do the magic for you?

    perl -MMath::BigInt -e 'my $bi = Math::BigInt->new(6)->bpow(25); print + $bi, "\n";' 28430288029929701376

    That looks better.


    Dave

Re: Math With Big Numbers
by pryrt (Abbot) on Feb 14, 2019 at 21:02 UTC
    C:\>perl -MMath::BigInt -le "push @ans, 6**25; push @ans, Math::BigInt +->new(6)**25; push @ans, 6**Math::BigInt->new(25); push @ans, Math::B +igInt->new(6)**Math::BigInt->new(25); print for @ans" 2.84302880299297e+019 28430288029929701376 28430288029929701376 28430288029929701376

    As ++tybalt89 pointed out, you need to convert before you do the exponentiation. But you don't actually have to convert both -- you can convert either the base or the exponent or both, and the BigInt math will work correctly

Re: Math With Big Numbers
by Cristoforo (Curate) on Feb 14, 2019 at 20:42 UTC
    While I can't comment on why you are not getting accurate results, when I use bignum, I get the exact number.

    C:\Old_Data\perlp>perl -Mbignum -e "print 6**25" 28430288029929701376
Re: Math With Big Numbers
by Laurent_R (Canon) on Feb 14, 2019 at 21:58 UTC
    tybalt89 and other monks have provided good explanations and solutions.

    Just for the record, using Perl 6 out of the box:

    ~ perl6 -e 'say 6**25;' 28430288029929701376
Re: Math With Big Numbers
by danaj (Friar) on Mar 26, 2019 at 23:20 UTC

    For fun on the quadmath perl I use:

    $ perl -V | grep nvsize nvsize=16 $ perl -E 'say 6**25; say ~0' 28430288029929701376 18446744073709551615

    Quadmath works in this case, but of course you really want to use bigint, Math::BigInt, Math::GMP, Math::GMPz, etc. as this is just putting it off (e.g. 6^42 is exact but 6^43 is not).

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://1229917]
Front-paged by haukex
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others wandering the Monastery: (7)
As of 2024-03-28 22:06 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found