我刚刚经历了一个比较两个号码的错误,我发现以下内容很有趣:
assert 1 == 1;//true
assert 1d == 1;//true
assert 1 == 1f;//true
assert 1d == 1f;//true
assert 1.1 == 1.1;//true
assert 1.1d == 1.1;//true
assert 1.1 == 1.1f;//false
assert 1.1d == 1.1f;//false
我的问题是:为什么只有最后两个陈述是假的?
答案 0 :(得分:13)
这是因为四舍五入。
1可以完全表示为double或float,因此前4个比较按预期工作。
1.1 == 1.1
将双精度值与自身进行比较,并按预期工作。
1.1d == 1.1
与上述内容完全相同(d
隐含1.1
)。
最后两次比较将1.1的双倍与1.1的浮动比较。除了1.1
不能完全表示为float(resp.pleip),所以它会四舍五入到最接近的float(resp.seip) - 但double有一个“更高的分辨率”,因此它们不会被类似地舍入。
要查看确切的值:
System.out.println(new BigDecimal(1.1f)); //1.10000002384185791015625
System.out.println(new BigDecimal(1.1d)); //1.100000000000000088817841970012523233890533447265625
正如@yshavit在评论中所建议的,当你将double与float进行比较时,float会转换为double(http://my.instance.ip:9000),所以你真的要比较两个双打:
System.out.println(new BigDecimal((double) 1.1f)); //1.10000002384185791015625
System.out.println(new BigDecimal(1.1d)); //1.100000000000000088817841970012523233890533447265625
答案 1 :(得分:2)
启动此计划
public static void main(String... args) {
System.out.println("1.1f bits: " + Long.toBinaryString(Double.doubleToLongBits(1.1f)));
System.out.println("1.1d bits: " + Long.toBinaryString(Double.doubleToLongBits(1.1d)));
}
it yelds
1.1f as double: 11111111110001100110011001100110100000000000000000000000000000
1.1d as double: 11111111110001100110011001100110011001100110011001100110011010
这种行为的原因是文字1.1
,即小数1.1 dec 没有有限表示作为二进制分数,IEEE-754将数字存储为二进制分数。所以它是四舍五入的,结果取决于转换时可用的位数(顺便说一下,转换甚至不会在运行时发生 - 这是编译器的工作)。
当比较不同规模的运营商时,会提升规模越小。请注意,并非double和float不能相等:
3.1f != 3.1d
3.0f == 3.0d
答案 2 :(得分:1)
数字1.1无法在二进制浮点表示中精确表示,因此在4字节浮点和8字节双重表示中略有不同。
因此,最后两个都是假的,因为他们将一个double和一个浮点数比作一个不能完全代表的数字。
另一个只是比较一个double和一个double或使用一个可以完全表示为1.0