开发者

Comparing doubles in Java gives odd results

开发者 https://www.devze.com 2023-02-15 06:35 出处:网络
I really can\'get my head around why the following happens: Double d = 0.开发者_C百科0; System.out.println(d == 0); // is true

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

Double d = 0.开发者_C百科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.


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.


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.


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

|x - y| < ε, ε very small


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


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.

0

精彩评论

暂无评论...
验证码 换一张
取 消