4

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

例如,以下解决方案比简单的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)) { ... }

上述解决方案源自以下资源: 在 Java 中直接比较 2 float/double 是否安全?

虽然我无法找到任何文献来证实这一点,但在我看来,对于像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;
}

我的假设正确吗?

4

2 回答 2

4

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

例如,我们希望 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);
}
于 2013-02-13T01:01:03.727 回答
2

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

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

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

于 2013-02-13T01:00:00.827 回答