Search code examples
phpprecisionpi

Different values of pi?


ini_set('precision', 64);    
echo M_PI."<br>";
echo pi()."<br>";
echo "3.14159265358979323846264338327950<br>";

For reference I've used http://www.eveandersson.com/pi/digits/100

If you compare the output you get the following:

3.1415926535898
3.141592653589793115997963468544185161590576171875
3.14159265358979323846264338327950

So what's with the precision value of pi()? It seems its totally off. Yes, I know pi is irrational, but at least to 100 significant digits it should be accurate?

Can anyone confirm this problem, and is it possible to explain why after 16 digits it goes wrong in php?


Solution

  • In the bcmath extensions manual page the following is presented:

    //bcpi function with Gauss-Legendre algorithm
    //by Chao Xu (Mgccl)
    
    function bcpi($precision){
      $n=0;
        $limit = ceil(log($precision)/log(2))-1;
        bcscale($precision+6);
        $a = 1;
        $b = bcdiv(1,bcsqrt(2));
        $t = 1/4;
        $p = 1;
        while($n < $limit){
            $x = bcdiv(bcadd($a,$b),2);
            $y = bcsqrt(bcmul($a, $b));
            $t = bcsub($t, bcmul($p,bcpow(bcsub($a,$x),2)));
            $a = $x;
            $b = $y;
            $p = bcmul(2,$p);
            ++$n;
        }
        return bcdiv(bcpow(bcadd($a, $b),2),bcmul(4,$t),$precision);
    }
    
    echo bcpi(64);
    echo "<br>3.1415926535897932384626433832795028841971693993751058209749445923";
    

    It seems therefore, that ini_set('precision',64); doesn't do anything constructive for the regular php math functions (>15), but bcmath extension ignores the setting entirely.

    So to work in precision >= 16 use bcmath extension otherwise ini_set works up to 15

    And @Progman's answer that float/double storing rules still apply - means that there is a cap on 15 decimal points (even though php stores all floats as double)