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.
//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
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
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 !!