-3

当我在玩 Java Puzzlers 的代码时(我没有这本书),我遇到了这段代码

public static void main(String args[]) {
        System.out.println(2.00 - 1.10);
    }

输出是

0.8999999999999999

当我尝试将代码更改为

2.00d - 1.10d我仍然得到相同的输出0.8999999999999999

对于,2.00d - 1.10f输出是0.8999999761581421
对于,2.00f - 1.10d输出是0.8999999999999999
对于,2.00f - 1.10f输出是0.9

为什么我没有像一开始那样得到输出0.9?我无法从中做出任何正面或反面?有人能说清楚吗?

4

3 回答 3

6

因为在 Java 中,双精度值是IEEE 浮点数

解决方法可能是使用Big Decimal 类

不可变的、任意精度的有符号十进制数。BigDecimal 由一个任意精度的整数未缩放值和一个 32 位整数刻度组成。如果为零或正数,则刻度是小数点右侧的位数。如果为负数,则将数字的未缩放值乘以 10 的负数次方。因此 BigDecimal 表示的数字的值是 (unscaledValue × 10^-scale)。

在旁注中,您可能还想查看 有关 IEEE 754 的 Wikipedia 文章,浮点数是如何在大多数系统上存储的。

对浮点数执行的操作越多,舍入误差就越大。

于 2013-09-29T13:26:30.507 回答
5

在二进制 0.1 中是 0.00011001100110011001100110011001.....,

因此,它不能用二进制精确表示。根据您四舍五入的位置(浮点数或双数),您会得到不同的答案。

所以 0.1f =0.000110011001100110011001100 和 0.1d=0.0001100110011001100110011001100110011001100110011001

您注意到该数字以 1100 个周期重复。然而,浮点和双精度在循环中的不同点将其拆分。因此,一个错误向上取整,另一个向下取整;导致差异。

但最重要的是; 永远不要假设浮点数是准确的

于 2013-09-29T13:27:51.357 回答
2

其他答案是正确的,只是为了指向一个有效的参考,我引用oracle doc

double:double 数据类型是双精度 64 位 IEEE 754 浮点数。它的值范围超出了本次讨论的范围,但在 Java 语言规范的浮点类型、格式和值部分中指定。对于十进制值,此数据类型通常是默认选择。如上所述, 这种数据类型不应该用于精确值,例如货币

于 2013-09-29T13:32:24.583 回答