2012-12-08 24 views
0

假设我想检查两个数字ab是否相等。由于浮点不精确,我知道不是简单地检查a == b,我通常要挑选一些小号码eps,而不是检查abs(a - b) < eps测试时浮点不精确性的帐户“大约大于”

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

if (a > b) { 
    ... 
} 

我想要做的事,如:

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

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

+1

“我知道,而不是简单地检查== B,我通常要挑一些少量的每股收益”你应该知道的是,你要了解你的程序的逻辑,并利用这些知识来选择一个合适的ε- ,**如果有需要的话**。相同的理解会导致你对'a> b'做出正确的决定。没有为'一== B'没有通用的解决方案(您可以投诉给谁就给谁告诉你有),并有对'一> B'没有通用的解决方案。 –

+0

这是不可能回答这样的问题,不知道更多的应用程序。例如,用'如果(A> B - EPS)',这相当于你的第二个'if'声明,你会得到一些误报。如果没有进一步的信息,那么这些误报是否适用于您的特定应用是无法衡量的。 –

+0

使用'epsilon'可能不够,因为正确选择epsilon取决于所涉及的相对大小。深入研究这些问题绝对值得。 [Goldberg的论文](http://www.validlab.com/goldberg/paper.pdf)是一个经典的,重要的理论。还有一系列的文章[这里](http://randomascii.wordpress.com/category/floating-point/)。 –

回答

2

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

让我们假设你已经计算出了一些ab近似于理想值一个b,其中一个b是,如果计算是用精确的数学做,你将有结果。另外,假定我们知道误差范围Ë一个Ë b这样一个 - Ë一个a一个 + Ë一个一个 - e bbb + e b。换句话说,计算出的ab分别位于ab附近的一些区间内。 (根据所执行的操作,有可能是错误可能导致ab趴在一些无关的间隔,甚至可能不包含一个b。但我们会假设你已经“表现良好”的错误。)

在这种情况下,如果a - Ë一个>b + è b,那么可以肯定的是一个>b

但是,假设您测试此条件并返回true(如果它成立)。然后,只要这返回true,您将知道a>b。但是,当它返回false时,您将无法确定a>b是否为假。所以,如果你想执行一些动作只有当你一定一个>b这个测试是好的。但是这会导致您错过在某些情况下执行此操作时a>b

假设您不想错过任何这些情况。再考虑条件a + Ë一个>b - Ë b。如果a>b,则该条件必须为真。因此,如果您测试此条件并在其执行时执行所需操作,则执行总是时将执行a>b。但是,如果不是这样的话,也可以执行一些操作a>b

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

  • 它是如何接受的是应用程序执行的操作,当它是假的是一个>b。它总是可接受/不可接受的,还是取决于如何接近ab
  • 对于您的应用程序而言,如果它确实无法执行该操作,那么该接受程度如何?a>b。它总是可接受/不可接受的,还是取决于如何接近ab

如果你能找到一些令人满意的妥协,那么你设置你的病情一些中等水平,和你测试的条件a-b > e,对于一些e是介于 - Ë一个 - Ë b和+ Ë一个 + è b,包括端值。如果您找不到令人满意的折中方案,那么您需要改进ab的计算以减少错误,或者您需要以某种方式重新设计您的程序。

注意:在这种情况下的最终测试是a-b > e而不是a > b+e,因为可能会有一个小的舍入误差计算b+e。还可以有一个舍入误差计算a-b,但仅当ab并不彼此靠近,在这种情况下的差,即使有舍入,比e大得多(除非你的错误间隔是恶劣)。在我们所关心的精确度,当a靠近b的情况下,a-b计算是准确的。