【问题标题】:How to implement the "fast inverse square root" in Java?如何在 Java 中实现“快速反平方根”?
【发布时间】:2012-07-16 22:12:38
【问题描述】:

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

我在看代码,C 代码通过一些 C 指针魔术直接将 float 转换为 int。如果您尝试在 Java 中使用强制转换来执行此操作,则它不起作用:java 会截断浮点数(正如您所期望的那样),并且您无法获得原始指针(就像在 C 中那样)。 那你是怎么做到的呢?

【问题讨论】:

    标签: java floating-point square-root


    【解决方案1】:

    记得在使用它之前对您的代码进行基准测试。

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


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

    正如在 java.lang.Float ( http://docs.oracle.com/javase/6/docs/api/java/lang/Float.html ) 的 Javadoc 中看到的,我们有 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

    【讨论】:

    • 有人知道 0x5fe6ec85e7de30daL 从 0x5f3759df 推导吗?
    • @micycle 这些特定常数的推导随着时间的流逝而消失了,这些实际上并不是最佳常数——仅仅是著名的常数。您可以在某处找到最佳常量搜索代码。
    【解决方案2】:

    For Riking's answer,即使是双倍也可以返回 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 次似乎可以使其达到双精度的最大精度。如果你想要完美的准确性(或者如果你不应该打扰你的长小数字符串),请使用这个版本。

    【讨论】:

    • 我不明白为什么,但是循环可以解决问题并解决奇怪值0.998... 的问题。谢谢
    • @56ka 循环内的行是牛顿法的迭代。通过增加 3 次迭代,它可以提高准确性,但代价是更多的操作。
    • 其实,现在我仔细看,这不是计算 sqrt 而不是 inverse sqrt 吗?显然 1.0 存在相同的问题,但如果我仍然 4.0 进入你的代码,它会给我 2. 最后的 x*=number 应该为 invSqrt 删除
    猜你喜欢
    • 2011-10-03
    • 1970-01-01
    • 1970-01-01
    • 2018-12-02
    • 2023-04-07
    • 1970-01-01
    • 2011-12-04
    • 2016-03-15
    • 1970-01-01
    相关资源
    最近更新 更多