快速方形双倍
我正在寻找最快的双倍方式( double d
)。 到目前为止,我提出了两种方法:
1. d*d 2. Math.pow(d, 2)
为了测试性能,我设置了三个测试用例,每个测试用例使用相同的种子为三种情况生成随机数,然后计算循环中的平方数1000000次。
在第一个测试用例中,使用random.nextDouble()
生成数字,在第二种情况下使用random.nextDouble()*Double.MAX_VALUE
,在第三种情况下使用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的速度大致相同。
对数字进行平方的最快方法是将其自身相乘。
为什么
Math.pow
这么慢?
它实际上不是,但它正在执行取幂而不是简单的乘法。
为什么它会严重处理> 1,甚至更差,<-1数
首先,因为它做了数学。 从Javadoc它还包含许多极端情况的测试。 最后,我不会过分依赖你的微观基准。
通过与自身相乘来平方是最快的 。 因为approch可以直接转换为简单的非分支字节码(因此,间接地,机器代码)。
Math.pow()是一个非常复杂的函数,它为边缘情况提供了各种保证。 它需要被调用而不是内联。
Math.pow()
很慢,因为它必须处理通用情况或将数字提升到任何给定的功率。
至于为什么它的负数较慢,这是因为它必须测试功率是正还是负以给出符号,所以这是另外一个操作。