Подтвердить что ты не робот

Почему BigDecimal ( "5.50" ) не соответствует BigDecimal ( "5.5" ) и как обойти эту проблему?

Собственно, я нашел возможное решение

//returns true
new BigDecimal ("5.50").doubleValue () == new BigDecimal("5.5").doubleValue ()

Конечно, его можно улучшить с помощью чего-то вроде Math.abs (v1 - v2) < EPS, чтобы сделать сравнение более надежным, но вопрос в том, приемлема ли эта методика или есть ли лучшее решение?

Если кто-то знает, почему дизайнеры java решили реализовать BigDecimal равным таким образом, было бы интересно прочитать.

4b9b3361

Ответ 1

Из javadoc BigDecimal

равно

public boolean equals(Object x)

Сравнивает этот BigDecimal с указанным Object для равенства. В отличие от compareTo, этот метод рассматривает два объекта BigDecimal равными , только если они равны по значению и масштабу (таким образом, 2.0 не сравнивается с 2.00 при сравнении по этому методу).

Просто используйте compareTo() == 0

Ответ 2

Использование == для сравнения удвоений похоже на плохую идею в целом.

Вы можете вызвать setScale на ту же самую вещь на сравниваемых вами номерах:

new BigDecimal ("5.50").setScale(2).equals(new BigDecimal("5.5").setScale (2))

где вы будете устанавливать масштаб на большее из двух:

BigDecimal a1 = new BigDecimal("5.051");
BigDecimal b1 = new BigDecimal("5.05");
// wow, this is awkward in Java
int maxScale = Collections.max(new ArrayList() {{ a1.scale(), b1.scale()}});
System.out.println(
  a1.setScale(maxScale).equals(b1.setScale(maxScale)) 
  ? "are equal" 
  : "are different" );

Использование compareTo() == 0 - лучший ответ. Увеличение масштаба одного из чисел в моем подходе выше, вероятно, является "ненужной инфляцией", которую упоминает документация compareMagnitude, когда он говорит:

/**
 * Version of compareTo that ignores sign.
 */
private int compareMagnitude(BigDecimal val) {
    // Match scales, avoid unnecessary inflation
    long ys = val.intCompact;
    long xs = this.intCompact;

и, конечно, compareTo намного проще в использовании, поскольку он уже реализован для вас.

Ответ 3

Простейшее выражение для сравнения игнорирует ведущие нули, так как Java 1.5:

bd1.stripTrailingZeros().equals(bd2.stripTrailingZeros())