减去两个十进制数,给出奇怪的输出

当我玩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 ? 我不能做出任何头或尾? 有人可以清楚说明这一点吗?

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

因此,它不能完全用二进制表示。 根据您的圆形(浮动或双重),您可以获得不同的答案。

所以0.1f = 0.000110011001100110011001100和0.1d = 0.0001100110011001100110011001100110011001100110011001

您注意到该数字在1100周期重复。 但是浮动和双精度将它分成循环中的不同点。 因此,一个错误四舍五入,另一个回合; 导致差异。

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

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

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

不可变的,任意精度的带符号十进制数。 BigDecimal由任意精度整数非标度值和32位整数标度组成。 如果为零或正数,则比例是小数点右侧的位数。 如果是负数,则将数字的未缩放值乘以10来表示比例的否定。 因此,BigDecimal表示的数字的值是(unscaledValue×10 ^ -scale)。

另外,您可能还需要查看有关IEEE 754的维基百科文章如何在大多数系统上存储浮点数。

您对浮点数执行的操作越多,可能会出现更严重的舍入错误。

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

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