我期待在Java中的[0,2 * 10 ^ 12]输入范围内的快速平方根执行双值。 对于在此范围内的任何值,精度应高达5位小数。 换句话说,结果可以从不同Math.sqrt()
后5个小数位的方法。 然而,这种方法需要比快得多Math.sqrt()
有任何想法吗? 谢谢!
我期待在Java中的[0,2 * 10 ^ 12]输入范围内的快速平方根执行双值。 对于在此范围内的任何值,精度应高达5位小数。 换句话说,结果可以从不同Math.sqrt()
后5个小数位的方法。 然而,这种方法需要比快得多Math.sqrt()
有任何想法吗? 谢谢!
我不相信(不含基准,以证明这是错误的),一个纯Java实现可能比我快很多 Math.sqrt()
无论是甲骨文JRE实现和OpenJDK的实施是本地实现。
一旦你给的代码时间来热身。 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
试试这个
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