ArithmeticException: "non-terminating decimal expansion; нет точного представимого десятичного результата"

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

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 ответов


С Java 8 docs:

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

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

если коэффициент имеет расширение бесконечной десятичной дроби и операция возвращает точный результат, arithmeticexception бросается. В противном случае возвращается точный результат деления, как это сделано для прочие операции.

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

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/


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

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


можно сделать

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


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

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

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


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

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

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

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

4 является десятичной Precion

и RoundingMode являются константами перечисления, вы можете выбрать любой из этого 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/


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


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

мое решение:

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

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


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

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

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

divider.divide(dividend,RoundingMode.HALF_UP);