ArithmeticException: «Не заканчивающееся десятичное расширение; нет точного представимого десятичного результата» - PullRequest
465 голосов
/ 04 января 2011

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

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.

Ответы [ 9 ]

772 голосов
/ 04 января 2011

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

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

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

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

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

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

where 2 is precision and RoundingMode.HALF_UP is rounding mode

Подробнее: http://jaydeepm.wordpress.com/2009/06/04/bigdecimal-and-non-terminating-decimal-expansion-error/

72 голосов
/ 04 января 2011

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

Однако, если вы укажете RoundingMode и точность, он сможет преобразовать (например, 1.333333333 в бесконечность во что-то вроде1.3333 ... но вы, как программист, должны сказать, с какой точностью вы «довольны».

49 голосов
/ 06 марта 2013

Вы можете сделать

a.divide(b, MathContext.DECIMAL128)

Вы можете выбрать желаемое количество битов: 32,64,128.

Проверить эту ссылку:

http://edelstein.pebbles.cs.cmu.edu/jadeite/main.php?api=java6&state=class&package=java.math&class=MathContext

13 голосов
/ 26 марта 2015

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

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

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

6 голосов
/ 15 ноября 2014

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

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/

2 голосов
/ 07 августа 2018

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

divider.divide(dividend,RoundingMode.HALF_UP);
1 голос
/ 27 октября 2016

Это потому, что у 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);

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

1 голос
/ 20 июня 2016

Ответ для 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 в вызове метода деления и отрегулируйте точность и режим округления.Это должно исправить вашу проблему

0 голосов
/ 29 июня 2018

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

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
...