在PHP中计算机器epsilon的最佳方法?

Best way to calculate machine epsilon in PHP?

提问人:Agnius Vasiliauskas 提问时间:10/20/2020 更新时间:10/21/2020 访问量:451

问:

在PHP中直接计算机器epsilon(浮点舍入误差)的最佳/最正确的方法是什么,而不使用内置常量?目前,我已经设法研究了两种方式,“标准”和渐近接近 epsilon :PHP_FLOAT_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。

php 浮动精度 epsilon

评论

0赞 RiggsFolly 10/20/2020
最好在另一个堆栈站点上问这个问题,也许 math.stackexchange.com
0赞 Agnius Vasiliauskas 10/20/2020
也许,也许不是。它还可能取决于浮点格式的语言实现。无论如何,这不仅仅是数学浮点格式实现是计算机的东西。
0赞 Eric Postpischil 10/20/2020
@RiggsFolly:不,这里涉及的问题是计算问题。特别是,舍入会导致不相等,即使小于“机器 epsilon”(但高于它的一半)。这是一个计算问题,而不是一个纯粹的数学问题。($x/=$dx)+1.01.0($x/=$dx)
0赞 Eric Postpischil 10/20/2020
如果您看到“机器 epsilon”的定义是最小值 x,其值不等于 ,这是不正确的。“机器 epsilon”的正确定义是它是 1 和下一个可表示数字之间的差。称这个 u 为。所以 1 和 1+e 是可表示的数字。假设 x 是 (1/2u, u) 中的某个数字。然后,计算时,结果是 1+u,因为它是四舍五入的 - 实际算术结果介于 1 和 1+u 之间,这是两个最接近的可表示值。由于它更接近 1+u,因此四舍五入为 1+u。1+x11+x
1赞 Eric Postpischil 10/20/2020
所以,这就是为什么第一个定义是错误的。第二种情况是,您的代码在循环终止显示 的值,这意味着它显示两个表达式相等的第一个值,而不是显示两个表达式不相等的最后一个值。$x$x$x

答:

0赞 Agnius Vasiliauskas 10/21/2020 #1

多亏了@EricPostpischil,错误的主要原因是打印了 x 的第一个值,而不是我应该打印 x 的最后一个值。固定代码:x+1=1x+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
ε₀

现在已经足够好了,因为第一个 -standard case- 报告 epsilon 与 PHP 文档中的相同。至于第二个算法,可能是由于舍入问题,可以有不同的解释。也就是说,如果 ±ε 让你得到下一个可表示的浮点数,那么表示误差是 epsilon 的一半,因为任何大于 |0.5 ε₀|将四舍五入到下一个可代表的数字。这类似于物理学家计算测量误差。假设您有一把最小测量单位为 1 毫米的尺子。然后将 ±0.5 毫米添加到当前读数和四舍五入将使您进入标尺上的下一个可表示读数。因此,有人说实际测量误差是 0.5 毫米,有人说是 1 毫米,这取决于定义。同样在这里。