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

java floating-point square-root

7302 просмотра

2 ответа

1587 Репутация автора

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

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

Автор: Riking Источник Размещён: 16.07.2012 10:12

Ответы (2)


20 плюса

1587 Репутация автора

Решение

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

Если окажется, что он вам не нужен или он медленнее в используемой архитектуре ЦП, то лучше обойтись без этого тупого кода в вашем проекте.


У библиотек 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

Автор: Riking Размещён: 16.07.2012 10:12

5 плюса

145 Репутация автора

Для ответа Рикинга , даже двойное число может вернуть что-то вроде 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 раза, кажется, снизили его до максимальной точности в два раза. Если вы хотите идеальной точности (или если длинные строки десятичных знаков там, где они не должны вас беспокоить), используйте эту версию.

Автор: Zeusoflightning125 Размещён: 03.01.2014 05:34
Вопросы из категории :
32x32