Я думал, что java.math.BigDecimal
должен быть "Ответ & торговля"; к необходимости выполнения бесконечной точности арифметики с десятичными числами.
Рассмотрим следующий фрагмент:
import java.math.BigDecimal;
//...
final BigDecimal one = BigDecimal.ONE;
final BigDecimal three = BigDecimal.valueOf(3);
final BigDecimal third = one.divide(three);
assert third.multiply(three).equals(one); // this should pass, right?
Я ожидаю, что assert
пройдет, но на самом деле выполнение даже не доходит: one.divide(three)
вызывает выброс ArithmeticException
!
Exception in thread "main" java.lang.ArithmeticException:
Non-terminating decimal expansion; no exact representable decimal result.
at java.math.BigDecimal.divide
Оказывается, это поведение явно задокументировано в API:
В случае
divide
точное частное может иметь бесконечно длинное десятичное разложение; например, 1 делится на 3. Если фактор имеет неограничивающее десятичное расширение, и операция указана для возврата точного результата, генерируетсяArithmeticException
. В противном случае возвращается точный результат деления, как это сделано для других операций.
Далее, просматривая API, обнаруживается, что на самом деле существуют различные перегрузки divide
, которые выполняют неточное деление, то есть:
final BigDecimal third = one.divide(three, 33, RoundingMode.DOWN);
System.out.println(three.multiply(third));
// prints "0.999999999999999999999999999999999"
Конечно, теперь очевидный вопрос: "Какая точка???". Я думал, что BigDecimal
является решением, когда нам нужна точная арифметика, например. для финансовых расчетов. Если мы точно не можем даже divide
, то насколько это полезно? Действительно ли это служит общей цели, или это полезно только в очень нишевом приложении, где вам, к счастью, просто не нужно divide
вообще?
Если это не правильный ответ, что мы можем использовать для точного деления в финансовых расчетах? (Я имею в виду, у меня нет финансового специалиста, но они все еще используют деление, правильно?).