不同的pi值?
Different values of pi?
ini_set('precision', 64);
echo M_PI."<br>";
echo pi()."<br>";
echo "3.14159265358979323846264338327950<br>";
作为参考,我使用了 http://www.eveandersson.com/pi/digits/100
如果比较输出,您会得到以下结果:
3.1415926535898
3.141592653589793115997963468544185161590576171875
3.14159265358979323846264338327950
那么pi()
的精度值是怎么回事呢?它似乎完全关闭了。是的,我知道 pi 是无理数,但至少要准确到 100 位有效数字?
任何人都可以确认这个问题,并且可以解释为什么在 php 中的 16 位后会出错吗?
"problem" 是 M_PI
的值(与 pi()
返回的值相同)是硬编码的。
来自 php_math.h
文件:
#ifndef M_PI
#define M_PI 3.14159265358979323846 /* pi */
#endif
更改精度不会更改已定义的常量值。此外,通常的 "how are float/double numbers are stored" 仍然适用。
在 bcmath 扩展手册页中介绍了以下内容:
//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";
因此,似乎 ini_set('precision',64);不会对常规 php 数学函数 (>15) 做任何有建设性的事情,但 bcmath 扩展会完全忽略该设置。
所以要精确工作 >= 16 使用 bcmath 扩展
否则 ini_set 最多 15
@Progman 的回答是 float/double 存储规则仍然适用 - 意味着小数点后 15 位有上限(即使 php 将所有浮点数存储为双精度数)
ini_set('precision', 64);
echo M_PI."<br>";
echo pi()."<br>";
echo "3.14159265358979323846264338327950<br>";
作为参考,我使用了 http://www.eveandersson.com/pi/digits/100
如果比较输出,您会得到以下结果:
3.1415926535898
3.141592653589793115997963468544185161590576171875
3.14159265358979323846264338327950
那么pi()
的精度值是怎么回事呢?它似乎完全关闭了。是的,我知道 pi 是无理数,但至少要准确到 100 位有效数字?
任何人都可以确认这个问题,并且可以解释为什么在 php 中的 16 位后会出错吗?
"problem" 是 M_PI
的值(与 pi()
返回的值相同)是硬编码的。
来自 php_math.h
文件:
#ifndef M_PI #define M_PI 3.14159265358979323846 /* pi */ #endif
更改精度不会更改已定义的常量值。此外,通常的 "how are float/double numbers are stored" 仍然适用。
在 bcmath 扩展手册页中介绍了以下内容:
//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";
因此,似乎 ini_set('precision',64);不会对常规 php 数学函数 (>15) 做任何有建设性的事情,但 bcmath 扩展会完全忽略该设置。
所以要精确工作 >= 16 使用 bcmath 扩展 否则 ini_set 最多 15
@Progman 的回答是 float/double 存储规则仍然适用 - 意味着小数点后 15 位有上限(即使 php 将所有浮点数存储为双精度数)