###### sqrt函数实现--牛顿迭代法（重点）

float SqrtByBisection(float n) //用二分法
{
if(n<0) //小于0的按照你需要的处理
return n;
float mid,last;
float low,up;
low=0,up=n;
mid=(low+up)/2;
do
{
if(mid*mid>n)
up=mid;
else
low=mid;
last=mid;
mid=(up+low)/2;
}while(abs(mid-last) > eps);//精度控制
return mid;
} 

(       4  + 2/4        ) / 2 = 2.25
(     2.25 + 2/2.25     ) / 2 = 1.56944..
( 1.56944..+ 2/1.56944..) / 2 = 1.42189..
( 1.42189..+ 2/1.42189..) / 2 = 1.41423..
....

float SqrtByNewton(float x)
{
float val = x;//最终
float last;//保存上一个计算的值
do
{
last = val;
val =(val + x/val) / 2;
}while(abs(val-last) > eps);
return val;
}

float InvSqrt(float x)
{
float xhalf = 0.5f*x;
int i = *(int*)&x; // get bits for floating VALUE
i = 0x5f375a86- (i>>1); // gives initial guess y0
x = *(float*)&i; // convert bits BACK to float
x = x*(1.5f-xhalf*x*x); // Newton step, repeating increases accuracy
x = x*(1.5f-xhalf*x*x); // Newton step, repeating increases accuracy
x = x*(1.5f-xhalf*x*x); // Newton step, repeating increases accuracy

return 1/x;
}


Quake-III Arena (雷神之锤3)是90年代的经典游戏之一。该系列的游戏不但画面和内容不错，而且即使计算机配置低，也能极其流畅地运行。这要归功于它3D引擎的开发者约翰-卡马克（John Carmack）。事实上早在90年代初DOS时代，只要能在PC上搞个小动画都能让人惊叹一番的时候，John Carmack就推出了石破天惊的Castle Wolfstein, 然后再接再励，doom, doomII, Quake...每次都把3-D技术推到极致。他的3D引擎代码资极度高效，几乎是在压榨PC机的每条运算指令。当初MS的Direct3D也得听取他的意见，修改了不少API。

http://www.fileshack.com/file.x?fid=7547

(下面是官方的下载网址，搜索 “quake3-1.32b-source.zip” 可以找到一大堆中文网页的。ftp://ftp.idsoftware.com/idstuff/source/quake3-1.32b-source.zip)

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

x2 = number * 0.5F;
y   = number;
i   = * ( long * ) &y;   // evil floating point bit level hacking
i   = 0x5f3759df - ( i >> 1 ); // what the fuck?
y   = * ( float * ) &i;
y   = y * ( threehalfs - ( x2 * y * y ) ); // 1st iteration
// y   = y * ( threehalfs - ( x2 * y * y ) ); // 2nd iteration, this can be removed

#ifndef Q3_VM
#ifdef __linux__
assert( !isnan(y) ); // bk010122 - FPE?
#endif
#endif
return y;
}  

i = 0x5f3759df - ( i >> 1 );

Lomont为此写下一篇论文，"Fast Inverse Square Root"。 论文下载地址：
http://www.math.purdue.edu/~clomont/Math/Papers/2003/InvSqrt.pdf
http://www.matrix67.com/data/InvSqrt.pdf

float InvSqrt(float x)
{
float xhalf = 0.5f*x;
int i = *(int*)&x; // get bits for floating VALUE
i = 0x5f375a86- (i>>1); // gives initial guess y0
x = *(float*)&i; // convert bits BACK to float
x = x*(1.5f-xhalf*x*x); // Newton step, repeating increases accuracy
return 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;
}

PS. 这个 function 之所以重要，是因为求 开根号倒数 这个动作在 3D 运算 (向量运算的部份) 里面常常会用到，如果你用最原始的 sqrt() 然后再倒数的话，速度比上面的这个版本大概慢了四倍吧… XD
PS2. 在他们追寻的过程中，有人提到一份叫做 MIT HACKMEM 的文件，这是 1970 年代的 MIT 强者们做的一些笔记 (hack memo)，大部份是 algorithm，有些 code 是 PDP-10 asm 写的，另外有少数是 C code (有人整理了一份列表)

# 求平方根倒数的算法

float InvSqrt (float x){
float xhalf = 0.5f*x;
int i = *(int*)&x;
i = 0x5f3759df - (i>>1);
y = *(float*)&i;
y = y*(1.5f - xhalf*x*x);
return x;
}

int i = *(int*)&x; 这条语句把 转成

i = 0x5f3759df - (i>>1); 这条语句从 计算

y = *(float*)&i; 这条语句将 转换为

y = y*(1.5f - xhalf*y*y); 这时候的y是近似解；此步就是经典的牛顿迭代法。迭代次数越多越准确。

，用 带入之后两边取对数，再利用近似表示 ，算一算就得到

#### 牛顿迭代法实现平方根函数sqrt

2014-11-06 16:49:57

#### leetcode:Sqrt(x) 牛顿迭代法求整数开方

2014-04-10 15:46:23

#### Sqrt(x)算法详解

2015-06-26 20:45:18

#### 各种快速SQRT

2004-10-21 18:30:00

#### Java计算平方根（牛顿迭代法）

2018-01-08 11:02:12

#### 【sass】实现三角函数

2016-08-12 15:16:03

#### 北邮数值与符号计算实验 方程求根的牛顿迭代法

2016年05月26日 226KB 下载

#### 不用sqrt库函数求一个整数的平方根（牛顿迭代法）

2013-09-17 10:16:01

#### 【经典面试题】实现平方根函数sqrt

2014-08-30 17:53:19

#### sqrt函数实现（神奇的算法）

2017-06-25 18:59:52

## 不良信息举报

sqrt函数实现--牛顿迭代法（重点）