Java 快速平方双

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/25205750/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-10 23:52:48  来源:igfitidea点击:

Quickly square a double

javaperformancemathmultiplication

提问by Samuel

I am looking for the fastest way to square a double (double d). So far I came up with two approaches:

我正在寻找平方双 ( double d)的最快方法。到目前为止,我想出了两种方法:

1. d*d
2. Math.pow(d, 2)

To test the performance I set up three test cases, in each I generate random numbers using the same seed for the three cases and just calculate the squared number in a loop 100 000 000 times.

为了测试性能,我设置了三个测试用例,在每个测试用例中,我使用三个用例的相同种子生成随机数,并在循环中计算平方数 100 000 000 次。

In the first test case numbers are generated using random.nextDouble(), in the second case using random.nextDouble()*Double.MAX_VALUEand in the third one using random.nextDouble()*Double.MIN_VALUE.

在第一个测试用例中使用生成random.nextDouble(),在第二个用例中使用random.nextDouble()*Double.MAX_VALUE和在第三个用例中使用 random.nextDouble()*Double.MIN_VALUE

The results of a couple of runs (approximate results, theres always some variation, run using java 1.8, compiled for java 1.6 on Mac OSX Mavericks)

几次运行的结果(近似结果,总是有一些变化,使用 java 1.8 运行,在 Mac OSX Mavericks 上为 java 1.6 编译)

Approach | Case 1 | Case 2 | Case 3
---------?--------?--------?-------
    1    | ~2.16s | ~2.16s | ~2.16s
    2    | ~9s    | ~30s   | ~60s

The conclusion seems to be that approach 1 is way faster but also that Math.powseems to behave kind of weird.

结论似乎是方法 1 更快,但Math.pow似乎表现得有点奇怪。

So I have two questions:

所以我有两个问题:

  1. Why is Math.powso slow, and why does it cope badly with > 1and even worse with < -1numbers?

  2. Is there a way to improve the performance over what I suggested as approach 1? I was thinking about something like:

    long l = Double.doubleToRawLongBits(d);
    long sign = (l & (1 << 63));
    Double.longBitsToDouble((l<<1)&sign);
    
  1. 为什么Math.pow这么慢,为什么它在处理数字方面表现不佳> 1甚至更糟< -1

  2. 有没有办法比我建议的方法 1 提高性能?我在想这样的事情:

    long l = Double.doubleToRawLongBits(d);
    long sign = (l & (1 << 63));
    Double.longBitsToDouble((l<<1)&sign);
    

But that is a) wrong, and b) about the same speed as approach 1.

但这是 a) 错误,b) 与方法 1 的速度大致相同。

采纳答案by Elliott Frisch

The fastest way to square a number is to multiply it by itself.

对一个数求平方的最快方法是将其乘以自身。

Why is Math.powso slow?

为什么Math.pow这么慢?

It's really not, but it is performing exponentiationinstead of simple multiplication.

它真的不是,但它正在执行幂运算而不是简单的乘法。

and why does it cope badly with > 1 and even worse with < -1 numbers

以及为什么它处理 > 1 的情况很糟糕,处理 < -1 的数字甚至更糟

First, because it does the math. From the Javadocit also contains tests for many corner cases. Finally, I would not rely too much on your micro-benchmark.

首先,因为它进行数学运算。从Javadoc 中,它还包含对许多极端情况的测试。最后,我不会过分依赖您的微基准测试。

回答by Durandal

Squaring by multipling with self is the fastest. Because that approch can be directly translated into simple, non-branching bytecode (and thus, indirectly, machine code).

乘以 self 进行平方是最快的。因为该方法可以直接转换为简单的、无分支的字节码(因此间接地转换为机器码)。

Math.pow()is a quite complex function that comes with various guarantees for edge cases. And it need to be called instead of being inlined.

Math.pow()是一个非常复杂的函数,它为边缘情况提供了各种保证。它需要被调用而不是被内联。

回答by Varpie

Math.pow()is slow because it has to deal with the generic case or raising a number to any given power.
As for why it is slower with negative numbers, it is because it has to test if the power is positive or negative in order to give the sign, so it is one more operation to do.

Math.pow()很慢,因为它必须处理一般情况或将数字提高到任何给定的幂。
至于为什么用负数会慢,是因为它要测试幂是正数还是负数才能给出符号,所以又要做一个操作。