Faster implementation of Math.round?

Are there any flaws in this code that look faster (and the correct) version of java.lang.Math.round ?

 public static long round(double d) { if (d > 0) { return (long) (d + 0.5d); } else { return (long) (d - 0.5d); } } 

It uses the fact that in Java, trimming to long rounds to zero.

+5
java math micro-optimization rounding
Nov 17 '09 at 18:13
source share
3 answers

There are some special cases that an inline method handles that your code does not handle. From the documentation:

  • If the argument is NaN , the result is 0.
  • If the argument has negative infinity or any value less than or equal to the value of Integer.MIN_VALUE , the result is equal to the value of Integer.MIN_VALUE .
  • If the argument is positive infinity or any value greater than or equal to the value of Integer.MAX_VALUE , the result is equal to the value of Integer.MAX_VALUE .
+15
Nov 17 '09 at 18:19
source share

Yes; You do not account for underutilization or overflow. This, by right, does not matter for your application.

+5
Nov 17 '09 at 18:18
source share

I tested this, and there is one key potential flaw that has not yet been described here: you are changing tie-break rounding .

Math.round() implements the "round half up" rule, while your round() method implements the "round half away from zero" rule.

For example:

  • Math.round(-0.5d) => 0L
  • Your.round(-0.5d) => -1L

This may or may not be a problem for you, but you should understand that the above method is not a replacement for Math.round() , even after considering the considerations of NaN and infinity.

Another topical issue: Rounding negative numbers in Java

As for performance, there is no doubt that the above method is much faster than Math.round() - it works in about 35% of cases for randomly generated positive and negative values. This may be a worthwhile optimization when calling this method in a narrow loop. This is even better (25% of runtime) when only positive values ​​are given, possibly because of a processor using branch prediction .

Math.round() is ultimately implemented using a native JNI call, which can cause a difference in performance. This Sun / Oracle error suggests that there may be a pure-Java version in j6u22, but I don’t see where Math.round() really is in my tests, j6u23 performs similarly to j6u16. I have not tested other versions.

+3
Jul 04 2018-12-12T00:
source share



All Articles