- 1、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。。
- 2、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载。
- 3、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
- 4、该文档为VIP文档,如果想要下载,成为VIP会员后,下载免费。
- 5、成为VIP后,下载本文档将扣除1次下载权益。下载后,不支持退款、换文档。如有疑问请联系我们。
- 6、成为VIP后,您将拥有八大权益,权益包括:VIP文档下载权益、阅读免打扰、文档格式转换、高级专利检索、专属身份标志、高级客服、多端互通、版权登记。
- 7、VIP文档为合作方或网友上传,每下载1次, 网站将根据用户上传文档的质量评分、类型等,对文档贡献者给予高额补贴、流量扶持。如果你也想贡献VIP文档。上传文档
查看更多
快速平方根算法 (1)
默认分类 2010-09-03 06:42:49 阅读 16 评论 0 字号:大中小 订阅
快速平方根算法
在 3D 图形编程中,经常要求平方根或平方根的倒数,例如:求向量的长度或将向量归一化。 C 数学函数
库中的 sqrt 具有理想的精度, 但对于 3D 游戏程式来说速度太慢。 我们希望能够在保证足够的精度的同时,
进一步提高速度。
Carmack 在 QUAKE3 中使用了下面的算法,它第一次在公众场合出现的时候,几乎震住了所有的人。据
说该算法其实并不是 Carmack 发明的,它真正的作者是 Nvidia 的 Gary Tarolli (未经证实)。
//
// 计算参数 x 的平方根的倒数
//
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;
}
该算法的本质其实就是 牛顿迭代法 (Newton-Raphson Method ,简称 NR ),而 NR 的基础则是 泰勒级数
(Taylor Series )。NR 是一种求方程的近似根的方法。首先要估计一个与方程的根比较靠近的数值,然后
根据公式推算下一个更加近似的数值,不断重复直到可以获得满意的精度。其公式如下:
函数: y=f(x)
其一阶导数为: y=f(x)
则方程: f(x)=0 的第 n+1 个近似根为
x[n+1] = x[n] - f(x[n]) / f(x[n])
NR 最关键的地方在于估计第一个近似根。如果该近似根与真根足够靠近的话,那么只需要少数几次迭代,
就可以得到满意的解。
现在回过头来看看如何利用牛顿法来解决我们的问题。 求平方根的倒数, 实际就是求方程 1/(x^2)-a=0 的解。
将该方程按牛顿迭代法的公式展开为:
x[n+1]=1/2*x[n]*(3-a*x[n]*x[n])
将 1/2 放到括号里面,就得到了上面那个函数的倒数第二行。
接着,我们要设法估计第一个近似根。这也是上面的函数最神奇的地方。它通过某种方法算出了一个与真
根非常接近的近似根,因此它只需要使用一次迭代过程就获得了较满意的解。它是怎样做到的呢?所有的
奥妙就在于这一行:
i = 0x5f3759df - (i 1); // 计算第一个近似根
超级莫名其妙的语句,不是吗?但仔细想一下的话,还是可以理解的。我们知道, IEEE 标准下, float 类
型的数据在 32 位系统上是这样表示的 (大体来说就是这样, 但省略了很多细节, 有兴趣可以 GOOGLE ):
bits :31 30 ... 0
31 :符号位
30-23 :共 8 位,保存指数( E)
22-0 :共 23 位,保存尾数( M )
所以, 32 位的浮点数用十进制实数表示就是: M*2^E 。开根然后倒数就是: M^(-1/2)*2^(-E/2) 。现在就十
分清晰了。语句 i1 其工作就是将指数除以 2,实现 2^(E/2) 的部分。而前面用一个常数减去它,目的就
是得到 M^(1/2) 同时反转所有指数的符号。
至于那个 0x5f3759df ,呃,我只能说,的确是一个超级的 Magic Number 。
那个 Magic Number 是可以推导出来的,但我并不打算在这里讨论,因为实在太繁琐了。简单来说,其原
理如下:因为 IEEE
文档评论(0)