假设我想检查两个数字a
和b
是否相等。由于浮点不精确,我知道不是简单地检查a == b
,而是通常想要选择一些小号eps
,而是检查abs(a - b) < eps
。
但是,如果我想在检查a > b
时考虑浮点错误,该怎么办?我猜这不是简单的
if (a > b) {
...
}
我想做类似的事情:
if ((a > b) || abs(a - b) < eps) {
...
}
这是对的吗?如何检查a
是否“大于”b
?
答案 0 :(得分:2)
您正在询问如何从错误输入(某些值中包含错误的值)计算正确的结果(一个值是否大于另一个值)。显然,这通常是不可能的:错误的输入会产生错误的输出。但是,在某些特定情况下,我们可以挽救一些东西。以下讨论一种情况。
假设您计算了一些a
和b
近似理想值 a 和 b ,其中 a 和 b 是使用精确数学进行计算时的结果。还假设我们知道错误界限 e a 和 e b ,以便 a - e a ≤a
≤ a + e a 和 a - e b ≤b
≤ b + e b < /子> 的。换句话说,计算出的a
和b
分别位于 a 和 b 周围的某些区间内。 (根据所执行的操作,错误可能会导致a
或b
处于某些未连接的间隔,甚至可能不包含 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-b > e
,对于位于 - e e > a - e b 和+ e a + e b ,包括在内。如果您找不到令人满意的折衷方案,那么您需要改进a
和b
的计算以减少错误,或者您需要以某种方式重新设计您的程序。
注意:此方案中的最终测试为a-b > e
而非a > b+e
,因为计算b+e
时可能会出现小的舍入误差。计算a-b
时可能还存在舍入误差,但仅当a
和b
彼此不相近时,在这种情况下,即使使用舍入,差异也远大于{{ 1}}(除非你的错误间隔很恶劣)。在我们关心精确度的情况下,当e
靠近a
时,b
的计算是准确的。