BigDecimal умножить на ноль
Я выполняю простое умножение с BigDecimal, и я нашел какое-то странное поведение при умножении на ноль (умножение на ноль правильно в этом случае использования).
Базовая математика говорит мне, что все, умноженное на ноль, будет равно нулю (см.: Нулевое Свойство Продукта и Свойства Умножения)
однако следующий код будет последовательно отказывать с тем же ошибка:
assertEquals(new BigDecimal(0), new BigDecimal(22.3).multiply(new BigDecimal(0)));
java.lang.AssertionError: Expected :0 Actual :0E-48
это неточность с BigDecimal или есть какая-то нишевая ветвь математики, которую я где-то упускаю?
Примечания: JDK 1.6.0_27 работает в IntelliJ 11
3 ответа:
вы не можете использовать
equals()
метод сравненияBigDecimals
, как это утверждение делает. Это потому, что эта функция equals будет сравнивать масштаб. Если масштаб отличается,equals()
вернет false, даже если они являются одним и тем же числом математически.однако, вы можете использовать
compareTo()
делать то, что вы хотите:как указывает @assylias, вы также должны использовать
new BigDecimal("22.3")
конструктор чтобы избежать проблем с двойной точностью.BigDecimal expected = BigDecimal.ZERO; BigDecimal actual = new BigDecimal("22.3").multiply(BigDecimal.ZERO); assertEquals(0, expected.compareTo(actual));
существует также метод, называемый
signum()
, которая возвращает -1, 0 или 1 для отрицательного, нулевого и положительного. Таким образом, вы также можете проверить на ноль сassertEquals(0, actual.signum());
есть 2 проблемы с вашим кодом:
- вы должны сравнить BigDecimal с compareTo вместо equals, как советуют другие ответы
- но вы также должны использовать string конструктор:
new BigDecimal("22.3")
вместо двойного конструктораnew BigDecimal(22.3)
чтобы избежать проблем с двойной точностьюдругими словами, следующий код (который правильно использует compareTo) по-прежнему возвращает false:
BigDecimal bd = new BigDecimal(0.1).multiply(new BigDecimal(10)); System.out.println(bd.compareTo(BigDecimal.ONE) == 0);
, потому что
0.1d * 10d != 1
equals()
onBigDecimal
проверяет внутреннее состояниеBigDecimal
для сравнениясм. код ниже
public boolean equals(Object x) { if (!(x instanceof BigDecimal)) return false; BigDecimal xDec = (BigDecimal) x; if (x == this) return true; if (scale != xDec.scale) return false; long s = this.intCompact; long xs = xDec.intCompact; if (s != INFLATED) { if (xs == INFLATED) xs = compactValFor(xDec.intVal); return xs == s; } else if (xs != INFLATED) return xs == compactValFor(this.intVal); return this.inflate().equals(xDec.inflate()); }
если вы хотите сравнить значения использовать
compareTo()
изменить ваш код
assertEquals(0 , new BigDecimal(0).compareTo(new BigDecimal(22.3).multiply(new BigDecimal(0)));
обновление:
использовать конструктор, принимающий строку в качестве параметра для BigDecimal для точности в точности проверьте связанные ссылки ниже
См. Также