Java lang arithmeticexception non terminating decimal expansion no exact representable decimal



Handling the ArithmeticException Runtime Exception in Java

Table of Contents

Introduction

Arithmetic is at the core of every program and every programming language in existence. From integer and floating-point arithmetic all the way down to bitwise and pointer arithmetic, these mathematical operations translate into machine instructions which execute with thundering speeds and manipulate the state of software applications used across all sorts of different domains. Most modern programming languages have a dedicated category of errors or exceptions for dealing with all the peculiar cases and problematic conditions that may arise while performing these arithmetic operations.

ArithmeticException & Why it is an Unchecked Exception

In Java, any arithmetic operation which creates an exceptional condition makes the Java Virtual Machine throw the ArithmeticException exception [1]. Generally speaking, anything that a scientific calculator isn’t able to process would throw this exception. At a lower level, certain rules and constraints are imposed by the programming language itself, so if any of these are broken, the ArithmeticException exception will emerge.

ArithmeticException inherits from the RuntimeException class which means it is an unchecked, runtime exception [2]. This is due to a language design decision made to reduce the exception handling clutter that would otherwise arise with the high frequency of arithmetic operations, but more importantly because throwing and propagating arithmetic exceptions wouldn’t make sense for the majority of cases, which in practice are the result of logical programming errors that need to be refactored, rather than exceptions that need to be handled. Consequently, Java doesn’t require ArithmeticException instances to be checked and will only let them manifest at runtime.

How to Handle ArithmeticException

To prevent the ArithmeticException exception in Java, one should diligently implement methods with arithmetic operations and ensure that they are correct from a mathematical and a semantical standpoint. If and when encountered, the ArithmeticException exception should instigate refactoring of the problematic code, and only in rare and justified cases, the exception should be explicitly handled.

ArithmeticException Examples

Division by zero (integer arithmetic)

Dividing a real number by zero is one of those mathematical operations that seem very simple but do not have a clean and definitive answer. The result of this operation is formally considered to be undefined, as any attempt at a definition leads to a contradiction [3]. Since this is a special case of the division operation, Java treats it as an exceptional condition and throws the ArithmeticException exception whenever it encounters it at runtime.

Preferred approach

The proper way to deal with division by zero is to make sure that the divisor variable is never zero, or when the input cannot be controlled and there is a possibility of zero manifesting itself in the equation, treating that as one of the expected options and resolving it accordingly. This usually means testing (validating) the value of the divisor before using it, as shown below:

Alternative approach

As with any other exception, it is possible to catch the ArithmeticException inside a try-catch construct, but this should generally be avoided as it creates memory overhead and understates the importance of validating input values and working with a bounded set of parameters.

Division by zero doesn’t always throw ArithmeticException

It is important to be aware that division by zero in the context of floating point numbers does NOT trigger the ArithmeticException . This is because the IEEE 754 standard [4] defines division by zero in floating point arithmetic as ±Infinity and the JVM specification follows this standard [5]. As it can be seen in the example below, setting the operand types to the double floating point number type, results in the positive Infinity constant [6] being assigned to the variable z , which then multiplied by itself yields Infinity again.

Читайте также:  Клапанная крышка холодной сваркой

Non-terminating decimal expansion (floating point arithmetic)

Many Java software applications used in the financial sector or otherwise requiring the representation and manipulation of large numbers with great precision, rely on accurate floating point arithmetic and the use of specialized classes such as BigDecimal [7]. Working with these classes requires special attention to detail so as to avoid certain mistakes and prevent erroneous results. As an example, failing to specify a scale with a rounding mode to any operation that may produce a number with an infinite decimal expansion (such as 1.3333. ) [8] will throw an ArithmeticException .

The code in the example above declares two BigDecimal instances with the values of 1.8 and 9.2, and tries to divide the first one by the second one. However, since the result of 1.8/9.2 is 0.195652173913043478260869565217391304347826086…. with an endlessly repeating sequence, the BigDecimal::divide method is unable to return an exact value and the JVM throws an ArithmeticException . As the Java documentation for BigDecimal suggests:

“. 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.”

The way out of this issue is to specify a scale of the quotient to be returned and a rounding policy to apply to the calculated result. One of the ways to do this is by invoking the overridden version of the BigDecimal::divide method which takes two additional parameters for scale and rounding mode, as demonstrated below. Now the resulting computation is a valid number rounded down to 4 decimal places, as explicitly specified.

Safe type casts & putting ArithmeticException to good use

