用PHP计算机器ε的最佳方法?
在PHP中直接计算机器epsilon(浮点舍入误差)的最佳/最正确方法是什么,而不是使用内置常量用PHP计算机器ε的最佳方法?,php,precision,floating-accuracy,epsilon,Php,Precision,Floating Accuracy,Epsilon,在PHP中直接计算机器epsilon(浮点舍入误差)的最佳/最正确方法是什么,而不是使用内置常量PHP\u FLOAT\u epsilon?目前,我研究了两种方法,“标准”和渐近逼近ε: // Standard way $x=1.0; $dx=2.0; while (($x/=$dx)+1.0!=1.0); echo "EPSILON : $x".", DEFINED/CALC : ".round(PHP_FLO
PHP\u FLOAT\u epsilon
?目前,我研究了两种方法,“标准”和渐近逼近ε:
// Standard way
$x=1.0;
$dx=2.0;
while (($x/=$dx)+1.0!=1.0);
echo "EPSILON : $x".", DEFINED/CALC : ".round(PHP_FLOAT_EPSILON/$x)."x\n";
// Asymptotically approaching
$x=1.0;
$dx=2.0;
while (($x/=$dx)+1.0!=1.0) $dx/=1.0+10**-5;
echo "EPSILON : $x".", DEFINED/CALC : ".round(PHP_FLOAT_EPSILON/$x)."x\n";
问题是,他们给出的答案有不同的错误:
ε:1.1102230246252E-16,已定义/计算:2x
EPSILON:5.6311222663283E-17,已定义/计算:4x
所以标准给出ε=1/2ε0,其他算法给出ε=1/4ε0。我不确定epsilon应该如何正确计算。多亏了@EricPostpischil,导致错误的主要原因是打印x的第一个值
x+1=1
,而不是打印x的最后一个值x+1>≠1
。固定代码:
// Standard way
$x=1.0;
$dx=2.0;
while (true) {
$px = $x;
$x/=$dx;
if ($x+1.0==1.0)
break;
}
printf ("ε = $x ≈ %.1f ε₀ \n", $px/PHP_FLOAT_EPSILON);
// Asymptotically approaching
$x=1.0;
$dx=2.0;
while (true) {
$px = $x;
$x/=$dx;
$dx/=1.0+10**-5;
if ($x+1.0==1.0)
break;
}
printf ("ε = $x ≈ %.1f ε₀ \n", $px/PHP_FLOAT_EPSILON);
报告=>
ε=1.1102230246252E-16≈ 1.0 ε₀ε=5.6311222663283E-17≈ 0.5 ε₀
现在已经足够好了,因为第一个标准案例报告的epsilon与PHP文档中的epsilon相同。至于第二个algo,它可能是由于舍入问题,可以有一些不同的解释。也就是说,如果±ε使您进入下一个可表示的浮点数,则表示误差为半ε,因为任何大于| 0.5ε的变化₀| 将四舍五入到下一个可表示的数字。这就像物理学家计算测量误差一样。假设你有一把最小测量单位为1毫米的尺子。然后,在当前读数上加上±0.5 mm,四舍五入将获得标尺上的下一个可表示读数。因此,有些人说实际测量误差是0.5毫米,有些人说是1毫米,这取决于定义。这里也一样。最好在堆栈站点上询问这个问题,可能是,也可能不是。它还可能取决于浮点格式的语言实现。在任何情况下,不仅仅是数学浮点格式的实现是计算机的东西。@RiggsFolly:不,这里涉及的问题是计算问题。特别是,舍入导致
($x/=$dx)+1.0
不等于1.0
,即使($x/=$dx)
小于“机器ε”(但超过一半)。这是一个计算问题,而不是一个纯粹的数学问题。如果你看到“机器ε”的定义是1+x
不等于1
的最小值x,那是不正确的。“机器ε”的正确定义是,它是1和下一个可表示数字之间的差。这叫美国。所以1和1+e是可表示的数字。假设x是(½u,u)中的某个数字。然后,当计算1+x
时,结果为1+u,因为它被四舍五入,实际算术结果介于1和1+u之间,这是两个最接近的可表示值。因为它更接近1+u,所以四舍五入到1+u,这就是为什么第一个定义是错误的。第二,循环终止后,代码显示$x
的值,这意味着它显示两个表达式相等的$x
的第一个值,而不是显示两个表达式不相等的$x
的最后一个值。