Faster implementation of Math.round?

℡╲_俬逩灬. 提交于 2019-12-22 04:30:42

问题


Are there any drawbacks to this code, which appears to be a faster (and 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 takes advantage of the fact that, in Java, truncating to long rounds in to zero.


回答1:


There are some special cases which the built in method handles, which your code does not handle. From the documentation:

  • If the argument is NaN, the result is 0.
  • If the argument is 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.



回答2:


Yes; you're not accounting for underflow or overflow. Pragmatically speaking, this may not matter for your application.




回答3:


I've been testing this, and there is one key potential drawback which has not yet been described here: You are changing the rounding tie-breaking method.

Math.round() implements the "round half up" rule, whereas 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 drop-in replacement for Math.round(), even after the NaN and infinity considerations already outlined.

Another relevant question: Rounding negative numbers in Java

As for the performance, there is no doubt that the above method is significantly faster than Math.round() - it runs in about 35% of the time for randomly generated positive and negative values. This can be a worthwhile optimisation when calling this method in a tight loop. It's even better (25% of the runtime) when given only positive values, possibly because of the CPU using branch prediction.

Math.round() is ultimately implemented by a native JNI call, which might be the cause of the performance difference. This Sun/Oracle bug suggests there might be pure-Java version in j6u22, but I can't see where, and indeed Math.round() in j6u23 performs similarly to j6u16 in my tests. I have not tested on other versions.



来源:https://stackoverflow.com/questions/1750739/faster-implementation-of-math-round

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!