Что вызывает исключение "Non-terminating decimal expansion" из BigDecimal.divide?
Я использовал BigDecimals раньше, но не очень часто, и я работал над чем-то этим утром, и я продолжал получать следующее исключение:
Exception in thread "main" java.lang.ArithmeticException: Non-terminating decimal expansion;
no exact representable decimal result.
at java.math.BigDecimal.divide(BigDecimal.java:1594)
Я пытался установить масштаб и использовать округление, чтобы устранить проблему следующим образом:
BigDecimal bd1 = new BigDecimal(1131).setScale(2,BigDecimal.ROUND_HALF_UP);
BigDecimal bd2 = new BigDecimal(365).setScale(2,BigDecimal.ROUND_HALF_UP);
BigDecimal bd3 = bd1.divide(bd2).setScale(2,BigDecimal.ROUND_HALF_UP);
System.out.println("result: " + bd3);
Однако я все равно получаю то же исключение. Кто-нибудь может показать мне, где я совершил ошибку?
Ответы
Ответ 1
При использовании divide
вы должны использовать MathContext
, если точный результат имеет бесконечное число десятичных знаков (это ваш случай):
MathContext mc = new MathContext(2, RoundingMode.HALF_UP);
BigDecimal bd3 = bd1.divide(bd2, mc);
или, альтернативно:
BigDecimal bd3 = bd1.divide(bd2, RoundingMode.HALF_UP);
Ответ 2
Здесь проблема
bd1.divide(bd2)
Вам нужно использовать один из перегруженных методов divide()
, который принимает режим округления (в разных формах) - вы не можете делать округление после деления, потому что с неисчерпаемой фракцией промежуточный результат либо уже должен быть округлен, или требуют бесконечного пространства для хранения.
Ответ 3
По умолчанию BigDecimal пытается вернуть точное значение данного выражения разделения. Из-за этого, если точное значение не может быть определено из-за бесконечного десятичного расширения, генерируется исключение ArithmeticException. Основным примером этого является разделение 1 на 3, что приводит к одной трети, значение, которое невозможно точно представить в десятичной нотации.
Ответ 4
Вы получаете эту ошибку из-за деления:
- BigDecimal по умолчанию всегда пытается вернуть точный результат операции.
- В связи с этим некоторые операции деления, такие как 1, деленная на 3, точный коэффициент будет иметь бесконечно длинное десятичное расширение. Это приведет к сбою операции деления и выбросу ошибки, как описано выше.
Предоставьте масштаб и режим округления (как вы делали при создании BigDecimals) в методе разделения, чтобы предотвратить это.
Взято из здесь. Также предоставляется код примера рабочего подразделения.
Смотрите также: Java-документы в BigDecimal.
Ответ 5
Проблема вызвана операцией (делением), которая приведет к повторяющейся десятичной дроби.
Решение состоит в том, чтобы указать масштаб при выполнении деления, например:
BigDecimal one = new BigDecimal("1");
BigDecimal three = new BigDecimal("3");
BigDecimal oneDivThree = one.divide(three, 200, RoundingMode.HALF_UP);
Ответ 6
Чтобы исправить это, вы должны изменить третий замысел следующим образом:
BigDecimal bd1 = new BigDecimal(1131).setScale(2,BigDecimal.ROUND_HALF_UP);
BigDecimal bd2 = new BigDecimal(365).setScale(2,BigDecimal.ROUND_HALF_UP);
BigDecimal bd3 = bd1.divide(bd2, 2, BigDecimal.ROUND_HALF_UP);
System.out.println("result: " + bd3);