在Java中比较双精度会得到奇怪的结果

2022-09-04 06:17:02

我真的可以弄清楚为什么会发生以下情况:

Double d = 0.0;
System.out.println(d == 0); // is true
System.out.println(d.equals(0)); // is false ?!

但是,这按预期工作:

Double d = 0.0;
System.out.println(d == 0.0); // true
System.out.println(d.equals(0.0)); // true

我很确定这在某种程度上与自动装箱有关,但我真的不知道为什么当使用==运算符和调用.equals,0会以不同的方式装箱

这难道不是隐含地违反了合同吗?equals

  *  It is reflexive: for any non-null reference value
  *     x, x.equals(x) should return
  *     true.

编辑

感谢您的快速回答。我认为它的盒装方式不同,真正的问题是:为什么它的盒装方式不同?我的意思是,如果这比直觉和预期更直观,但是如果哪个看起来像一个比“直观地”也应该是真的。d == 0dd.equals(0d)d == 0Integertrued.equals(0)


答案 1

只需将其更改为

System.out.println(d.equals(0d)); // is false ?! now true

您正在将双倍与 0 进行比较Integer

封面下

System.out.println(d.equals(0)); // is false ?!

0将被自动装箱到,Integer的一个实例将被传递给类的方法,在那里它将比较像Integerequals()Double

@Override
    public boolean equals(Object object) {
        return (object == this)
                || (object instanceof Double)
                && (doubleToLongBits(this.value) == doubleToLongBits(((Double) object).value));
    }

这当然会返回的。

更新

当您使用它进行比较时,它会比较值,因此不需要自动框,它直接对值进行操作。如果您尝试调用 ,则接受的地方不是对象,因此它将执行自动装箱,并将其打包为整数,这是一个对象。==equals()Objectd1.equals(0)0


答案 2

Number对象仅等于具有相同值的数字(如果它们具有相同的类型)。那是:

new Double(0).equals(new Integer(0));
new BigInteger("0").equals(new BigDecimal("0"));

类似的组合都是错误的。

在本例中,文本被装箱到一个对象中。0Integer


推荐