双重和浮动值比较

时间:2016-01-20 17:56:23

标签: java

我刚刚经历了一个比较两个号码的错误,我发现以下内容很有趣:

    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

我的问题是:为什么只有最后两个陈述是假的?

3 个答案:

答案 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 ye​​lds

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

的值