快速方形双倍

时间:2014-08-08 14:25:09

标签: java performance math multiplication

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

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

为了测试性能,我设置了三个测试用例,每个测试用例使用相同的种子为三种情况生成随机数,然后计算循环中的平方数1000000次。

在第一个测试案例中,使用random.nextDouble()生成数字,第二种情况使用random.nextDouble()*Double.MAX_VALUE,第三种情况使用random.nextDouble()*Double.MIN_VALUE

几次运行的结果(近似结果,总是有些变化,使用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

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

所以我有两个问题:

1 为什么Math.pow如此缓慢,为什么它会与> 1严重对应,而对于< -1数字则更糟?

2 有没有办法提高性能超过我建议的方法1?我在考虑类似的事情:

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

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

3 个答案:

答案 0 :(得分:9)

对数字求平方的最快方法是将其自身相乘。

  

为什么Math.pow这么慢?

实际上并非如此,但它正在执行exponentiation而不是简单的乘法。

  

为什么它与&gt;严重对应? 1,甚至更糟糕的&lt; -1个数字

首先,因为它做数学。从Javadoc它还包含许多极端情况的测试。最后,我不会过分依赖你的微观基准。

答案 1 :(得分:5)

通过与自身相乘进行平方是最快的。因为approch可以直接转换为简单的非分支字节码(因此,间接地,机器代码)。

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

答案 2 :(得分:2)

Math.pow()很慢,因为它必须处理一般情况或将数字提升到任何给定的权力 至于为什么它的负数较慢,这是因为它必须测试功率是正还是负以给出符号,所以这是另外一个操作。