2013-02-13 117 views
4

据我所知,浮点类型的值必须仔细比较以避免固有浮点错误的问题。通过比较值和错误阈值可以改善这一点。比较float和double值与delta吗?

例如,下面的解决方案比一个简单的测试x == y更多的可用:

static float CompareRelativeError(float x, float y) { 
    return Math.Abs(x - y)/Math.Max(Math.Abs(x), Math.Abs(y)); 
} 
static bool CompareAlmostEqual(float x, float y, float delta) { 
    return x == y || CompareRelativeError(x, y) < delta; 
} 

// apologies if this is a poor example 
if (CompareAlmostEqual(1f/10f, 0.1f)) { ... } 

将上述溶液从下面的资源衍生的: Is it safe when compare 2 float/double directly in Java?

虽然我还没有能找到任何文学来证实这一点,对我来说,似乎相同必须适用于比较,如x > y。例如,如果xy基本上是相等的,怎么能一个比其他更大...

static bool CompareGreater(float x, float y, float delta) { 
    return x > y && !CompareAlmostEqual(x, y, delta); 
} 

因此建立了下面将为x >= y是有效的:

static bool CompareGreaterOrEqual(float x, float y) { 
    return x >= y; 
} 

是我的假设是否正确?

+0

可能重复[Doub le.Epsilon for equal,大于,小于,小于或等于,大于或等于](http://stackoverflow.com/questions/2411392/double-epsilon-for-equality-greater-thanless - 小于或等于gre) – 2013-02-13 01:02:27

回答

4

等式测试正是delta(或epsilon)技术用于浮点值的原因。

例如我们希望3等于2.999999 ...以某种精度。

static bool CompareGreaterOrEqual(float x, float y) { 
    return x >= y; 
} 

它应该是::

因此,当定义为您的CompareGreaterOrEqual方法是不够的

static bool CompareGreaterOrEqual(float x, float y, float delta) { 
    return x >= y || CompareAlmostEqual(x, y, delta); 
} 

注:x >= y在第一次测试可能只是x > y因为增量比较需要的护理等于:

static bool CompareGreaterOrEqual(float x, float y, float delta) { 
    return x > y || CompareAlmostEqual(x, y, delta); 
} 
+0

非常感谢你们的帮助!这是一个写得很好的答案,我现在明白为什么'CompareAlmostEqual'在这里也需要。 – 2013-02-13 01:07:49

2

既然我们已经同意在这种情况下运营商=是通过CompareAlmostEqual完成的,那么在CompareGreaterOrEqual中使用它也是有意义的。

static bool CompareGreaterOrEqual(float x, float y, float delta) { 
    return x >= y || CompareAlmostEqual(x, y, delta); 
} 

此外,虽然它在很大程度上取决于你将如何使用这些功能的,我也会使delta是整个类使用的常数变量,以确保使用相同的值(而不是周围将它作为一个参数)。

+0

+1。击败我! ;) – 2013-02-13 01:04:18

+1

@MitchWheat - 实际上根据我们的回答来看时间,我相信*你*是胜利者,先生! – 2013-02-13 01:05:46