这是一个奇怪的事(至少对我来说)。此例程打印为true:
double x = 11.0;
double y = 10.0;
if (x-y == 1.0) {
// print true
} else {
// print false
}
但是这个例程打印错误:
double x = 1.1;
double y = 1.0;
if (x-y == 0.1) {
// print true
} else {
// print false
}
有人想解释这里发生了什么吗?我猜它与int
冒充float
s的整数算术有关。此外,是否还有其他基础(10
除外)具有此属性?
答案 0 :(得分:9)
1.0具有精确的二进制表示。 0.1没有。
也许你在问为什么0.1没有存储为1的尾数和-10的指数?但这不是它的工作原理。它不是十进制数加上指数,而是二进制数。所以“时代10”并不是一件很自然的事情。
抱歉,也许最后一部分不清楚。最好将指数视为位的移位。没有位移位会将0.1(十进制)等无限序列转换为有限序列。答案 1 :(得分:4)
修改强>
我被安德鲁纠正了。谢谢!
Java遵循IEEE 754,Base为2,因此它无法正确表示0.1(IEEE中的aprox。0.1000000000000000055511151231257827021181583404541015625
或1.1001100110011001100110011001100110011001100110011010 * 2^-4
),您可以根据该二进制表示法找到它。像这样加倍(位63
=符号,位62-52
=指数,位51-0
是尾数):
long l = Double.doubleToLongBits(0.1);
System.out.println(Long.toBinaryString(l));
我刚刚被结果带走了,我想了一下,Java中的浮点数正在使用10的基数,在这种情况下,它可能代表0.1就好了。
现在希望一劳永逸地清除这些事情,这里发生了什么:
BigDecimal bigDecimal1 = new BigDecimal(0.1d);
BigDecimal bigDecimal2 = new BigDecimal(1.1d - 1.0);
BigDecimal bigDecimal3 = new BigDecimal(1.1d);
BigDecimal bigDecimal4 = new BigDecimal(1.0d);
System.out.println(bigDecimal1.doubleValue());
System.out.println(bigDecimal2.doubleValue());
System.out.println(bigDecimal3.doubleValue());
System.out.println(bigDecimal4.doubleValue());
System.out.println(bigDecimal1);
System.out.println(bigDecimal2);
System.out.println(bigDecimal3);
System.out.println(bigDecimal4);
输出:
0.1
0.10000000000000009
1.1
1.0
0.1000000000000000055511151231257827021181583404541015625
0.100000000000000088817841970012523233890533447265625
1.100000000000000088817841970012523233890533447265625
1
那会发生什么? 1.1 - 1.0相当于:
1.100000000000000088817841970012523233890533447265625 - 1
(Java不能精确地表示1.1),这是0.100000000000000088817841970012523233890533447265625
,这与Java在内部表示0.1的方式不同0.1000000000000000055511151231257827021181583404541015625
)
如果您想知道为什么减法的结果显示为0.10000000000000009
和" 0.1"按原样显示,有一个look over here
答案 2 :(得分:0)
这始终是货币计算。如果您需要精确的数字表示,请使用BigDecimal,但代价是没有硬件启用性能。