在测试“大于”时考虑浮点不精确

时间:2012-12-08 05:42:30

标签: floating-point

假设我想检查两个数字ab是否相等。由于浮点不精确,我知道不是简单地检查a == b,而是通常想要选择一些小号eps,而是检查abs(a - b) < eps

但是,如果我想在检查a > b时考虑浮点错误,该怎么办?我猜这不是简单的

if (a > b) {
  ...
}

我想做类似的事情:

if ((a > b) || abs(a - b) < eps) {
  ...
}

这是对的吗?如何检查a是否“大于”b

1 个答案:

答案 0 :(得分:2)

您正在询问如何从错误输入(某些值中包含错误的值)计算正确的结果(一个值是否大于另一个值)。显然,这通常是不可能的:错误的输入会产生错误的输出。但是,在某些特定情况下,我们可以挽救一些东西。以下讨论一种情况。

假设您计算了一些ab近似理想值 a b ,其中 a b 是使用精确数学进行计算时的结果。还假设我们知道错误界限 e a e b ,以便 a - e a a a + e a a - e b b b + e b < /子> 的。换句话说,计算出的ab分别位于 a b 周围的某些区间内。 (根据所执行的操作,错误可能会导致ab处于某些未连接的间隔,甚至可能不包含 a b < / em>。但我们会假设你有“表现良好”的错误。)

在这种情况下,如果a - e a &gt; b + e b ,然后您可以确定 a &gt; B'/ em>的

但是,假设您测试此条件并返回true(如果有)。然后,只要返回true,您就会知道 a &gt; B'/ em>的。但是,当它返回false时,您将无法确定 a &gt; b 是假的。因此,如果您希望在某些 a &gt;时执行某些操作 ,则此测试很有用。 B'/ em>的。但是,这会导致您在某些情况下错过执行操作 a &gt; B'/ em>的

假设您不想错过任何这些案例。然后考虑条件a + e a &gt; b - e b 。如果 a &gt; b ,那么这个条件必须为真。因此,如果您测试此条件并在其保持时执行所需操作,则 a &gt;时将执行始终操作。 B'/ em>的。但是,当 a &gt;不正确时,也可能会执行某些操作。 B'/ em>的

这表明您可以做出选择。如果计算中有错误,有时您的应用程序会做错误的事情。你必须选择:

  • a &gt;错误时,您的应用程序执行操作的可接受程度如何 B'/ em>的。它总是可接受/不可接受,还是取决于 b 的接近程度?
  • 如果 a &gt;属于您的应用程序不执行操作的可接受程度 B'/ em>的。它总是可接受/不可接受,还是取决于 b 的接近程度?

如果您能找到一些令人满意的折衷方案,那么您可以将条件设​​置为某个中间级别,并测试条件a-b > e,对于位于 - e e > a - e b 和+ e a + e b ,包括在内。如果您找不到令人满意的折衷方案,那么您需要改进ab的计算以减少错误,或者您需要以某种方式重新设计您的程序。

注意:此方案中的最终测试为a-b > e而非a > b+e,因为计算b+e时可能会出现小的舍入误差。计算a-b时可能还存在舍入误差,但仅当ab彼此不相近时,在这种情况下,即使使用舍入,差异也远大于{{ 1}}(除非你的错误间隔很恶劣)。在我们关心精确度的情况下,当e靠近a时,b的计算是准确的。