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

标签 java double ieee-754

为什么这些简单的双重比较会返回 true?

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))));

我知道这可能是 IEEE 754 精度问题,但我无法弄清楚这里的确切问题是什么。

最佳答案

非常大的 float 非常不精确。您看到的是舍入误差。

我们可以演示以 10 为基数(科学记数法)的 float ,比如指数为 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

由此可见:

1234*10^9 - 1234*10^1 == 1234*10^9

您可以看到,随着数字变大,我们会失去精度。很多。

对于kicks,可以测试一下:

double d = 10;
while(Double.MAX_VALUE - d == Double.MAX_VALUE)
    d *= 10;
System.out.println(d);

我们可以确定 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));

这大约是 1.99584*10^292,或 2^971

关于java - 将 Java Double.Max_VALUE 与大双数进行比较返回 true,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27007763/

相关文章:

c++ - 从给定的符号、尾数和指数构造 float ( double )的宏或函数?

将 char* 转换为 double,点后最多 2 个位置

c++ - C++ 11:将 `double`打印为十六进制?

c - 以 IEEE 754 交换格式记录/读取 C double

java - 安全标志 fstack-protector Realm library Android

java - 为什么 Double.parseDouble(scan.next()) 比 scan.nextDouble() 快这么多?

java - 使用 Gradle 在运行时出现 NoClassDefFoundError

c++ - 如何遍历 float 的​​精确表示?

java - IntelliJ 无法识别 PATH 变量

java - 仅当jetty应用程序在本地主机上运行时,非英语(希伯来语)字符才能很好地插入mysql数据库?! (部署到heroku)