在 PHP 中计算机器 epsilon 的最佳方法?
Best way to calculate machine epsilon in PHP?
直接计算 PHP 中的机器 epsilon(浮点舍入误差)的最佳/最正确方法是什么,而不是使用内置常数 PHP_FLOAT_EPSILON
?目前,我设法研究了两种方法,“标准”和渐近接近 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";
问题是,他们给出的答案有不同的错误:
EPSILON : 1.1102230246252E-16, DEFINED/CALC : 2x
EPSILON : 5.6311222663283E-17, DEFINED/CALC : 4x
所以标准给出 ε = 1/2ε0 而其他算法给出 ε = 1/4ε0。我不确定应该如何正确计算 epsilon。
感谢@EricPostpischil,错误的主要原因是打印了 x+1=1
的 x 的第一个值,而不是我应该打印 x+1≠1
的 x 的最后一个值。固定码:
// 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 documentation.As 中关于第二个算法的相同,这可能是由于四舍五入问题并且可以稍微不同地解释. IE。如果 ±ε 将您带到下一个 可表示的 浮点数,则表示误差为半 epsilon,因为任何大于 |0.5 ε₀| 的变化将四舍五入到下一个可表示的数字。这类似于物理学家计算测量误差。假设您有一把最小测量单位为 1 毫米的尺子。然后将 ±0.5 毫米添加到当前读数和四舍五入将使您获得标尺上的下一个可表示读数。因此有人说实际测量误差是 0.5 毫米,有人说是 1 毫米,这取决于定义。这里也一样。
直接计算 PHP 中的机器 epsilon(浮点舍入误差)的最佳/最正确方法是什么,而不是使用内置常数 PHP_FLOAT_EPSILON
?目前,我设法研究了两种方法,“标准”和渐近接近 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";
问题是,他们给出的答案有不同的错误:
EPSILON : 1.1102230246252E-16, DEFINED/CALC : 2x
EPSILON : 5.6311222663283E-17, DEFINED/CALC : 4x
所以标准给出 ε = 1/2ε0 而其他算法给出 ε = 1/4ε0。我不确定应该如何正确计算 epsilon。
感谢@EricPostpischil,错误的主要原因是打印了 x+1=1
的 x 的第一个值,而不是我应该打印 x+1≠1
的 x 的最后一个值。固定码:
// 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 documentation.As 中关于第二个算法的相同,这可能是由于四舍五入问题并且可以稍微不同地解释. IE。如果 ±ε 将您带到下一个 可表示的 浮点数,则表示误差为半 epsilon,因为任何大于 |0.5 ε₀| 的变化将四舍五入到下一个可表示的数字。这类似于物理学家计算测量误差。假设您有一把最小测量单位为 1 毫米的尺子。然后将 ±0.5 毫米添加到当前读数和四舍五入将使您获得标尺上的下一个可表示读数。因此有人说实际测量误差是 0.5 毫米,有人说是 1 毫米,这取决于定义。这里也一样。