卡马克的求平方根的倒数的程序(快速平方根倒数算法)

时间:2019-05-14 19:53:10下载本文作者:会员上传
简介:写写帮文库小编为你整理了多篇相关的《卡马克的求平方根的倒数的程序(快速平方根倒数算法)》,但愿对你工作学习有帮助,当然你在写写帮文库还可以找到更多《卡马克的求平方根的倒数的程序(快速平方根倒数算法)》。

第一篇:卡马克的求平方根的倒数的程序(快速平方根倒数算法)

卡马克的求平方根的倒数的程序(快速平方根倒数算法)

2009-09-18 10:45:01| 分类: 离奇的code |字号大中小 订阅

这个程序,大概在2006年看到的,当时进行了分析,主要分析了位运算那部分:如何利用浮点数的位表示法快速计算一个近似值。而对于整个迭代计算原理并没有仔细看,今天再重新分析一下,并把当时那部分分析写的更明了些。原贴如下:-------------发信人: interma(4PZP | 抓紧时间 | OFG P), 信区: C_Cpp 标

题: [zz] 源自Quake3的快速求InvSqrt()函数

发信站: 兵马俑BBS(Mon Dec 4 13:11:36 2006), 本站(202.117.1.8)http://games.solidot.org/article.pl?sid=06/12/04/0210205&from=rss

"人们很早就在Quake3源代码中发现了如下的C代码,它可以快速的求1/sqrt(x),在3D图形向量计算方面应用很广。float InvSqrt(float x){

float xhalf=0.5f*x;

long i=*(long*)&x;

i=0x5f3759df(i>>1);

x=*(float *)&i;

其他地方都比较简单,这三句的意思,应当是把x的浮点表示格式直接看出long类型的,然后进行0x5f3759df(i>>1)

对于0x5f3759df如果看成浮点数的话,其指数位为(0101)(1111)0->1011111=190

设原来的xIEEE表示的指数位为a则新的结果的指数位变成了190-a/2;注意如果要转换成

m*2^n格式,需要将指数a-127;所以得到的新结果用数学表示的指数位为190-a/2-127= 63-a/2

而x的原来如果从ieee格式变成数学表示应为a-127

比较63-a/2与a-127

可以看出指数之间的关系为63-a/2==(a-127)*(-1/2)

所以经过上述三句,x应该已经是1/sqrt(x)的近似值

然后下面的应该是继续进行了精化,具体依据还没搞懂

【 在 interma(4PZP | 抓紧时间 | OFG P)的大作中提到: 】

☆──────────────────────────────────────☆

xiaocui 于 Tue Dec 5 10:06:34 2006 提到:

厉害。

【 在 phylips(爱立佛)的大作中提到: 】

☆──────────────────────────────────────☆

NemoK 于 Tue Dec 5 11:58:01 2006 提到:

re!

【 在 phylips(爱立佛)的大作中提到: 】

☆──────────────────────────────────────☆

zqfalcon 于 Tue Dec 5 12:01:02 2006 提到:

呵呵大牛啊,佩服

【 在 phylips 的大作中提到: 】

------------------------

首先看牛顿迭代法的原理

若函数f(x)在点的某一临域内具有直到(n+1)阶导数,则在该邻域内f(x)的n阶泰勒公式为:

f(x)= f(x0)+(x-x0)f'(x0)+(x-x0)^2*f''(x0)/2!+… +...fn(x0)(x-x0)n/n!....解非线性方程f(x)=0的牛顿法是把非线性方程线性化的一种近似方法。把f(x)在x0点附近展开成泰勒级数 f(x)= f(x0)+(x-x0)f'(x0)+(x-x0)^2*f''(x0)/2!+… 取其线性部分,作为非线性方程f(x)= 0的近似方程,即泰勒展开的前两项,则有f(x0)+f'(x0)(x-x0)=f(x)=0 设f'(x0)≠0则f(x0)+f'(x0)(x-x0)=0 其解为x1=x0-f(x0)/f'(x0)这样,得到牛顿法的一个迭代序列:x(n+1)=x(n)-f(x(n))/f'(x(n))。也就是说x(n+1)=x(n)-f(x(n))/f'(x(n)),是用来计算f(x)=0的根的迭代公式,如果x(n)与真根足够靠近的话,那么只需要少数几次迭代,就可以得到满意的解。我们现在要求的是一个数的平方根的倒数,设这个数为a,那么我们要计算的就是x= a^(-0.5)。首先我们要把这个计算需求转换为f(x)=0的形式。x = a^(-0.5)x^(-2)= a x^(-2)-a = 0 这样就转化成了f(x)= 0的形式,其中x就是a的平方根的倒数。f(x)= x^(-2)-a 则f'(x)=-2*x^(-3)根据牛顿迭代公式可以得到

