26. Summing two large int/long values and operation overflow

Let's dive into the solution by starting with the + operator, as in the following example:

int x = 2;
int y = 7;
int z = x + y; // 9

This is a very simple approach and works fine for most of the computations that involve int, long, float, and double.

Now, let's apply this operator on the following two large numbers (sum 2,147,483,647 with itself):

int x = Integer.MAX_VALUE;
int y = Integer.MAX_VALUE;
int z = x + y; // -2

This time, z will be equal to -2, which is not the expected result, that is, 4,294,967,294. Changing only the z type from int to long will not help. However, changing the types of x and y from int to long as well will help:

long x = Integer.MAX_VALUE;
long y = Integer.MAX_VALUE;
long z = x + y; // 4294967294

But the problem will reappear if, instead of Integer.MAX_VALUE, there is Long.MAX_VALUE:

long x = Long.MAX_VALUE;
long y = Long.MAX_VALUE;
long z = x + y; // -2

Starting with JDK 8, the + operator has been wrapped in a more expressive way by each wrapper of a primitive numeric type. Therefore, the Integer, Long, Float, and Double classes have a sum() method:

long z = Long.sum(); // -2

Behind the scenes, the sum() methods uses the + operator as well, so they simply produce the same result.

But also starting with JDK 8, the Math class was enriched with two addExact() methods. There is one addExact() for summing two int variables and one for summing two long variables. These methods are very useful if the result is prone to overflowing int or long, as shown in the preceding case. In such cases, these methods throw ArithmeticException instead of returning a misleading result, as in the following example:

int z = Math.addExact(x, y); // throw ArithmeticException

The code will throw an exception such as java.lang.ArithmeticException: integer overflow. This is useful since it allows us to avoid introducing misleading results in further computations (for example, earlier, -2 could silently enter further computations).

In a functional style context, a potential solution will rely on the BinaryOperator functional interface, as follows (simply define the operation of the two operands of the same type):

BinaryOperator<Integer> operator = Math::addExact;
int z = operator.apply(x, y);

Besides addExact(), Math has multiplyExact(), substractExact(), and negateExact(). Moreover, the well-known increment and decrement expressions, i++ and i--, can be controlled for overflowing their domains via the incrementExact() and decrementExact() methods (for example, Math.incrementExact(i)). Notice that these methods are only available for int and long.

When working with a large number, also focus on the BigInteger (immutable arbitrary-precision integers) and BigDecimal (immutable, arbitrary-precision signed decimal numbers) classes.
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.221.126.56