虽然我正在玩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 :(得分:6)
因为在Java中,双值是IEEE floating point numbers。
解决方法可能是使用Big Decimal class
不可变,任意精度的带符号十进制数。一个BigDecimal 由任意精度整数非标度值和32位组成 整数尺度。如果为零或正数,则比例为数字位数 小数点右侧。如果为负数,则为未缩放值 数字乘以十来得到否定的力量 规模。 BigDecimal表示的数字的值是 因此(unscaledValue×10 ^ -scale)。
旁注,您可能还想检查Wikipedia article on IEEE 754大多数系统中如何存储浮点数。
您对浮点数执行的操作越多,可能会出现更严重的舍入错误。
答案 1 :(得分:5)
在二进制0.1中是0.00011001100110011001100110011001 .....,
因此无法用二进制表示。根据你四舍五入的地方(浮动或双重),你得到不同的答案。
所以0.1f = 0.000110011001100110011001100 并且0.1d = 0.0001100110011001100110011001100110011001100110011001
您注意到该数字在1100个循环中重复。但是浮动和双精度将它分成循环中的不同点。因此,一个错误四舍五入,另一个回合;导致差异。
但最重要的是; 永远不要假设浮点数是准确的
答案 2 :(得分:1)
其他答案是正确的,只是指向有效的参考,我引用oracle doc:
double:双精度数据类型是双精度64位IEEE 754 浮点。它的价值范围超出了这个范围 讨论,但在浮点类型,格式和 Java语言规范的值部分。对于十进制值, 此数据类型通常是默认选择。正如刚才提到的, 此数据类型永远不应用于精确值,例如 货币