问题
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 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
.
回答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