2012-04-03 2 views
32

Несколько интересных наблюдений w.r.t равняется оператора на 0 и 0.0Равно оператор для нулей (BigDecimal/Double) в Java

  1. new Double(0.0).equals(0) возвращает ложь, в то время как new Double(0.0).equals(0.0) возвращает истину.

  2. BigDecimal.ZERO.equals(BigDecimal.valueOf(0.0)) возвращает false, а BigDecimal.ZERO.equals(BigDecimal.valueOf(0)) возвращает true.

Похоже, что сравнение строк выполняется в обоих случаях. Может ли кто-нибудь пролить свет на это.

Спасибо.

ответ

59

BigDecimal 'equals' сравнивает значение и масштаб. Если вы хотите сравнить значения (0 == 0,0) следует использовать СотрагеТо:

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

См javadoc.

Что касается двойного сравнения, как объясняется другими ответами, вы сравниваете Double с целым числом в new Double(0.0).equals(0), который возвращает false, потому что объекты имеют разные типы. Для справки, code for the equals method in JDK 7 является:

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

В вашем случае (obj instanceof Double) ложно.

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

как аргумент, который вы передали, является целым числом. и equels() в Двойной проверки класса является ли аргумент спосо экземпляр Double или не используя экземпляр оператора.

Двойной 's equals() способ.

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

Аргумент вы прошли это целое, который не является экземпляром Double, поэтому он возвращает ложь.

5
  1. 0 в первом выражении интерпретируется как int, который может быть autoboxed в Integer, но не к Double. Таким образом, тип двух разных, следовательно, они не равны. OTOH 0.0 - это double, который автобоксирован в Double, поэтому два операнда считаются равными.

  2. BigDecimals также содержит шкалу (то есть число цифр справа от десятичной разделительной точки). BigDecimal.ZERO имеет значение «0», поэтому его масштаб равен 0. Следовательно, он не равен «0.0», масштаб которого равен 1.
    Если вы хотите сравнить значения, используйте BigDecimal.compareTo:

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

новый двойной (0.0) .equals (0) фактически боксировал как что-то вроде этого:

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

Double.equals (...) никогда не вернет true, если не будет дан другой экземпляр Double.

+0

@LukasEder Спасибо, обновлено. – Adam

0
new Double(0.0).equals(0) 

Эта строка сравнивает двойное значение 0 (который не является точным нулем) с целым 0.

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

BigDecimal будет сравнивать длину шкалы в операции равно.

0

Для соображений производительности BigDecimal, BigInteger кэширует малые значения 0 до 15 в случае BigDecimal (без фракций)

BigDecimal.ZERO будет новый BigDecimal (BigInteger.ZERO, 0, 0, 1) & valueOf метод обычно берет от кеша от 0 до 15 :)

0
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"); 
} 
+1

Преобразование BigDecimal в double может привести к потере точности и отличному от нуля, но близко к нулю. BigDecimal, превращенный в Double, может стать 0. Вы должны сравнить использование метода compareTo в BigDecimal –

Смежные вопросы