将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)) { ... }
上面的解决方案来自以下资源: 在Java中直接比较2 float / double时是否安全?
虽然我还没有找到任何文献来证实这一点,但对我来说似乎也必须适用于像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.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); }
由于我们已经同意operator =
在这种情况下是通过CompareAlmostEqual
完成的,因此在CompareGreaterOrEqual
使用它也是有意义的。
static bool CompareGreaterOrEqual(float x, float y, float delta) { return x >= y || CompareAlmostEqual(x, y, delta); }
此外,虽然它在很大程度上取决于你如何利用这些函数,但我还要使delta
成为整个类中使用的常量变量,以确保使用相同的值(而不是将其作为参数传递)。