Comparing doubles in Java gives odd results

断了今生、忘了曾经 提交于 2019-12-09 04:44:44

问题


I really can'get my head around why the following happens:

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

This however works as expected:

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

I'm positive that this is related to autoboxing in some way, but I really don't know why 0 would be boxed differently when the == operator is used and when .equals is called.

Doesn't this implicitly violate the equals contract ?

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

EDIT:

Thanks for the fast answers. I figured that it is boxed differently, the real question is: why is it boxed differently ? I mean that this would be more intuitive if d == 0d than d.equals(0d) is intuitive and expected, however if d == 0 which looks like an Integer is true than 'intuitively' d.equals(0) should also be true.


回答1:


just change it to

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

You were comparing double with Integer 0

Under the cover

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

0 will be autoboxed to Integer and an instance of Integer will be passed to equals() method of Double class, where it will compare like

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

which is going to return false of course.

Update

when you do comparison using == it compares values so there is no need to autobox , it directly operates on value. Where equals() accepts Object so if you try to invoke d1.equals(0) , 0 is not Object so it will perform autoboxing and it will pack it to Integer which is an Object.




回答2:


Number objects only equal to numbers with the same value if they are of the same type. That is:

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

and similar combinations are all false.

In your case, the literal 0 is boxed into an Integer object.




回答3:


It's probably worth noting that you should compare floating point numbers like this:

|x - y| < ε, ε very small



回答4:


d.equals(0) : 0 is an int. The Double.equals() code will return true only for Double objects.




回答5:


When you perform

d == 0

this is upcast to

d == 0.0

however there are no upcasting rules for autoboxing and even if there were equals(Object) gives no hits that you want a Double instead of an Integer.



来源:https://stackoverflow.com/questions/5230642/comparing-doubles-in-java-gives-odd-results

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!