In one of my recent projects, I had to use java.math.BigDecimal to divide two values. I had to use BigDecimal instead of double as this was a Billing application and required the results to be accurate.

However, after running the application, I encountered the following error intermittently:

Exception in thread "main" java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result. Below is a sample code which illustrates the issue:

Below is a sample code which illustrates the issue:

/** * Sample Code for "java.lang.ArithmeticException: * Non-terminating decimal expansion" error with * BigDecimal. * @author Anand Kushwaha **/ public class TestBigDecimalDivide { public static void main(String[] args) { String result = TestBigDecimalDivide.divide("1", "5"); System.out.println("Case #1: result = " + result); result = TestBigDecimalDivide.divide("1", "2"); System.out.println("Case #2: result = " + result); /** *Case(#3) will through the exception : "Exception in thread "main" java.lang.ArithmeticException: Non-terminating decimal expansion; no exact *representable decimal result." Because the quotient (result) is a non-terminating decimal value. */ result = TestBigDecimalDivide.divide("1", "3"); System.out.println("case3 #3: result = " + result); } /** * Divide val1 by val2 and return the result as String. * @param val1 * @param val2 * @return value as String */ public static String divide(String val1, String val2) { BigDecimal v1 = new BigDecimal(val1); BigDecimal v2 = new BigDecimal(val2); return v1.divide(v2).toPlainString(); } } And Here is the Output : Case #1: result = 0.2 Case #2: result = 0.5 Exception in thread "main" java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result. at java.math.BigDecimal.divide(BigDecimal.java:1690) at TestBigDecimalDivide.divide(TestBigDecimalDivide.java:29) at TestBigDecimalDivide.main(TestBigDecimalDivide.java:15) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:483) at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)

After searching on Net and looking at the Java Doc for BigDecimal, I found that this happens due to a couple of reasons:

1. The BigDecimal by default always tries to return the exact result of an operation.

2. Due to this, certain division operations like 1 divided by 3, the exact quotient will have an infinitely long decimal expansion. This will cause the division operation to fail and throw the error as described above.

This is also described in the BigDecimal Java Doc quoted below:

“In the case of divide, the exact quotient could have an infinitely long decimal expansion; for example, 1 divided by 3. If the quotient has a non terminating decimal expansion and the operation is specified to return an exact result, an ArithmeticException is thrown. Otherwise, the exact result of the division is returned, as done for other operations.”

To fix the issue, we need to provide a scale (i.e. the precision) for the quotient and also the rounding mode to the BigDecimal.divide(). In the sample below, I have used a scale of 2 and the rounding mode as RoundingMode.HALF_UP. You can increase the scale if you want a greater precision.

/** * Sample Code for "java.lang.ArithmeticException: * Non-terminating decimal expansion" error with * BigDecimal. * @author Anand Kushwaha **/ public class TestBigDecimalDivide { public static void main(String[] args) { String result = TestBigDecimalDivide.divide("1", "5"); System.out.println("Case #1: result = " + result); result = TestBigDecimalDivide.divide("1", "2"); System.out.println("Case #2: result = " + result); /** *Case(#3) will through the exception : "Exception in thread "main" java.lang.ArithmeticException: Non-terminating decimal expansion; no exact *representable decimal result." Because the quotient (result) is a non-terminating decimal value. */ result = TestBigDecimalDivide.divide("1", "3"); System.out.println("case3 #3: result = " + result); } /** * Divide val1 by val2 and return the result as String. * @param val1 * @param val2 * @return value as String */ public static String divide(String val1, String val2) { BigDecimal v1 = new BigDecimal(val1); BigDecimal v2 = new BigDecimal(val2); return v1.divide(v2, 2, RoundingMode.HALF_UP).toPlainString(); } } The output of the above program now is as desired: Test #1: result = 0.20 Test #2: result = 0.50 Test #3: result = 0.33

## Recent Comments