将float值和double值与delta进行比较?

时间:2013-02-13 00:51:11

标签: c# .net floating-point

据我所知,必须仔细比较浮点类型的值,以避免固有浮点错误的问题。这可以通过将值与错误阈值进行比较来改进。

例如,以下解决方案比直接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;
}

我的假设是否正确?

2 个答案:

答案 0 :(得分:4)

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

e.g。我们希望3等于2.999999 ...到某种精确度。

因此定义为:

时,CompareGreaterOrEqual方法不够用
static bool CompareGreaterOrEqual(float x, float y) {
    return x >= y;
}

应该是:

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

注意:第一次测试中的x >= y可能只是x > y,因为delta比较会处理相等:

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

答案 1 :(得分:2)

由于我们已经同意在这种情况下运算符=是通过CompareAlmostEqual完成的,因此在CompareGreaterOrEqual中使用它也是有意义的。

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

此外,虽然它在很大程度上取决于你如何利用这些函数,但我也会使delta成为整个类中使用的常量变量,以确保使用相同的值(而不是将其作为参数传递) )。