假设我想检查两个数字a
和b
是否相等。由于浮点数不精确,我知道不是简单地检查a == b
,我通常想选择一些小数字eps
并检查abs(a - b) < eps
。
但是,如果我想在检查时考虑浮点错误该a > b
怎么办?我猜这不是简单的
if (a > b) {
...
}
我想做类似的事情:
if ((a > b) || abs(a - b) < eps) {
...
}
它是否正确?如何检查a
“大约大于” b
?
假设我想检查两个数字a
和b
是否相等。由于浮点数不精确,我知道不是简单地检查a == b
,我通常想选择一些小数字eps
并检查abs(a - b) < eps
。
但是,如果我想在检查时考虑浮点错误该a > b
怎么办?我猜这不是简单的
if (a > b) {
...
}
我想做类似的事情:
if ((a > b) || abs(a - b) < eps) {
...
}
它是否正确?如何检查a
“大约大于” b
?
您正在询问如何从不正确的输入(某些值中有错误)计算正确的结果(一个值是否大于另一个值)。显然,这通常是不可能的:不正确的输入会产生不正确的输出。但是,在某些特定情况下,我们可以挽救一些东西。下面讨论一种情况。
假设您已经计算了一些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。但我们会假设您有“表现良好”的错误。)
在这种情况下,如果a
– e a > b
+ e b,那么您可以确定a > b。
但是,假设您测试此条件并true
在它成立时返回。然后,无论何时返回true
,您都会知道a > b。但是,当它返回时false
,您将无法确定a > b是否为假。因此,如果您仅在确定a > b时才想执行某些操作,则此测试很好。但这会导致您在某些情况下错过执行操作a > b。
假设您不想错过任何这些情况。然后考虑条件a
+ e a > b
– e b。如果a > b,则此条件必须为真。因此,如果您测试此条件并在它成立时执行所需的操作,那么该操作将始终在a > b时执行。但是,当a > b不正确时,也可能会执行该操作。
这表明您可以做出选择。如果您的计算中有错误,有时您的应用程序会做错事。您必须选择:
如果您能找到一些令人满意的折衷方案,那么您可以将您的条件设置为某个中间水平,并测试条件a-b > e
,对于介于 – e a – e b和 + e a + e be
之间的一些条件,包括在内。如果找不到令人满意的折衷方案,则需要改进计算并减少错误,或者需要以某种方式重新设计程序。a
b
注意:这个场景中的最终测试a-b > e
不是a > b+e
因为计算可能存在小的舍入误差b+e
。也可能有一个舍入误差计算a-b
,但只有当a
和b
不接近时,在这种情况下,即使舍入,差异也远大于e
(除非你的错误间隔很糟糕)。在我们关心精度的情况下,当a
接近时b
,计算a-b
是精确的。