如果普通地用牛顿法求一个数的平方根倒数,应该是这样的:
float myrsqrt(float a, float x){
for(int i=0 ; i<4 ; i++){
x = x*(1.5-((a*0.5)*x*x));
}
return x;
}
其中a是你要求的数,而x是这个迭代式的一个初值
但是在卡马克与雷神3的故事里,网上很多人讨论里面的一段开源码是这样的:
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;
}
这个方法里面参数只有一个,相当于我们普通版的那个a,那初值在哪儿?
就在这段注释是wtf那里:
i = 0x5f3759df - ( i >> 1 );
具体解释既有推导也有论文
用了那个神奇的参数,迭代一次(或者说直接计算)就行。