求平方根的倒数速算法--向卡马克等人致敬

昨日,风雨交加,气温骤降,所有人都蜷缩在不暖和的厚衣服里,无神的盯着显示器。我也不例外,颤抖的手点击着鼠标,一边埋怨这天气,一边埋怨这电脑。突然,一段代码映入眼帘,定睛一看,没看懂,代码是这样的:

float Q_rsqrt( float number )
{
    long i;
    float x2, y;
    const float threehalfs = 1.5F;

    x2 = number * 0.5F;
    y  = number;
    i  = * ( long * ) &y;    // 这TM是啥
    i  = 0x5f3759df - ( i >> 1 );  // 这TM又是啥
    y  = * ( float * ) &i; // 这TM到底是啥
    y  = y * ( threehalfs - ( x2 * y * y ) );   // 这.......
//      y  = y * ( threehalfs - ( x2 * y * y ) );   // .........

    return y;
}

这段代码出自《雷神之锤3》,求平方根的倒数,速度号称比通常 求根号,取倒数的计算方法快四倍,我瞬即一愣,不知哪来的热气,包裹着我的身体,驱赶着寒冷,除却了颤抖,凝结在心中的只有一个念头:这TM到底是啥。

好吧,其实在以下只有一句是关键:

 i  = 0x5f3759df - ( i >> 1 );  // 这TM又是啥

下文将重点分析上面那一句,但是文章嘛,要有开头结尾,好,当我前面都没说,咱们从头再来:

时间: 2024-10-12 15:32:15

求平方根的倒数速算法--向卡马克等人致敬的相关文章

平方根倒数速算法(卡马克开方法)

平方根倒数速算法(Fast inverse square root),经常和一个十六进制的常量 0x5f3759df联系起来.该算法被用来快速运算平方根倒数,速度是 float(1/sqrt(x)) 方法的4倍.该算法大概由上个世纪90年代的硅图公司开发出来,后来出现在John Carmark的Quake III Arena的源码中. 这是一个古老的算法,最早的讨论见于2001年中国的CSDN论坛上.并且该段代码可能已经不适用于当代的64bits机器,因为现在的64bits的机器上 long 型

Fast InvSqrt()(平方根倒数速算法)

浮点数的平方根倒数常用于计算正规化矢量.3D图形程序需要使用正规化矢量来实现光照和投影效果,因此每秒都需要做上百万次平方根倒数运算,而在处理坐标转换与光源的专用硬件设备出现前,这些计算都由软件完成,计算速度亦相当之慢.在1990年代这段代码开发出来之时,多数浮点数操作的速度更是远远滞后于整数操作.因而针对正规化矢量算法的优化就显得尤为重要.下面陈述计算正规化矢量的原理: 要将一个矢量标准化,就必须计算其欧几里德范数,以求得矢量长度,为此便需对矢量的各分量的平方和求平方根:而当求取到其长度,并以之

速求平方根倒数

在游戏3D建模方面很多时候要用到求平方根的倒数,而本文章打算介绍的算法会比正常算法快上4倍左右.这对于产品性能将是一个大幅度的提高. 那我们要从哪里开始呢?首先不得不提一提 idsoftware.这是一个创建之初只有13个人的小公司,但它推出的毁灭战士(DOOM)系列游戏可以说改变了游戏世界,极大地推动了游戏产业的发展,因为在当时贫瘠的电脑性能的支撑下,一个开发者能够在游戏中加入一段流畅的动画都会让人惊叹不已,而我们所说的idsoftware,在那个年代就已经做出了画面远超同代其余作品的游戏,像

平方根(sqrt)算法

最近听说开平方算法挺难写,自己思考一下确实这些库函数只是一直在用,但是很少去思考如何实现的,sqrt在排序中使用频率非常的高,所以就研究了一下.大概有三种实现方式. 一.用二分的方法 每次用中间数就试,如果大就到左区间选取中间数试,如果小就到右区间找中间数试,采用不断逼近的方式计算平方根,这种方式迭代次数有点多,且每次试验都要进行运算,效率不是很高,但是思路简单,巧妙的运用了二分的方法. #define eps 0.00000001 float SqrtByBisection(float n)

sqrt函数实现之卡马克方法

sqrt函数的实现主要有三种方式: 二分法 牛顿法 卡马克方法 这里主要介绍高效的卡马克方法.卡马克方法起源于<雷神之锤III竞技场>中使用的平方根倒数速算法,下列代码是平方根倒数速算法在<雷神之锤III竞技场>源代码中的应用实例.示例剥离了C语言预处理器的指令,但附上了原有的注释: float Q_rsqrt( float number ) { long i; float x2, y; const float threehalfs = 1.5F; x2 = number * 0.

经典算法:牛顿迭代法求平方根

//牛顿迭代法求平方根 1 double mysqrt(double num) 2 { 3 double x = num/2; 4 double y = 0; 5 do{ 6 x = x/2+num/(2*x); 7 y = x*x-num; 8 if(y<0) y = -y; 9 } while(y>0.0001); 10 return x; 11 } 12 int main(int argc, char* argv[]) 13 { 14 printf("%.3f",my

算法练习之牛顿法求平方根

牛顿法求平方根公式:Xn+1 = 1/2 * (Xn+ a/Xn); 若求a的平方根,将公式进行迭代计算迭代越多,越接近结果最后Xn为a的平方根 代码实现: 参数:要求平方根的数,迭代次数 var sqrt = function (a,accur){ var pre = 1; for(var i = 0;i<accur;i++){ var cur = 1/2 * (pre + a/pre); pre = cur; } return cur; } console.log(sqrt(2,10000)

求平方根算法 Heron’s algorithm

求平方根问题 概述:本文介绍一个古老但是高效的求平方根的算法及其python实现,分析它为什么可以快速求解,并说明它为何就是牛顿迭代法的特例. 问题:求一个正实数的平方根. 给定正实数 \(m\),如何求其平方根\(\sqrt{m}\)? 你可能记住了一些完全平方数的平方根,比如\(4, 9, 16, 144, 256\)等.那其它数字(比如\(105.6\))的平方根怎么求呢? 实际上,正实数的平方根有很多算法可以求.这里介绍一个最早可能是巴比伦人发现的算法,叫做Heron's algorit

C语言之基本算法11—牛顿迭代法求平方根

//迭代法 /* ================================================================== 题目:牛顿迭代法求a的平方根!迭代公式:Xn+1=(Xn+a/Xn)/2. ================================================================== */ #include<stdio.h> #include<math.h> main() { float a,x0,x1;