Оператор Equals для нулей (BigDecimal / Double) в Java

несколько интересных наблюдений w.r.t равно оператору на 0 и 0.0

  1. new Double(0.0).equals(0) возвращает false, в то время как new Double(0.0).equals(0.0) возвращает true.

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

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

спасибо.

7 ответов


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

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 потому что объекты имеют разные типы. Для справки,код для метода equals в JDK 7 есть:

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

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


  1. 0 в вашем первом выражении интерпретируется как int, который может быть autoboxed в Integer, а не Double. Таким образом, тип этих двух отличается, следовательно, они не равны. OTOH 0.0 это double, который autoboxed в 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
    

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

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

на двойной ' s равна() метод.

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

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


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

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

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


new Double(0.0).equals(0)

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

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

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


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

У bigdecimal.Ноль будет новым BigDecimal (BigInteger.Ноль, 0, 0, 1) & valueOf метод обычно забирает из кэша от 0 до 15:)


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