java - ArithmeticException: “Expansión decimal sin terminación; No hay un resultado decimal representable exacto ”
bigdecimal (9)
¿Por qué el siguiente código genera la excepción que se muestra a continuación?
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.
De la documentación de Java 8 :
Cuando un objeto MathContext se suministra con una configuración de precisión de 0 (por ejemplo, MathContext.UNLIMITED), las operaciones aritméticas son exactas, al igual que los métodos aritméticos que no toman ningún objeto MathContext. (Este es el único comportamiento que se admitió en las versiones anteriores a 5.)
Como corolario de calcular el resultado exacto, la configuración del modo de redondeo de un objeto MathContext con una configuración de precisión de 0 no se utiliza y, por lo tanto, es irrelevante. En el caso de la división, el cociente exacto podría tener una expansión decimal infinitamente larga; por ejemplo, 1 dividido por 3.
Si el cociente tiene una expansión decimal que no termina y la operación se especifica para devolver un resultado exacto, se lanza una excepción ArithmeticException. De lo contrario, se devuelve el resultado exacto de la división, como se hizo para otras operaciones.
Para arreglarlo, necesitas hacer algo como esto :
a.divide(b, 2, RoundingMode.HALF_UP)
where 2 is precision and RoundingMode.HALF_UP is rounding mode
Más detalles: http://jaydeepm.wordpress.com/2009/06/04/bigdecimal-and-non-terminating-decimal-expansion-error/
Para solucionar un problema de este tipo, he utilizado el siguiente código
a.divide(b, 2, RoundingMode.HALF_EVEN)
2 es la precisión. Ahora el problema se resolvió.
Porque no estás especificando una precisión y un modo de redondeo. BigDecimal se queja de que podría usar 10, 20, 5000, o decimales infinitos, y aún así no podría darle una representación exacta del número. Entonces, en lugar de darte un BigDecimal incorrecto, solo te molesta.
Sin embargo, si proporciona un RoundingMode y una precisión, entonces podrá convertir (por ejemplo, 1.333333333 a infinito a algo como 1.3333 ... pero usted, como programador, necesita decirle con qué precisión está satisfecho) ''.
Respuesta para 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")));
}
Agregue el objeto MathContext a su método de división y ajuste el modo de precisión y redondeo. Esto debería solucionar su problema
Se debe a que Bigdecimal no se pierde y, por ejemplo, si divide 1/3, resultará en una repetición decimal hasta el infinito. 0.33333333 ... teóricamente si multiplicas, recibes el resultado exacto. Pero, un número infinito generará una pila sobre flujo y, en este caso, se lanza la excepción.
Mi solución:
try {
result = n1.divide(n2);
} catch (ArithmeticException e){
Log.d("Error bigdecimal", e.toString());
result = (n1.doubleValue() / n2.doubleValue());
};
En este caso, su resultado no se reducirá redondeando.
Se trata de redondear el resultado, la solución para mí es la siguiente.
divider.divide(dividend,RoundingMode.HALF_UP);
Su programa no sabe qué precisión utilizar para usar los números decimales, por lo que arroja:
java.lang.ArithmeticException: Non-terminating decimal expansion
Solución para evitar la excepción:
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
Tu puedes hacer
a.divide(b, MathContext.DECIMAL128)
Puede elegir el número de bits que desee, ya sea 32,64,128.
Echa un vistazo a este enlace:
Tuve este mismo problema, porque mi línea de código era:
txtTotalInvoice.setText(var1.divide(var2).doubleValue() + "");
Cambio a esto, leyendo la Respuesta anterior, porque no estaba escribiendo precisión decimal:
txtTotalInvoice.setText(var1.divide(var2,4, RoundingMode.HALF_UP).doubleValue() + "");
4 es Precion Decimal
Y RoundingMode son constantes de Enum, puede elegir cualquiera de estas opciones: UP, DOWN, CEILING, FLOOR, HALF_DOWN, HALF_EVEN, HALF_UP
En este caso HALF_UP, tendrá este resultado:
2.4 = 2
2.5 = 3
2.7 = 3
Puede consultar la información de RoundingMode
aquí: http://www.javabeat.net/precise-rounding-of-decimals-using-rounding-mode-enumeration/