Java lang arithmeticexception non terminating decimal expansion no exact representable decimal

Java lang arithmeticexception non terminating decimal expansion no exact representable decimal result

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 financial application and required the results to be accurate.

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

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:

/**
* Test case for «java.lang.ArithmeticException:
* Non-terminating decimal expansion» error with
* BigDecimal.
*
* @author JM
*
*/
public class TestBigDecimal

public static void main(String[] args)

String returnVal = TestBigDecimal.divide(«1», «5»);

System.out.println(«Test #1: returnVal padding-left:30px;»> returnVal = TestBigDecimal.divide(«1», «2»);

System.out.println(«Test #2: returnVal padding-left:30px;»> // Test(#3) will fail as the quotient (returnVal)
//is a non-terminating decimal value.

returnVal = TestBigDecimal.divide(«1», «3»);

System.out.println(«Test #3: returnVal padding-left:30px;»> /**
* 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);

Test #1: returnVal = 0.2
Test #2: returnVal = 0.5
Exception in thread “main” java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result.
at java.math.BigDecimal.divide(Unknown Source)
at com.jm.client.TestBigDecimal.divide(TestBigDecimal.java:34)
at com.jm.client.TestBigDecimal.main(TestBigDecimal.java:20)

Upon some ‘googling’ 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 nonterminating 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.

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

/**
* Test case for «java.lang.ArithmeticException:
* Non-terminating decimal expansion» error with
* BigDecimal.
*
* @author JM
*
*/
public class TestBigDecimal

public static void main(String[] args)

String returnVal = TestBigDecimal.divide(«1», «5»);

System.out.println(«Test #1: returnVal padding-left:30px;»> returnVal = TestBigDecimal.divide(«1», «2»);

System.out.println(«Test #2: returnVal padding-left:30px;»> // Test(#3) will now work as we have provided a scale
// and a rounding mode to the divide() method

returnVal = TestBigDecimal.divide(«1», «3»);

System.out.println(«Test #3: returnVal padding-left:30px;»> >

/**
* 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: returnVal = 0.20
Test #2: returnVal = 0.50
Test #3: returnVal = 0.33

Источник

How to fix «java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result.»

In this tutorial, we show you how to fix the error messages «java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result.» when we use java.math.BigDecimal to divide two values.

How-to-fix-Non-terminating-decimal-expansion

Watch Tutorial

Error Messages

The following simple code snippet demonstrates the error messages

package com.jackrutorial; import java.math.BigDecimal; public class Test < public static void main(String[] args) < BigDecimal num1 = new BigDecimal("10"); BigDecimal num2 = new BigDecimal("3"); BigDecimal result = num1.divide(num2); System.out.println(result); >>

When the above code is executed, the expected exception is encountered as the following error messages

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 com.jackrutorial.Test.main(Test.java:11)

How to fix those error messages?

You have to modify the source code below

Way 1:

BigDecimal result = num1.divide(num2, 2, RoundingMode.HALF_DOWN);

2 is scale of the BigDecimal quotient to be returned.
RoundingMode.HALF_DOWN is Rounding mode to apply. The Rounding Mode Enum constants are UP, DOWN, CEILING, FLOOR, HALF_DOWN, HALF_EVEN, HALF_UP , and UNNECESSARY .

The updated Test class will have the following code:

package com.jackrutorial; import java.math.BigDecimal; import java.math.RoundingMode; public class Test < public static void main(String[] args) < BigDecimal num1 = new BigDecimal("10"); BigDecimal num2 = new BigDecimal("3"); BigDecimal result = num1.divide(num2, 2, RoundingMode.HALF_DOWN); System.out.println(result); >>

Way 2:

num1.divide(num2, MathContext.DECIMAL128)
package com.jackrutorial; import java.math.BigDecimal; import java.math.RoundingMode; public class Test < public static void main(String[] args) < BigDecimal num1 = new BigDecimal("10"); BigDecimal num2 = new BigDecimal("3"); BigDecimal result = num1.divide(num2, MathContext.DECIMAL128); System.out.println(result); >>
3.333333333333333333333333333333333

Источник

Исключение ArithmeticException: «Non-terminating decimal expansion; no exact representable decimal result» в Java

Существует типичная проблема, с которой могут столкнуться начинающие программисты при использовании класса BigDecimal в Java. Это исключение ArithmeticException с сообщением об ошибке «Non-terminating decimal expansion; no exact representable decimal result».

BigDecimal num1 = new BigDecimal("2.0"); BigDecimal num2 = new BigDecimal("3.0"); num1.divide(num2); // вызывает исключение

В данном случае, при попытке выполнить деление num1.divide(num2) , возникает исключение ArithmeticException .

Это происходит потому, что результат деления 2.0 на 3.0 в десятичной системе счисления не имеет конечного (т.е. терминирующего) представления. В действительности, результатом является бесконечно повторяющаяся десятичная дробь 0.6666666. .

В Java класс BigDecimal предназначен для точных вычислений с десятичными числами. Однако, по умолчанию, при делении двух чисел класс BigDecimal требует, чтобы результат был точно представим в десятичной форме. Если это не так (как в примере выше), то возникает исключение ArithmeticException .

Чтобы избежать этой проблемы, можно использовать одну из перегруженных версий метода divide() , которая принимает два аргумента: делитель и MathContext или точность результата (количество знаков после запятой).

Пример исправления:

BigDecimal num1 = new BigDecimal("2.0"); BigDecimal num2 = new BigDecimal("3.0"); num1.divide(num2, 2, RoundingMode.HALF_UP); // возвращает 0.67

В этом примере, используется метод divide() с тремя параметрами: делитель, точность результата (2 знака после запятой) и стратегия округления ( RoundingMode.HALF_UP ). Таким образом, возможно получить приемлемый результат, даже если точное десятичное представление невозможно.

Источник

ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result

This exception is thrown when the result of a division is recurring (never ending), and we haven’t specified rounding mode/scale. In other words, BigDecimal won’t know how to represent a recurring division result if we haven’t specified to what decimal places the result should be rounded, so it throws this exception.

package com.logicbig.example.arithmeticexception;

import java.math.BigDecimal;

public class ArithmeticExceptionNoExactRepresentable public static void main(String. args) BigDecimal a = new BigDecimal(5);
BigDecimal b = new BigDecimal(3);
BigDecimal result = a.divide(b);
System.out.println(result);
>
>

Output

java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result. 
at java.math.BigDecimal.divide (BigDecimal.java:1723)
at com.logicbig.example.arithmeticexception.ArithmeticExceptionNoExactRepresentable.main (ArithmeticExceptionNoExactRepresentable.java:18)
at jdk.internal.reflect.NativeMethodAccessorImpl.invoke0 (Native Method)
at jdk.internal.reflect.NativeMethodAccessorImpl.invoke (NativeMethodAccessorImpl.java:62)
at jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke (DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke (Method.java:564)
at org.codehaus.mojo.exec.ExecJavaMojo$1.run (ExecJavaMojo.java:282)
at java.lang.Thread.run (Thread.java:832)

Fixing the exception

To fix this error we need to specify scale and rounding mode by using following overloaded method:
BigDecimal#divide(BigDecimal divisor, int scale, RoundingMode roundingMode)

package com.logicbig.example.arithmeticexception;

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

public class ArithmeticExceptionNoExactRepresentableFix public static void main(String. args) BigDecimal a = new BigDecimal(5);
BigDecimal b = new BigDecimal(3);
BigDecimal result = a.divide(b, 3, RoundingMode.HALF_UP);
System.out.println(result);
>
>

Источник

Читайте также:  Binding event handlers javascript
Оцените статью