将Java Double.Max_VALUE与大双数进行比较,返回true

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精确问题,但我无法弄清楚究竟是什么问题.

Rad*_*def 8

非常大的浮点数非常不精确.你所看到的是四舍五入错误.

我们可以证明基数为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.