Math.round 的实施速度更快?

发布于 2024-08-11 16:56:14 字数 278 浏览 4 评论 0原文

此代码似乎是 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 中,将长舍入截断为零。

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

柳若烟 2024-08-18 16:56:14

有一些特殊情况 是内置方法处理的,而您的代码不处理的。来自文档:

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

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.
忘东忘西忘不掉你 2024-08-18 16:56:14

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

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

例如:

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

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

另一个相关问题:Rounding negative Numbers in Java

至于性能,毫无疑问上述方法明显比 Math.round() 快 - 对于随机生成的正值和负值,它的运行时间约为 35%。在紧密循环中调用此方法时,这可能是一项有价值的优化。当仅给出正值时,效果甚至更好(运行时间的 25%),可能是因为 CPU 使用 分支预测

Math.round() 最终由本机 JNI 调用实现,这可能是性能差异的原因。 此 Sun/Oracle bug 表明 j6u22 中可能存在纯 Java 版本,但我看不出在哪里,而且在我的测试中,j6u23 中的 Math.round() 的表现确实与 j6u16 类似。我没有在其他版本上测试过。

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.

无声情话 2024-08-18 16:56:14

是的;您没有考虑下溢或溢出。务实地说,这对您的应用程序可能并不重要。

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文