Java Exact Arithmetic Operations Support in Math Class

Java 8 has brought many awesome features for java developers. Some of them I have already described in Comparator changes, Streams examples, Internal vs. external iterations, predicates, functional interfaces, default methods, lambda expressions and date and time API changes. All above changes were related to lambda expressions, which is the most attention grabber and somehow game changer as well.

Apart from above changes, we got non-lambda expression changes as well. I already discussed about String.join() method in previous post. In this post, I am discussing about changes done in Math class to support exact arithmetic.

Sections in this post:

1) (add|substract|multiply|increment|decrement|negate)Exact methods
2) floorMod and floorDiv methods
3) toIntExact method
4) nextDown method

Let’s discuss them one by one.

1) (add|substract|multiply|increment|decrement|negate)Exact methods

The Math class provides these new methods which throws "java.lang.ArithmeticException" exception every-time the result of operation overflows to max limit. All above methods takes arguments as either int or long primitives.

e.g. Consider multiplication of 100000 * 100000. Normally done, it will give you a wrong return “silently” and in application runtime it’s your responsibility to check every time the max limit to avoid wrong calculations.

In java 8, multiPlyExact method will do the job for you and will throw the exception if result overflow the max limit.


//Normal multiplication
System.out.println( 100000 * 100000 );

//Using multiPlyExact
System.out.println( Math.multiplyExact( 100000 , 100000 ));

Output:

1410065408 //Incorrect result
Exception in thread "main" java.lang.ArithmeticException: integer overflow
    at java.lang.Math.multiplyExact(Math.java:867)
    at java8features.MathematicalFuctions.main(MathematicalFuctions.java:8)

The same thing will happen with other operations as well. e.g. add operation vs. addExact


//Normal add operation
System.out.println( Integer.MAX_VALUE + Integer.MAX_VALUE );

//Using addExact
System.out.println( Math.addExact( Integer.MAX_VALUE , Integer.MAX_VALUE ));

Output:

-2          //incorrect result
Exception in thread "main" java.lang.ArithmeticException: integer overflow
    at java.lang.Math.addExact(Math.java:790)
    at java8features.MathematicalFuctions.main(MathematicalFuctions.java:11)

2) floorMod and floorDiv methods

Java 8 has worked to solve a very long standing problem of integer remainders. Everybody knows that expression n % 2 is

i) 0 : if number is even
ii) 1 : if is odd

What if number is negative. Above expression can/cannot return -1. If fact for negative numbers, result is unpredictable to me.

System.out.println( 10 % 2 );
System.out.println( 11 % 2 );
System.out.println( -15 % 2 );
System.out.println( -16 % 2 );

Output:

0
1
-1
0

Now do the above mod operation with exact mathematics came with java 8.

System.out.println( Math.floorMod(10 , 2) );
System.out.println( Math.floorMod(11 , 2) );
System.out.println( Math.floorMod(-15 , 2) );
System.out.println( Math.floorMod(-16 , 2) );

Output:

0
1
1
0

Similarly another problem can be a getting the position of a hour hand of a clock. Let’s say current time is 10 O’clock. You made adjustment of n hours and now want to get it’s position. Formula is simple:

Current Position = (position + adjustment) % 12

It will work good if (position + adjustment) is computed to position number. But what if hour hand moved anti-clockwise such that (position + adjustment) becomes negative. Let’s check.


System.out.println( (10+3) % 12 );
System.out.println( (5+6) % 12 );
System.out.println( (10-27) % 12 );

Output:

1
11
-5 //This is incorrect

Now use the exact airthmatic method floorMod.


System.out.println( Math.floorMod(10+3 , 12) );
System.out.println( Math.floorMod(5+6 , 12) );
System.out.println( Math.floorMod(10-27 , 12) );

Output:

1
11
7 //This is correct

Similar changes has been done in floorDiv() method.

3) toIntExact method

This method is handy when you are trying to assign a long value to int type variable. Though this situation does not arrive easily but it may be required in some rare cases. Normal long to int conversion with cause incorrect data if long value is more than max int value. toIntExact() method will throw the exception if something like this happened.


System.out.println( Long.MAX_VALUE );
System.out.println( (int)Long.MAX_VALUE );
System.out.println( Math.toIntExact(10_00_00_000) );
System.out.println( Math.toIntExact(Long.MAX_VALUE) );

Output:

9223372036854775807
-1
100000000
Exception in thread "main" java.lang.ArithmeticException: integer overflow
    at java.lang.Math.toIntExact(Math.java:1011)
    at java8features.MathematicalFuctions.main(MathematicalFuctions.java:46)

4) nextDown method

This is also a noticeable new addition in java 8 kit. This is very helpful when you have a situation where you want to return a number less than n. And the number you computed for returning happens to be exactly n. Then you can use this method to find a number closest to n, still less than n.


System.out.println( Math.nextDown(100) );
System.out.println( Math.nextDown(100.365) );

Output:

99.99999
100.36499999999998

Please note that Math.nextUp() already existed since java 6. Only Math.nextDown() is added in java 8.

That’s it folks. Hope you enjoyed reading it. Your thoughts and comments are always more than welcome.

Happy Learning !!

Comments

Subscribe
Notify of
guest
2 Comments
Most Voted
Newest Oldest
Inline Feedbacks
View all comments

About Us

HowToDoInJava provides tutorials and how-to guides on Java and related technologies.

It also shares the best practices, algorithms & solutions and frequently asked interview questions.

Our Blogs

REST API Tutorial

Dark Mode

Dark Mode