http://www.perlmonks.org?node_id=11155774


in reply to bignum usage?

I wanted to create "bignum usability" SOPW question, but then the SS landed me right here, -- very fresh thread. This pragma is in the core, but how usable/advised/maintained it is?

use strict; use warnings; use feature 'say'; use bignum; # (1) #use bignum downgrade => "Math::BigInt", upgrade => "Math::BigI +nt"; ## (2) #use bigint; say $^V; say my $x = 21778071482940061661655974875633165533182; say my $y = $x / 2;

...

v5.38.0 21778071482940061661655974875633165533182 10889035741470030830827987437816582766590

off-by-one error. Using commented-out lines instead gives me (1):

Deep recursion on subroutine "Math::BigInt::bdiv" at C:/berrybrew/stra +wberry-perl-5.38.0.1-64bit-PDL/perl/site/lib/Math/BigInt.pm line 2229

and the Perl process hangs, or (2):

21778071482940061661655974875633165533182 10889035741470030830827987437816582766591

i.e. "don't use bignum if bigint suffices" will produce the correct answer, but doesn't smell quite right

Replies are listed 'Best First'.
Re^2: bignum usage?
by syphilis (Archbishop) on Nov 24, 2023 at 04:52 UTC
    off-by-one error

    It seems you've hit some precision limit - which is avoided if you use bigint.
    Try placing an extra number at the beginning of $x, and you'll soon see what I mean.
    For every extra number you prepend to the start of $x, you get an extra "0" at the end of $y:
    use strict; use warnings; use feature 'say'; use bignum;#num; # (1) #use bignum downgrade => "Math::BigInt", upgrade => "Math::BigI +nt"; ## (2) #use bigint; say $^V; my $x = 999999999921778071482940061661655974875633165533182; say $x; my $y = $x / 2; say $y; __END__ For me, outputs: D:\pscrpt>perl try.pl v5.39.5 999999999921778071482940061661655974875633165533182 499999999960889035741470030830827987437800000000000
    Cheers,
    Rob

      Thanks, looks like it's fallback (so called "div_scale", defaults to 40) value that was applied (and now I have a deja-vu to have already investigated this a few years back). Either of

      use bignum p => 0; bignum-> precision( 0 ); bignum-> div_scale( 999 );

      (or method calls on an instance) will help. That still doesn't feel right:

      use strict; use warnings; use feature 'say'; use Data::Dump; use bignum; #use bigint; say my $x = 999999999921778071482940061661655974875633165533182; dd $x; dd $x-> precision; dd $x-> accuracy; dd $x-> div_scale; dd (Math::BigInt-> precision); dd (Math::BigInt-> accuracy); say my $y = $x / 1; __END__ 999999999921778071482940061661655974875633165533182 bless({ sign => "+", value => bless([165533182, 974875633, 61661655, 71482940, 999921778, + 999999], "Math::BigInt::Calc"), }, "Math::BigInt") undef undef 40 undef undef 999999999921778071482940061661655974875600000000000

      But with bigint instead:

      999999999921778071482940061661655974875633165533182 bless({ sign => "+", value => bless([165533182, 974875633, 61661655, 71482940, 999921778, + 999999], "Math::BigInt::Calc"), }, "Math::BigInt") undef undef 40 undef undef 999999999921778071482940061661655974875633165533182

      i.e. object of the same class, with the same properties, same global parameters, but result is different. Same (per deja-vu) conclusion: avoid using bignum.

        ... avoid using bignum.

        That's the rule that I live by.

        To be fair, however, bignum is quite possibly easier to use than I think.
        One just has to be aware of all the caveats ;-)

        UPDATE:
        i.e. object of the same class, with the same properties, same global parameters, but result is different.

        I think the difference occurs because the "bignum" division is done by Math::BigFloat::bdiv, whereas the "bigint" division is done by Math::BigInt::bdiv.

        Cheers,
        Rob