将浮点值和双精度值与delta进行比较

本文关键字:delta 比较 双精度 | 更新日期: 2023-09-27 17:59:04

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

例如,以下解决方案比直接的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浮点/双精度是否安全?

虽然我还没有找到任何文献来证实这一点,但对我来说,像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;
}

我的假设正确吗?

将浮点值和双精度值与delta进行比较

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

例如,我们希望3在某种精度上等于2.9999999。

因此,当定义为:时,您的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);
}

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

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

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