如果我使用这样的比较是安全的(a是int,b和c是float/double):
a == b
b == c
Run Code Online (Sandbox Code Playgroud)
它可能听起来很荒谬,但在我的旧编程语言中,有时1 + 2 == 3是假的(因为左侧返回2.99999999999 ......).那么,这个:
Math.sqrt(b) == Math.sqrt(c)
b / 3 == 10 / 3 //In case b = 10, does it return true?
Run Code Online (Sandbox Code Playgroud)
Ste*_*n C 12
一般而言,由于无法精确表示如此多的十进制数float或double值,因此不安全.如果数字之间的差异小于某个"小"值(通常用数学文献中的希腊'epsilon'字符表示),则经常说明的解决方案是测试.
但是 - 你需要小心谨慎地进行测试.例如,如果你写:
if (Math.abs(a - b) < 0.000001) {
System.err.println("equal");
}
Run Code Online (Sandbox Code Playgroud)
在哪里a和b应该是"相同",你正在测试绝对错误.如果你这样做,你可以进入,如果麻烦a和b是(say_ 1,999,999.99和2,000,000.00分别.这两个数字之间的差异小于最小表示值在这种规模的float,但它是比我们的选择小量大得多.
可以说,更好的方法是使用相对误差 ; 例如编码(防御性地)为
if (a == b ||
Math.abs(a - b) / Math.max(Math.abs(a), Math.abs(b)) < 0.000001) {
System.err.println("close enough to be equal");
}
Run Code Online (Sandbox Code Playgroud)
但即使这不是完整的答案,因为它没有考虑某些计算导致错误累积到无法管理的比例的方式.请查看此Wikipedia链接以获取更多详细信息.
最重要的是,处理浮点计算中的错误比初看起来要困难得多.
另一点需要注意的是(正如其他人所解释的)整数算法在几个方面与浮点算法的行为非常不同:
无论是在编译时还是在运行时,这两种情况都没有任何警告.
你需要做一些照顾.
1.0 + 2.0 == 3.0
Run Code Online (Sandbox Code Playgroud)
是真的,因为整数是完全可表示的.
Math.sqrt(b) == Math.sqrt(c)
Run Code Online (Sandbox Code Playgroud)
如果b == c.
b / 3.0 == 10.0 / 3.0
Run Code Online (Sandbox Code Playgroud)
如果b == 10.0这就是我认为你的意思.
最后两个示例比较了同一计算的两个不同实例.当您使用不可表示的数字进行不同的计算时,则完全相等测试失败.
如果您正在测试受浮点近似计算的结果,则应进行相等测试,直至达到公差.
你有任何具体的现实世界的例子吗?我想你会发现很少想用浮点测试相等性.
| 归档时间: |
|
| 查看次数: |
7973 次 |
| 最近记录: |