Tuesday, June 24, 2014

java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal


Problem:

package foo;

import java.math.BigDecimal;

public class BigDecimalTest {

   public static void main(String[] args) {

       BigDecimal foo = new BigDecimal("1");
       BigDecimal bar = new BigDecimal("125.4");

       
       BigDecimal result = foo.divide(bar);
       
       System.out.println(foo + " / " + bar + " = " + result);

   }
}

The above example will result in a  

java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result.. BigDecimal's divide() method uses a really effed up way to calculate the scale of the result: dividend.scale() - divisor.scale(). In order for this to work, you have to use one of the other divide() methods, where you can add another parameter specifying the scale or a predefined MathContext. Mh, I just noticed that the divide() method in question was added in 1.5, in 1.4 all divide() methods required a scale or RoundingMode.
As I see it, the new version of the method is pretty much useless,
since there's always the chance of breaking at runtime when you don't
have control over the values, e. g. if read from a database. Seems like
they tried to fix a class that's broken beyond all repair.

So a working version of the above example would look like this:


package foo;

import java.math.BigDecimal;
import java.math.RoundingMode;

public class BigDecimalTestScale {

   public static void main(String[] args) {

       BigDecimal foo = new BigDecimal("1");
       BigDecimal bar = new BigDecimal("125.4");

       
       BigDecimal result = foo.divide(bar, 3, BigDecimal.ROUND_HALF_UP);

       
       System.out.println(foo + " / " + bar + " = " + result);

}

Reference:

No comments:

Post a Comment