将浮点值和双精度值与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
这样的比较似乎也是如此。例如,如果x
和y
本质上相等,怎么可能一个大于另一个。。。
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(或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
作为一个常量变量,在整个类中使用,以确保使用相同的值(而不是将其作为参数传递)。