快速平方双精度

2022-09-01 19:17:56

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

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

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

在第一个测试用例中,数字是使用 生成的,在第二个用例中使用 ,在第三个测试用例中使用 。random.nextDouble()random.nextDouble()*Double.MAX_VALUErandom.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的速度大致相同。


答案 1

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

为什么这么慢?Math.pow

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

以及为什么它对>1的处理能力很差,而对<-1数字的处理甚至更糟。

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


答案 2

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

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


推荐