6.3w+
社区成员
// 速的求1/sqrt(x)
//
float InvSqrt(float x){
float xhalf=0.5f*x;
long i=*(long*)&x;
i=0x5f3759df - (i>>1);
x=*(float *)&i;
x=x*(1.5f-xhalf*x*x);
return x;
}
Beyond3D.com的Ryszard Sommefeldt一直在想到底是哪个家伙写了这些神奇的代码?2003
年Chris Lomont还写了一篇文章(PDF)对这些代码进行了分析。毫无疑问写出这些代码的
人绝对是天才。
是John Carmack?Michael Abrash?John Carmack在邮件回复中明确表示不是他,也不是
Michael,可能是Terje Matheson。于是侦探Ryszard又向Terje Mathisen寻求答案。
Terje说他写过类似的高效代码,但上面的不是。他猜测可能在MIT的旧文档中可以找到。
Ryszard的求证之路显然无止境。
#include <iostream.h>
#include <math.h>
#include <windows.h>
/*
*浮点数开平方3种算法的速度测试
*阿金 2006-5-4
*z资料来源: http://greatsorcerer.go2.icpcn.com/info/fastsqrt.html
*
*测试结论:
*这些所谓高效的函数经过测试发现,还是sqrt()的速度最快。或者sqrtf()
*开始以为是函数调用时间的开销,于是把他们弄成inline,结果发现还是sqrt()的速度更快,
*又以为是程序先后顺序可能造成CPU或内存资源的问题,于是交换各个函数的执行顺序还是sqrt()的速度最快,
*又以为编译器对其进行过优化,把一些重复的部分给省略掉了,于是每处都加上一个rand()函数,输入加入rand()的结果,发现还是sqrt()的速度快,
*这样看来,可能是CPU的硬件厂商已经将该算法设计到硬件中,还是用math.h中的sqrt()吧~~
*/
////////////////////////test2;
inline float Faster_Sqrtf(float f)
{
float result;
_asm
{
mov eax, f
sub eax, 0x3f800000
sar eax, 1
add eax, 0x3f800000
mov result, eax
}
return result;
}
//////////////////////////test3
inline float CarmSqrt(float x){
union{
int intPart;
float floatPart;
} convertor;
union{
int intPart;
float floatPart;
} convertor2;
convertor.floatPart = x;
convertor2.floatPart = x;
convertor.intPart = 0x1FBCF800 + (convertor.intPart >> 1);
convertor2.intPart = 0x5f3759df - (convertor2.intPart >> 1);
return 0.5f*(convertor.floatPart + (x * convertor2.floatPart));
}
/////////////////////////////
void main()
{
float input,output1,output2,output3;
cout<<"input a float: "<<endl;
cin>>input;
unsigned long espTime1,espTime2,espTime3;
int temp;
unsigned long startTime=0, endTime=0, i=0,j=0,k=0;
///////////////////////////test3
startTime = timeGetTime();
for(i=0; i<100; i++)
{
for(j=0; j<1000; j++)
{
for(k=0; k<1000; k++)
{
temp = rand()%65535;
output3 = CarmSqrt(temp*input);
}
}
}
endTime = timeGetTime();
espTime3 = endTime - startTime;
/////////////////////////////test2
startTime = timeGetTime();
for(i=0; i<100; i++)
{
for(j=0; j<1000; j++)
{
for(k=0; k<1000; k++)
{
temp = rand()%65535;
output2 = Faster_Sqrtf(temp*input);
}
}
}
endTime = timeGetTime();
espTime2 = endTime - startTime;
/////////////////////////////test1
startTime = timeGetTime();
for(i=0; i<100; i++)
{
for(j=0; j<1000; j++)
{
for(k=0; k<1000; k++)
{
temp = rand()%65535;
output1 = sqrtf(temp*input);
}
}
}
endTime = timeGetTime();
espTime1 = endTime - startTime;
///////////////////////
cout<<"sqrt:"<<input<<" = "<<output1<<" espTime1:"<<espTime1<<endl;
cout<<"Fsqrt:"<<input<<" = "<<output2<<" espTime2:"<<espTime2<<endl;
cout<<"Csqrt:"<<input<<" = "<<output3<<" espTime3:"<<espTime3<<endl;
}