Быстрый sqrt в Java за счет точности

Я ищу быструю реализацию квадратного корня в Java для двойных значений во входном диапазоне [0, 2*10^12]. Для любого значения в этом диапазоне точность должна составлять до 5 знаков после запятой. Другими словами, результат может отличаться от Math.sqrt() метод после 5 знаков после запятой. Однако этот метод должен быть намного быстрее, чем Math.sqrt().

какие идеи? Спасибо!

3 ответов


Я не верю (без эталона, чтобы доказать это неправильно), что чистая реализация Java может меня быстрее чем Math.sqrt(). Оба реализация Oracle JRE и реализация OpenJDK родные реализаций.


Как только вы дадите коду время разогреться. Математика.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 В конце выражения, чтобы сделать его более точным.

EDIT: вы можете значительно повысить точность, пропустив его через раунд или два метода Ньютона

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