2012-05-15 28 views
19

He usado BigDecimals antes, pero no muy a menudo y que estaba trabajando en algo esta mañana y seguí recibiendo la siguiente excepción:¿Qué causa la excepción de "Expansión decimal no terminada" de BigDecimal.divide?

Exception in thread "main" java.lang.ArithmeticException: Non-terminating decimal expansion; 
no exact representable decimal result. 
    at java.math.BigDecimal.divide(BigDecimal.java:1594) 

yo estaba tratando de establecer la escala y el uso de redondeo para eliminar el problema como entonces:

BigDecimal bd1 = new BigDecimal(1131).setScale(2,BigDecimal.ROUND_HALF_UP); 
    BigDecimal bd2 = new BigDecimal(365).setScale(2,BigDecimal.ROUND_HALF_UP); 
    BigDecimal bd3 = bd1.divide(bd2).setScale(2,BigDecimal.ROUND_HALF_UP); 
    System.out.println("result: " + bd3); 

Sin embargo, sigo teniendo la misma excepción. ¿Alguien puede mostrarme dónde cometí un error?

+0

Qué línea desencadena la ¿excepción? – m0skit0

+0

@ m0skit0 'en java.math.BigDecimal.divide' muestra la ubicación de excepción –

+2

http://stackoverflow.com/questions/4591206/non-terminating-decimal-expansion-no-exact-representable-decimal-result –

Respuesta

46

Al utilizar divide se debe utilizar un MathContext en caso de que el resultado exacto tiene un número infinito de decimales (que es su caso):

MathContext mc = new MathContext(2, RoundingMode.HALF_UP); 
BigDecimal bd3 = bd1.divide(bd2, mc); 

o alternativamente:

BigDecimal bd3 = bd1.divide(bd2, RoundingMode.HALF_UP); 
+0

Gracias que corrigió el problema. También intenté usar un MathContext pero parece que lo hice incorrectamente. – ChadNC

+1

Me gusta el hecho de que demostró en ambos sentidos. Al principio pensé, ¿por qué alguien usaría el 'MathContext'? Entonces me di cuenta. Duh ... por coherencia ... – buzzsawddog

+0

No hago 'new BigDecimal (350000.00) .divide (nuevo BigDecimal (1))' y sigo teniendo la excepción de "Decimal decimal no terminante, sin resultado decimal representable exacto". No entiendo por qué el resultado no es simplemente 350000, ¿pueden explicarlo por favor? –

1

que está recibiendo este error debido a la división:

  1. El BigDecimal por defecto siempre trata de devolver el resultado exacto de una operación.
  2. Debido a esto, ciertas operaciones de división como 1 dividido por 3, el cociente exacto tendrá una expansión decimal infinitamente larga. Esto causará que la operación de división falle y arroje el error como se describió anteriormente.

Proporcione una escala y un modo de redondeo (como lo ha hecho al crear BigDecimales) dentro del método de división para evitar esto.

Tomado de here. El código de ejemplo para la división de trabajo también se proporciona.

Véase también: Java docs on BigDecimal.

+0

Parecido a no sean tus palabras, así que busqué en Google y encontré esto. http://jaydeepm.wordpress.com/2009/06/04/bigdecimal-and-non-terminating-decimal-expansion-error/ Lol. – Vulcan

+0

@Vulcan no lo son, pero siempre enlace a las fuentes. Simplemente haciendo que la respuesta se complete primero. La mayoría de las buenas respuestas serán citas. – keyser

+1

¿No es la escala, no el RoundingMode, lo que soluciona el problema? –

4

Aquí está el problema

bd1.divide(bd2) 

Es necesario utilizar una de las divide() métodos sobrecargados que se lleva a un modo de redondeo (en varias formas) - no se puede hacer el redondeo después de la división, ya que con una fracción sin terminación del intermedio El resultado ya tendría que redondearse o requerir espacio de almacenamiento infinito.

2

Por defecto, BigDecimal intenta devolver el valor exacto de la expresión de división dada. Debido a esto, si el valor exacto no puede determinarse debido a una expansión decimal infinita, se lanza una ArithmeticException. Un ejemplo básico de esto es dividir 1 por 3, lo que resulta en un tercio, un valor que no se puede representar exactamente en notación decimal.

1

El problema es causado por una operación (división) que daría como resultado un decimal recurrente.

La solución es especificar una escalacuando se realiza una división, por ejemplo:

BigDecimal one = new BigDecimal("1"); 
BigDecimal three = new BigDecimal("3"); 
BigDecimal oneDivThree = one.divide(three, 200, RoundingMode.HALF_UP); 
0

Para el montaje, se debe cambiar el tercer stament de la siguiente manera:

BigDecimal bd1 = new BigDecimal(1131).setScale(2,BigDecimal.ROUND_HALF_UP); 
BigDecimal bd2 = new BigDecimal(365).setScale(2,BigDecimal.ROUND_HALF_UP); 
BigDecimal bd3 = bd1.divide(bd2, 2, BigDecimal.ROUND_HALF_UP); 
System.out.println("result: " + bd3); 
Cuestiones relacionadas