更快地实现Math.round?

mrj*_*bq7 9 java math rounding micro-optimization

这段代码是否有任何缺点,这似乎是一个更快(和更正)的版本java.lang.Math.round

public static long round(double d) {

    if (d > 0) {
        return (long) (d + 0.5d);
    } else {
        return (long) (d - 0.5d);
    }
}
Run Code Online (Sandbox Code Playgroud)

它利用了这样一个事实,即在Java中,截断到长轮到零.

Kri*_*ian 15

内置方法处理的一些特殊情况,代码无法处理.从文档:

  • 如果参数是NaN,则结果为0.
  • 如果参数为负无穷大或任何小于或等于值的值Integer.MIN_VALUE,则结果等于值Integer.MIN_VALUE.
  • 如果参数为正无穷大或任何大于或等于值的值Integer.MAX_VALUE,则结果等于值Integer.MAX_VALUE.


Jon*_*erg 5

是; 你没有考虑下溢或溢出.从语用上讲,这可能对您的申请无关紧要.


Tim*_*age 5

我已经对此进行了测试,这里还没有描述一个关键的潜在缺陷:您正在更改舍入平局决胜方法。

Math.round()实现“向上舍入一半”规则,而您的round()方法实现“从零开始舍入一半”规则。

例如:

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

这可能对您来说不是问题,但您应该了解Math.round(),即使已经概述了NaN和无穷大考虑因素,上述方法也不能替代。

另一个相关问题:在Java中舍入负数

至于性能,毫无疑问,上述方法的速度明显快于Math.round()随机生成的正负值的时间大约为35%。在紧密循环中调用此方法时,这可能是值得进行的优化。如果仅给出正值,则效果会更好(运行时的25%),这可能是因为CPU使用了分支预测

Math.round()最终由本地JNI调用实现,这可能是性能差异的原因。这个Sun / Oracle错误表明j6u22中可能存在纯Java版本,但我看不到它的位置,实际上Math.round()在测试中j6u23的性能与j6u16类似。我尚未在其他版本上进行测试。