Подтвердить что ты не робот

Как реализовать "быстрый обратный квадратный корень" в Java?

Я слышал о "быстром обратном квадратном корне", обсуждался здесь, и я хотел поместить его в свою программу на Java (только для исследовательских целей, поэтому игнорировать что-либо о том, что собственные библиотеки быстрее).

Я смотрел на код, а код C напрямую преобразовывал float в int с некоторой магией указателя на C. Если вы попытаетесь сделать это на Java с приведениями, это не сработает: java усекает float (как и следовало ожидать), и вы не можете получить указатель на примитив (как вы можете на C). Итак, как вы это делаете?

4b9b3361

Ответ 1

Не забудьте проверить свой код перед использованием.

Если вам это не понадобится, или это медленнее на архитектуре процессора, которую вы используете, тогда вам лучше идти без этого тупого кода в вашем проекте.


В библиотеках Java есть способ получить от числа с плавающей точкой до необработанных битов.

Как видно из Javadoc для java.lang.Float (http://docs.oracle.com/javase/6/docs/api/java/lang/Float.html), мы имеем функцию floatToIntBits, а также intBitsToFloat.

Это означает, что мы можем написать "быстрый обратный квадратный корень" в Java следующим образом:

public static float invSqrt(float x) {
    float xhalf = 0.5f * x;
    int i = Float.floatToIntBits(x);
    i = 0x5f3759df - (i >> 1);
    x = Float.intBitsToFloat(i);
    x *= (1.5f - xhalf * x * x);
    return x;
}

Вот версия для парных:

public static double invSqrt(double x) {
    double xhalf = 0.5d * x;
    long i = Double.doubleToLongBits(x);
    i = 0x5fe6ec85e7de30daL - (i >> 1);
    x = Double.longBitsToDouble(i);
    x *= (1.5d - xhalf * x * x);
    return x;
}

Источник: http://www.actionscript.org/forums/showthread.php3?t=142537

Ответ 2

Для ответа на Riking даже двойной может вернуть материал, например 0.9983227945440889, для квадратного корня из одного.

Чтобы повысить точность, вы можете использовать эту версию, которую я сделал:

public static double Q_rsqrt(double number){
    double x = number;
    double xhalf = 0.5d*x;
    long i = Double.doubleToLongBits(x);
    i = 0x5fe6ec85e7de30daL - (i>>1);
    x = Double.longBitsToDouble(i);
    for(int it = 0; it < 4; it++){
        x = x*(1.5d - xhalf*x*x);
    }
    x *= number;
    return x;
}

Вы можете отредактировать, как долго задолго до того, как цикл for завершится, но вы хотите, но 4 раза, похоже, довели его до максимальной точности для двойника. Если вам нужна совершенная точность (или длинные строки десятичных знаков, где они не должны вас беспокоить), используйте эту версию.