I know this is ancient history now but...
Use of Math::BigFloat without very carefully reading the documentation is considered harmful
There is an old problem with the code and a new one.
The old problem is that nothing is passed to Math::BigFloat to tell it how precise we want our answers. By default, Math::BigFloat->new("2.0")->fsqrt will return only 40 digits; see the discussion of div_scale in Math::BigFloat. This accounts for the problem that metadoktor noted. By setting the precision to -10000 I was able to calculate pi to 10,000 digits, and according to the Joy of Pi site, it is correct. (It took about 40 minutes on a fast Xeon.)
The new problem is that every use of fsqrt needs to be changed from $x->fsqrt to ($x+0)->fsqrt. Apparently there has been a change to fsqrt in the last several years that causes $y = $x->fsqrt to change $x as well as $y to the square root of $x's original value. Most likely it is the change mentioned for bpow near the end of the Math::BigFloat documentation. Without the workaround the program converges quickly to 3.2693255..., which is high by over four percent... worse than slide rule accuracy.
The revised code, set to ten thousand digits, is:
#!/usr/bin/perl -w
use strict;
use warnings;
use constant ITERS => 13;
use Math::BigFloat;
Math::BigFloat->precision(-10000);
my $x = Math::BigFloat->new("2.0")->fsqrt;
my $p = $x + 2;
my $y = ($x+0)->fsqrt;
for(1 .. ITERS) {
my $xroot = ($x+0)->fsqrt;
$x = ($xroot + 1/$xroot)/2;
$xroot = ($x+0)->fsqrt;
$p = $p * (($x + 1)/($y + 1));
$y = (($y * $xroot) + (1/$xroot))/($y + 1);
print "Iter $_ $p\n\n";
}
|