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

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

I must be using bignum incorrectly, as I would have thought I would end up with 5 and 7 on the bottom 2 lines.

0.5833333333333333333333333333333333333333
5833333333333333333333333333333333333333
10000000000000000000000000000000000000000

```
use Math::BigRat;
use bignum;

my \$cf = 1 - 1/6 - 1/4; ## \$cf = 7/12
+         \

+
my \$n = \$cf->numerator();
my \$d = \$cf->denominator();

print "\$cf\n";
print "  \$n\n";
print " \$d\n";

Replies are listed 'Best First'.
Re: bignum usage?
by kcott (Archbishop) on Oct 15, 2023 at 05:04 UTC

G'day rkd257,

Welcome to the Monastery.

"... thought I would end up with 5 and 7 ... ## \$cf = 7/12 ..."

So, I think you should have been expecting 7 and 12. If not, please explain why 5 and 7?

Anyway, I think you want bigrat; not Math::BigRat and bignum. (All three are core modules.)

```\$ perl -e '
use bigrat;

my \$cf = 1 - 1/6 - 1/4;
my \$n = \$cf->numerator();
my \$d = \$cf->denominator();

print "\$cf\n";
print "  \$n\n";
print " \$d\n";
'
7/12
7
12

— Ken

Re: bignum usage?
by ikegami (Patriarch) on Oct 17, 2023 at 19:21 UTC

Replace

```use Math::BigRat;  # Useless
use bignum;        # Uses M::BigInt and M::BitFloat

with

```use bignum upgrade => "Math::BigRat";
or
```use bigrat;

I don't think they're equivalent -- the former initially creates M::BigInt objects and switches to M::BigRat when necessary, but I think the latter uses M::BitRat objects from the start -- but they have the same result here.

Re: bignum usage?
by Anonymous Monk on Nov 23, 2023 at 21:18 UTC

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;
+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

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;
+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

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