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.
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 ofInteger.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 ofInteger.MAX_VALUE
.
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.
Yes; you're not accounting for underflow or overflow. Pragmatically speaking, this may not matter for your application.
精彩评论