如何在Java中实现“快速反平方根”?

2022-09-02 20:57:45

我听说过这里讨论的“快速平方反比”,我想把它放在我的Java程序中(只是为了研究目的,所以忽略任何关于本机库更快的事情)。

我正在查看代码,C代码直接将一些C指针魔术转换为a。如果你尝试在Java中使用强制转换来执行此操作,它不起作用:java截断浮点数(如您所料),并且您无法获取基元的指针(就像在C中一样)。那么你是怎么做到的呢?floatint


答案 1

请记住在使用它之前对代码进行基准测试。

如果事实证明你不需要它,或者它在你正在使用的CPU架构上更慢,那么最好不要在你的项目中使用这个迟钝的代码。


Java库有一种方法可以从浮点数到原始位。

正如在 Javadoc for ( http://docs.oracle.com/javase/6/docs/api/java/lang/Float.html ) 中看到的,我们有函数,以及 .java.lang.FloatfloatToIntBitsintBitsToFloat

这意味着我们可以在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 次似乎可以将其降低到双精度的最大精度。如果你想要完美的准确性(或者如果长串的小数,它们不应该打扰你),请使用这个版本。