快速开方在Java中的精确度为代价(Fast sqrt in Java at the expense

2019-07-03 15:26发布

我期待在Java中的[0,2 * 10 ^ 12]输入范围内的快速平方根执行双值。 对于在此范围内的任何值,精度应高达5位小数。 换句话说,结果可以从不同Math.sqrt()后5个小数位的方法。 然而,这种方法需要比快得多Math.sqrt()

有任何想法吗? 谢谢!

Answer 1:

我不相信(不含基准,以证明这是错误的),一个纯Java实现可能比我快很多 Math.sqrt() 无论是甲骨文JRE实现和OpenJDK的实施是本地实现。



Answer 2:

一旦你给的代码时间来热身。 Math.sqrt()可以非常快

static double[] values = new double[500 * 1000];

public static void main(String... args) {
    for (int i = 0; i < values.length; i++) values[i] = i;

    for (int j = 0; j < 5; j++) {
        long start = System.nanoTime();

        for (int i = 1; i < values.length; i++) {
            values[i] = Math.sqrt(values[i]);
        }
        long time = System.nanoTime() - start;

        System.out.printf("Took %d ns to Math.sqrt on average%n", time / values.length);
    }
}

版画

Took 20 ns to Math.sqrt on average
Took 22 ns to Math.sqrt on average
Took 9 ns to Math.sqrt on average
Took 9 ns to Math.sqrt on average
Took 9 ns to Math.sqrt on average


Answer 3:

试试这个

double d = 289358932.0;
double sqrt = Double.longBitsToDouble( ( ( Double.doubleToLongBits( d )-(1l<<52) )>>1 ) + ( 1l<<61 ) );

我没有基准,但我希望它会更快。 精确度不是非常好,但尝试一下,看看它是否符合您的需求。 我想你可以添加额外的偏项a表达式的结束,使之更加精确。

编辑:您可以极大地将其通过牛顿法的圆形或两个提高精度

double better = (sqrt + d/sqrt)/2.0;
double evenbetter = (better + d/better)/2.0;

第二遍给你几乎平方根的精确值。

sqrt            17022.533813476562
better          17010.557763511835
evenbetter      17010.553547724947
Math.sqrt()     17010.553547724423


文章来源: Fast sqrt in Java at the expense of accuracy