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

Что вызывает исключение "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);

Однако я все равно получаю то же исключение. Кто-нибудь может показать мне, где я совершил ошибку?

4b9b3361

Ответ 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);