Manish Mulani
Manish Mulani

Reputation: 7375

Equals operator for zeros (BigDecimal / Double) in Java

A few interesting observations w.r.t equals operator on 0 and 0.0

  1. new Double(0.0).equals(0) returns false, while new Double(0.0).equals(0.0) returns true.

  2. BigDecimal.ZERO.equals(BigDecimal.valueOf(0.0)) returns false, while BigDecimal.ZERO.equals(BigDecimal.valueOf(0)) returns true.

Looks like the string comparison is being done in both the cases. Could anyone throw some light on this.

Thanks.

Upvotes: 43

Views: 45521

Answers (7)

assylias
assylias

Reputation: 328855

BigDecimal 'equals' compares the value and the scale. If you only want to compare values (0 == 0.0) you should use compareTo:

BigDecimal.ZERO.compareTo(BigDecimal.valueOf(0.0)) == 0 //true
BigDecimal.ZERO.compareTo(BigDecimal.valueOf(0)) == 0 //true

See the javadoc.

As for the Double comparison, as explained by other answers, you are comparing a Double with an Integer in new Double(0.0).equals(0), which returns false because the objects have different types. For reference, the code for the equals method in JDK 7 is:

public boolean equals(Object obj) {
    return (obj instanceof Double)
           && (doubleToLongBits(((Double)obj).value) ==
                  doubleToLongBits(value));
}

In your case, (obj instanceof Double) is false.

Upvotes: 71

Agassis
Agassis

Reputation: 113

please try doublevalue instead of compareto if you feel is not as beautiful and readable as or simply need an alternative like below:

BigDecimal a = new BigDecimal("0.00");
BigDecimal b = new BigDecimal("0.0");
BigDecimal c = new BigDecimal("0");

if(a.doubleValue()==BigDecimal.ZERO.doubleValue()) {
System.out.println("a equals");
}

if(b.doubleValue()==BigDecimal.ZERO.doubleValue()) {
System.out.println("b equals");
}

if(c.doubleValue()==BigDecimal.ZERO.doubleValue()) {
System.out.println("c equals");
} 

Upvotes: 0

Anish Dasappan
Anish Dasappan

Reputation: 415

For performance considerations BigDecimal, BigInteger caches small values 0 to 15 in case of BigDecimal (without fractions)

BigDecimal.ZERO will be new BigDecimal(BigInteger.ZERO, 0, 0, 1) & valueOf method typically picks up from cache for 0 to 15 :)

Upvotes: 0

TheOutsider
TheOutsider

Reputation: 63

new Double(0.0).equals(0)

This line compares a double value of 0 (which is not exact zero) with integer of 0.

BigDecimal.ZERO.equals(BigDecimal.valueOf(0.0))

BigDecimal will compare the scale length in the equals operation.

Upvotes: 0

Péter Török
Péter Török

Reputation: 116306

  1. The 0 in your first expression is interpreted as an int, which may be autoboxed into an Integer, but not to a Double. So the type of the two is different, hence they are not equal. OTOH 0.0 is a double, which is autoboxed into a Double, so the two operands are deemed equal.

  2. BigDecimals also contain a scale (i.e. number of digits to the right of the decimal separator dot). BigDecimal.ZERO has the value of "0", so its scale is 0. Hence it is not equal to "0.0", whose scale is 1.
    If you want to compare values, use BigDecimal.compareTo:

    BigDecimal.ZERO.compareTo(BigDecimal.valueOf(0.0)) == 0
    BigDecimal.ZERO.compareTo(BigDecimal.valueOf(0)) == 0
    

Upvotes: 7

Chandra Sekhar
Chandra Sekhar

Reputation: 19500

new Double(0.0).equals(0); //false

as the argument you passed is integer. and the equels() in Double class checks whether the argument is od instance Double or not using instance of operator.

The Double's equals() method.

if (!(argument instanceof Double))
  return false;

The argument you passed is integer, which is not instance of Double, so it returns false.

Upvotes: 1

Adam
Adam

Reputation: 36743

new Double(0.0).equals(0) is actually boxed as something like this:

new Double(0.0).equals(Integer.valueOf(0))

Double.equals(...) will never return true unless given another Double instance.

Upvotes: 1

Related Questions