10
perl -Mbigrat -E'for (1..100) { $i += 1/3; say int($i), "\t", sprintf "%.55f", $i }'

spams a lot of warnings:

Argument "100/3" isn't numeric in addition (+) at …/site_perl/5.24.1/Math/BigRat.pm line 1939.

Run again without -Mbigrat to see the desired effect of sprintf.

How do you downgrade the Math::BigRat instance $i into an ordinary NV delectable to sprintf?

Versions:

  • bigrat 0.47
  • Math::BigRat 0.2612
Daniel Böhmer
  • 14,463
  • 5
  • 36
  • 46
daxim
  • 39,270
  • 4
  • 65
  • 132
  • FWIW bigrat @ 0.39 and Math::BigRat at 0.2608 do not have this warning. Upgrading bigrat to 0.47, which brings in Math-BigInt-1.999811, does have a warning, but it's `Use of uninitialized value in string eq at .../5.22.2/Math/BigFloat.pm line 3626.` Manually updating Math::BigRat gives me your warning. – Schwern May 26 '17 at 23:36
  • Have you reported this problem yet? – ikegami Jun 03 '17 at 04:30

2 Answers2

1

I expected Math::BigRat to provide a method for getting a plain number and it does:

  • as_int for integers
  • as_float for floats

I inserted printing of $_ for debugging purposes.

$i->as_int() does the same as int($i):

$ perl -Mbigrat -E'for (1..100) { $i += 1/3; say $_, "\t", int($i), "\t", sprintf "%.55f", $i->as_int() }'
...
99      33      33.0000000000000000000000000000000000000000000000000000000
100     33      33.0000000000000000000000000000000000000000000000000000000

$i->as_float() seemed to work as expected on first sight but I don’t understand the output. All decimal places are zero and for every second line $i equals $_:

$ perl -Mbigrat -E'for (1..100) { $i += 1/3; say $_, "\t", int($i), "\t", sprintf "%.55f", $i->as_float() }'
...
90      30      30.0000000000000000000000000000000000000000000000000000000
91      30      91.0000000000000000000000000000000000000000000000000000000
92      30      92.0000000000000000000000000000000000000000000000000000000
93      31      31.0000000000000000000000000000000000000000000000000000000
94      31      94.0000000000000000000000000000000000000000000000000000000
95      31      95.0000000000000000000000000000000000000000000000000000000
96      32      32.0000000000000000000000000000000000000000000000000000000
97      32      97.0000000000000000000000000000000000000000000000000000000
98      32      98.0000000000000000000000000000000000000000000000000000000
99      33      33.0000000000000000000000000000000000000000000000000000000
100     33      100.0000000000000000000000000000000000000000000000000000000

This is Perl 5.30.0 with Math::BigRat 0.2614.

So the warnings are fixed but there seems to be something wrong with this solution.

Update: As requested in the comments without sprintf:

$ perl -Mbigrat -E'for (1..100) { $i += 1/3; say $_, "\t", int($i), "\t", $i->as_float() }'
...
90      30      30
91      30      91
92      30      92
93      31      31
94      31      94
95      31      95
96      32      32
97      32      97
98      32      98
99      33      33
100     33      100
Daniel Böhmer
  • 14,463
  • 5
  • 36
  • 46
  • What if you leave out the sprintf and print `as_float` directly? It looks like what you're getting is the numerator of the fraction in reduced form, rather than the proper numeric value. – hobbs Aug 29 '19 at 01:21
0

Not that serious of an answer:

use bigrat;
use feature 'say';
for (1..100) {
    $i += 1/3;
    no bigrat;
    say int($i),"\t",sprintf "%.55f", eval "$i"
}
mob
  • 117,087
  • 18
  • 149
  • 283