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.
проверьте эту ссылку:
для исправления такой проблемы я использовал ниже 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);