Pie*_*ard 3 java double ieee-754
为什么这些简单的双重比较会返回真实?
System.out.println(Double.MAX_VALUE == (Double.MAX_VALUE - 99 * Math.pow(10, 290)));
System.out.println(new Double(Double.MAX_VALUE).equals(new Double(Double.MAX_VALUE - 99 * Math.pow(10, 290))));
Run Code Online (Sandbox Code Playgroud)
我知道这可能是一个IEEE 754精确问题,但我无法弄清楚究竟是什么问题.
非常大的浮点数非常不精确.你所看到的是四舍五入错误.
我们可以证明基数为10(科学记数法)的浮点数,比如指数的1位数和基数的4位数:
1234*10^1 == 1234
1234*10^-1 == 123.4
1234*10^9 == 1,234,000,000,000
1235*10^9 == 1,235,000,000,000
Run Code Online (Sandbox Code Playgroud)
它遵循:
1234*10^9 - 1234*10^1 == 1234*10^9
Run Code Online (Sandbox Code Playgroud)
你可以看到随着数字变大,我们失去了精确度.很多.
对于踢球,你可以测试它:
double d = 10;
while(Double.MAX_VALUE - d == Double.MAX_VALUE)
d *= 10;
System.out.println(d);
Run Code Online (Sandbox Code Playgroud)
我们可以确定Double.MAX_VALUE和下一个最小值(称为ULP)之间的差距在某处10^292,这是一个非常大的差距.
我们可以借助以下方法确定其准确值Math#ulp:
long lng = Double.doubleToRawLongBits(Double.MAX_VALUE);
double nextMax = Double.longBitsToDouble(lng - 1);
System.out.println(Math.ulp(nextMax));
Run Code Online (Sandbox Code Playgroud)
这是关于1.99584*10^292,或2^971.