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

ArithmeticException: "Неограничивающее десятичное расширение, без точного представляемого десятичного результата"

Почему следующий код вызывает приведенное ниже исключение?

BigDecimal a = new BigDecimal("1.6");
BigDecimal b = new BigDecimal("9.2");
a.divide(b) // results in the following exception.

-

java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result.
4b9b3361

Ответ 1

Из документов Java 8:

Когда объекту MathContext предоставляется значение точности 0 (например, MathContext.UNLIMITED), арифметические операции являются точными, как и арифметические методы, которые не принимают объект MathContext. (Это единственное поведение, которое поддерживалось в выпусках до 5.)

Как следствие вычисления точного результата, настройка режима округления объекта MathContext с настройкой точности 0 не используется и, следовательно, не имеет значения. В случае деления точный фактор может иметь бесконечно длинное десятичное разложение; например, 1 делится на 3.

Если частное имеет неопределенное десятичное разложение, и указана операция для получения точного результата, генерируется исключение ArithmeticException. В противном случае возвращается точный результат деления, как и для других операций.

Чтобы исправить, вам нужно сделать что-то вроде этого:

a.divide(b, 2, RoundingMode.HALF_UP)

where 2 is scale and RoundingMode.HALF_UP is rounding mode

Более подробная информация: http://jaydeepm.wordpress.com/2009/06/04/bigdecimal-and-non-terminating-decimal-expansion-error/

Ответ 2

Потому что вы не указываете точность и округление. BigDecimal жалуется, что он может использовать десятичные числа 10, 20, 5000 или бесконечность, и он все равно не сможет дать вам точное представление числа. Поэтому вместо того, чтобы давать вам неправильный BigDecimal, он просто визжит на вас.

Однако, если вы предоставите RoundingMode и точность, то он сможет конвертировать (например, 1.333333333-to-infinity в нечто вроде 1.3333... но вы, как программист, должны сказать ему, какая точность вы "доволен".

Ответ 4

Для исправления такой проблемы я использовал ниже код

a.divide(b, 2, RoundingMode.HALF_EVEN)

2 - точность. Теперь проблема решена.

Ответ 5

У меня была такая же проблема, потому что моя строка кода была:

txtTotalInvoice.setText(var1.divide(var2).doubleValue() + "");

Я перехожу на это, читая предыдущий ответ, потому что я не писал десятичную точность:

txtTotalInvoice.setText(var1.divide(var2,4, RoundingMode.HALF_UP).doubleValue() + "");

4 - десятичная дробь

И RoundingMode являются константами Enum, вы можете выбрать любую из следующих: UP, DOWN, CEILING, FLOOR, HALF_DOWN, HALF_EVEN, HALF_UP

В этом случае HALF_UP будет иметь такой результат:

2.4 = 2   
2.5 = 3   
2.7 = 3

Вы можете проверить информацию RoundingMode здесь: http://www.javabeat.net/precise-rounding-of-decimals-using-rounding-mode-enumeration/

Ответ 6

Это вопрос округления результата, решение для меня следующее.

divider.divide(dividend,RoundingMode.HALF_UP);

Ответ 7

Ответа на этот вопрос для BigDecimal throws ArithmeticException

public static void main(String[] args) {
        int age = 30;
        BigDecimal retireMentFund = new BigDecimal("10000.00");
        retireMentFund.setScale(2,BigDecimal.ROUND_HALF_UP);
        BigDecimal yearsInRetirement = new BigDecimal("20.00");
        String name = " Dennis";
        for ( int i = age; i <=65; i++){
            recalculate(retireMentFund,new BigDecimal("0.10"));
        }
        BigDecimal monthlyPension =   retireMentFund.divide(
                yearsInRetirement.divide(new BigDecimal("12"), new MathContext(2, RoundingMode.CEILING)), new MathContext(2, RoundingMode.CEILING));      
        System.out.println(name+ " will have £" + monthlyPension +" per month for retirement");
    }
public static void recalculate (BigDecimal fundAmount, BigDecimal rate){
        fundAmount.multiply(rate.add(new BigDecimal("1.00")));
    }

Добавьте объект MathContext в свой вызов метода разделения и настройте режим точности и округления. Это должно устранить вашу проблему.

Ответ 8

Это потому, что у Bigdecimal нет потерь, и если вы, например, поделите 1/3, это приведет к повторению десятичной дроби до бесконечности. 0.33333333... теоретически, если вы умножите обратно, вы получите точный результат. Но бесконечное число будет генерировать стек поверх потока, и в этом случае запускается исключение.

решение:

 try {
     result = n1.divide(n2);
 } catch (ArithmeticException e){
     Log.d("Error bigdecimal", e.toString());
     result = (n1.doubleValue() / n2.doubleValue());
 };

или же

n1.divide(n2,RoundingMode.HALF_UP);

в этом случае ваш результат не будет обрезан округлением

Ответ 9

Ваша программа не знает, какую точность для десятичных чисел использовать, поэтому выдает:

java.lang.ArithmeticException: Non-terminating decimal expansion

Решение обойти исключение:

MathContext precision = new MathContext(int setPrecisionYouWant); // example 2
BigDecimal a = new BigDecimal("1.6",precision);
BigDecimal b = new BigDecimal("9.2",precision);
a.divide(b) // result = 0.17