9

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

public static long round(double d) {

    if (d > 0) {
        return (long) (d + 0.5d);
    } else {
        return (long) (d - 0.5d);
    }
}

它利用了这样一个事实,即在 Java 中,将长舍入截断为零。

4

3 回答 3

15

内置方法可以处理一些特殊情况,而您的代码无法处理这些情况。从文档中:

  • 如果参数为NaN,则结果为 0。
  • 如果参数为负无穷大或任何小于或等于 的值Integer.MIN_VALUE,则结果等于 的值Integer.MIN_VALUE
  • 如果参数是正无穷大或任何大于或等于 的值的值Integer.MAX_VALUE,则结果等于 的值Integer.MAX_VALUE
于 2009-11-17T18:19:56.410 回答
6

我一直在对此进行测试,但这里尚未描述一个关键的潜在缺点:您正在更改舍入平局打破方法。

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 类似。我没有在其他版本上测试过。

于 2012-07-04T12:24:26.223 回答
5

是的; 你没有考虑下溢或上溢。务实地说,这对您的应用程序可能无关紧要。

于 2009-11-17T18:18:12.300 回答