中文第一计算机图形学社区OpenGPU 版权所有2007-2018

 找回密码
 注册

扫一扫,访问微社区

搜索
查看: 5687|回复: 8

卡马克平方根倒数的精确度为什么没有sqrt精确?

[复制链接]
发表于 2013-7-18 21:09:59 | 显示全部楼层 |阅读模式
本帖最后由 Razor87 于 2013-7-18 21:13 编辑

代码如下:
[code=cpp]#include <iostream> #include <math.h>
using namespace std;

float InvSqrt (float x)
{
        float xhalf = 0.5f*x;
        int i = *(int*)&x;
        i = 0x5f3759df - (i >> 1); // 计算第一个近似根
        x = *(float*)&i;
        x = x*(1.5f - xhalf*x*x); // 牛顿迭代法
        return x;
}

float CarmSqrt(float x){
        union{
                int intPart;
                float floatPart;
        } convertor;
        union{
                int intPart;
                float floatPart;
        } convertor2;
        convertor.floatPart = x;
        convertor2.floatPart = x;
        convertor.intPart = 0x1FBCF800 + (convertor.intPart >> 1);
        convertor2.intPart = 0x5f3759df - (convertor2.intPart >> 1);
        return 0.5f*(convertor.floatPart + (x * convertor2.floatPart));
}

int main()
{
        float a = 0.25;

        cout << InvSqrt(a) << endl;
        cout << CarmSqrt(a) << endl;
        cout << sqrt(a) << endl;

        return 0;
}[/code]
结果如下:
[code=cpp]1.99661     
0.488594
0.5
请按任意键继续. . .[/code]
为什么卡马克算法误差这么大?




发表于 2013-7-19 04:15:00 | 显示全部楼层
因为迭代一次是不够的,多几次会精确很多。另外,那个常数有个更好的值0x5f375a86,看这里http://www.lomont.org/Math/Papers/2003/InvSqrt.pdf。不过话说你举的这个例子来看,精度也还好咯,比你给的另一个CarmSqrt高了几个数量级。
发表于 2013-7-19 14:59:37 | 显示全部楼层
InvSqrt 函数内容是不是写错了
怎么错这么多
发表于 2013-7-19 17:52:03 来自手机 | 显示全部楼层
速度和精度不可能两全其美。
发表于 2013-7-20 01:06:22 | 显示全部楼层
代码没错,只是cout << InvSqrt(a) << endl;应该改成cout << 1.0f / InvSqrt(a) << endl;。所以我提到了就这个例子来说,精度已经很不错了。
发表于 2013-7-21 12:27:06 | 显示全部楼层
gongminmin 发表于 2013-7-20 01:06
代码没错,只是cout

多了一步求倒数,效率上是否会有大影响?请问一下,在实际运用中,InvSqrt和CarmSqrt用哪一个更好啊
发表于 2013-7-21 13:07:34 | 显示全部楼层
animaseed 发表于 2013-7-21 12:27
多了一步求倒数,效率上是否会有大影响?请问一下,在实际运用中,InvSqrt和CarmSqrt用哪一个更好啊 ...

倒数也有近似的方式,只是那样精度会进一步下降。目前我还没用过carm,要么就是sqrt,要么就是1 / inv的版本。
发表于 2013-7-21 15:21:39 | 显示全部楼层
gongminmin 发表于 2013-7-21 13:07
倒数也有近似的方式,只是那样精度会进一步下降。目前我还没用过carm,要么就是sqrt,要么就是1 / inv的 ...

了解了,谢谢龚大回复
发表于 2017-7-8 01:54:56 | 显示全部楼层
x = x*(1.5f - xhalf*x*x) 这个牛顿迭代可以做两次提高精度,另外我自研究发现 使用 1.f / 结果 的方式把数据倒回来偏大,x * 结果 的方式又偏小,于是我就试着把这两个平方根结果求了一下平均值,便发现精度果然大大提高,和两次牛顿迭代一组合几乎就跟C库结果完全一样。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

关于我们|小黑屋|Archiver|手机版|中文第一计算机图形学社区OpenGPU

GMT+8, 2018-6-18 06:01 , Processed in 0.053630 second(s), 19 queries .

Powered by Discuz! X3.4

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表