x(n+1)= x(n)a)/(-2*x(n)^(-3))x(n+1)= x(n)+(x(n)^(-2)(a*x(n)^3)/2 x(n+1)= 1.5*x(n)(i>>1);

x=*(float *)&i;其他地方都比较简单,这三句的意思,应当是把x的浮点表示格式直接看出long类型的,然后进行0x5f3759df(i>>1);对于0x5f3759df如果看成浮点数的话,二进制位为.10111110.***11011111,其指数位为10111110=190。设原来的x的IEEE表示的指数位为a则新的结果的指数位变成了190-a/2;注意如果要转换成m*2^n格式,需要将指数减去127;所以得到的新结果用数学表示的指数位为190-a/2-127= 63-a/2,而x的原来的指数a,如果从ieee格式变成数学表示应为a-127。

比较63-a/2与a-127,可以看出指数之间的关系为63-a/2==(a-127)*(-1/2)所以经过上述三句,x应该已经是1/sqrt(x)的近似值。当然上面只是从指数位进行了简单分析,如果要细化到尾数,还需要看具体效果。

--------------以下摘自:http://tbl.javaeye.com/blog/231425 雷神之锤III》里求平方根倒数的函数(快速平方根(倒数)算法)

至于那个0x5f3759df,呃,我只能说,的确是一个超级的Magic Number。那个Magic Number是可以推导出来的,但我并不打算在这里讨论,因为实在太繁琐了。简单来说,其原理如下:因为IEEE的浮点数中,尾数M省略了最前面的1,所以实际的尾数是1+M。如果你在大学上数学课没有打瞌睡的话,那么当你看到(1+M)^(-1/2)这样的形式时,应该会马上联想的到它的泰勒级数展开,而该展开式的第一项就是常数。下面给出简单的推导过程:

对于实数R>0,假设其在IEEE的浮点表示中,指数为E,尾数为M,则: R^(-1/2)=(1+M)^(-1/2)* 2^(-E/2)将(1+M)^(-1/2)按泰勒级数展开,取第一项,得: 原式

=(1-M/2)* 2^(-E/2)= 2^(-E/2)(M/2)*2^(E/2)= C(R>>1)求出令到相对误差最小的C值就可以了

上面的推导过程只是我个人的理解,并未得到证实。而Chris Lomont则在他的论文中详细讨论了最后那个方程的解法,并尝试在实际的机器上寻找最佳的常数C。

而Chris Lomont则在他的论文中详细讨论了最后那个方程的解法,并尝试在实际的机器上寻找最佳的常数C。

所以,所谓的Magic Number,并不是从N元宇宙的某个星系由于时空扭曲而掉到地球上的,而是几百年前就有的数学理论。只要熟悉NR和泰勒级数,你我同样有能力作出类似的优化。

在GameDev.net上有人做过测试,该函数的相对误差约为0.177585%,速度比C标准库的sqrt提高超过20%。如果增加一次迭代过程,相对误差可以降低到e-004的级数,但速度也会降到和sqrt差不多。据说在DOOM3中,Carmack通过查找表进一步优化了该算法,精度近乎完美,而且速度也比原版提高了一截。值得注意的是,在Chris Lomont的演算中,理论上最优秀的常数(精度最高)是0x5f37642f,并且在实际测试中,如果只使用一次迭代的话,其效果也是最好的。但奇怪的是,经过两次NR后,在该常数下解的精度将降低得非常厉害(天知道是怎么回事!)。经过实际的测试,Chris Lomont认为,最优秀的常数是0x5f375a86。如果换成64位的double版本的话,算法还是一样的,而最优常数则为0x5fe6ec85e7de30da(又一个令人冒汗的Magic Number--b)。这个算法依赖于浮点数的内部表示和字节顺序,所以是不具移植性的。如果放到Mac上跑就会挂掉。如果想具备可移植性,还是乖乖用sqrt好了。但算法思想是通用的。大家可以尝试推算一下相应的平方根算法。

下载卡马克的求平方根的倒数的程序(快速平方根倒数算法)word格式文档
下载卡马克的求平方根的倒数的程序(快速平方根倒数算法).doc
将本文档下载到自己电脑,方便修改和收藏,请勿使用迅雷等下载。
点此处下载文档

文档为doc格式


声明:本文内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:645879355@qq.com 进行举报,并提供相关证据,工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。

相关范文推荐