Исключение 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.
9 ответов:
С Java 8 docs:
когда объект MathContext поставляется с настройкой точности 0 (для например, MathContext.Неограниченный), арифметические операции точны, как являются арифметические методы, которые не принимают 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/
потому что вы не указываете точность и режим округления. BigDecimal жалуется, что он может использовать 10, 20, 5000 или бесконечные десятичные знаки, и он все равно не сможет дать вам точное представление о числе. Поэтому вместо того, чтобы дать вам неверный BigDecimal, он просто скулит на вас.
однако, если вы поставите RoundingMode и точность, то он сможет конвертировать (например. 1.333333333 до бесконечности что-то вроде 1.3333 ... но ты как то программист должен сказать ему, с какой точностью вы "довольны".
можно сделать
a.divide(b, MathContext.DECIMAL128)вы можете выбрать количество битов, которые вы хотите либо 32,64,128.
проверьте эту ссылку:
для исправления такой проблемы я использовал ниже код
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-десятичное значение
и 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);
Comments