In rare instances, particularly when designing libraries for use by other programs and APIs, ArithmeticException can effectively be used as a safeguard against undesired results and consequences. One such case is numeric type conversions (aka. casts), which Java allows to be done in either direction, from a smaller capacity type to a larger one and vice versa. Casting from a larger to a smaller capacity type is known as downcasting, which is a process where certain information may be lost if the value is larger than what the smaller type can hold. As a specific example, below is a small program casting the maximum value a long type can hold to an integer, i.e., int type. The resulting value here is -1 which is not representative of nor close to the initial value in any way.

To avoid this from happening, an explicit check can be performed to see whether the input value falls within the boundaries of what the target type can hold, as shown below.

This naive and straightforward approach will prevent unsafe casts by triggering the ArithmeticException exception, which is a reasonable solution in this scenario. A more succinct and idiomatic way of accomplishing the same would be to use the native Java method Math::toIntExact which essentially does the same under the hood and makes the type cast safe, i.e., checked.

Conclusion

Arithmetic operations are some of the most frequently encountered operations found in programming code. Java has a dedicated type of exception called ArithmeticException for dealing with exceptional conditions that arise from these operations. The key to preventing the ArithmeticException is being very explicit and deliberate in dealing with special cases such as integer division by zero and non-terminating decimal expansions in floating point arithmetic. Practical examples of these cases alongside possible ways and mechanisms for dealing with them are presented in this article. Finally, a software design scenario where the ArithmeticException exception can be used in a purposeful and beneficial manner is explored, in the context of safe numeric type conversions.

Читайте также:  Fujimi sm cl1 раздвижной зажим для смартфонов

Track, Analyze and Manage Errors With Rollbar

Managing Java errors and exceptions in your code is challenging. It can make deploying production code an unnerving experience. Being able to track, analyze, and manage errors in real-time can help you to proceed with more confidence. Rollbar automates error monitoring and triaging, making fixing Java errors easier than ever. Sign Up Today!

Источник

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 = » + returnVal);

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

System.out.println(«Test #2: returnVal = » + returnVal);

// 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 = » + returnVal);
>

/**
* 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);

Below is the output:

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 = » + returnVal);

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

System.out.println(«Test #2: returnVal = » + returnVal);

// 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 = » + returnVal);

/**
* 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

Источник

What Is Arithmetic exception In Java – Class java.lang. ArithmeticException

Last Updated on: August 16, 2020 By Softwaretestingo Editorial Board

What Is Arithmetic exception?

Thrown when an exceptional arithmetic condition has occurred. For example, an integer “divide by zero” throws an instance of this class.

In this tutorial, we will take a look at a few examples that will highlight the causes of getting an ArithmeticException in the Java program. Also, we will discuss the common causes of Arithmetic exception and how can we handle this exception.

An arithmetic exception is an error that is thrown when a “wrong” arithmetic situation occurs. This usually happens when mathematical or calculation errors occur within a program during run-time. There various causes to an ArithmeticException, the following are a few of them:

List of all invalid operations that throw an ArithmeticException() in Java

  • Dividing by an integer Zero
  • Non-terminating decimal numbers using BigDecimal

Dividing by an integer Zero:

Java throws an Arithmetic exception when a calculation attempt is done to divide by zero, where the zero is an integer. Take the following piece of code as an example:

When we run the code, we get the following error:

Since we divided 10 by 0, where 0 is an integer, java throws the above exception. However, if the zero is a floating-point as in the following code, we get a completely different result.

Here, no exception is thrown, and “Q” now has a value of infinity. Note that is (almost) always a bad idea to divide by zero, even if no exception is thrown.

Non-terminating decimal numbers using BigDecimal:

The BigDecimal class is a Java class used to represent decimal numbers up to a very high number of precision digits. The class also offers a set of functionalities that are not available using primitive data types such as doubles and floats. These functionalities include rounding up/down, defining the number of decimal places we need from a number, etc.

Since BigDecimals are used to represent numbers to a high degree of accuracy, a problem might occur with some numbers, for example, when dividing 1 by 3, or 2 by 12. These numbers do not have a specific number of decimal places, for example, 1/3 = 0.33333333333333333…

Take the following program for example :

Take a Look On The Execution:

In the program above, since the class doesn’t know what to do with the division result, an exception is thrown.

As we said, the program doesn’t know what to do with the result of the division, hence an exception is thrown with the message “Non-terminating decimal expansion”. One possible solution to the above problem is to define the number of decimal places we require from a big decimal, and the form of rounding that will be used to limit the value to a certain number of decimals. For example, we could say that z should be limited to 7 decimal places, by rounding up at the 7th decimal place:

Here, the program runs properly, since we defined a limit to the number of places the variable “x” could assume.

If You Have any doubts feel free to drop your doubts in the Comment Section.

Источник

Оцените статью
toolgir.ru
Adblock
detector