sqrt开平方算法的尝试,是的看了卡马克大叔的代码,我来试试用C#写个0x5f3759df和0x5f375a86跟System.Math.Sqrt到底哪个更强
今天笔试遇到一个代码题,要求写一个开平方算法,回来发现了雷神之锤里的一段神代码:
1 float Q_rsqrt( float number ) 2 { 3 long i; 4 float x2, y; 5 const float threehalfs = 1.5F; 6 x2 = number * 0.5F; 7 y = number; 8 i = * ( long * ) &y; // evil floating point bit level hacking 9 i = 0x5f3759df - ( i >> 1 ); // what the fuck? 10 y = * ( float * ) &i; 11 y = y * ( threehalfs - ( x2 * y * y ) ); // 1st iteration 12 // y = y * ( threehalfs - ( x2 * y * y ) ); // 2nd iteration, this can be removed 13 14 #ifndef Q3_VM 15 #ifdef __linux__ 16 assert( !isnan(y) ); // bk010122 - FPE? 17 #endif 18 #endif 19 return y; 20 }
打算用C#写一个,试试这玩意会有多好用。
class Sqrt_Yc { unsafe internal static double DoubleSqrt(double number) { double x2, y; const double threehalfs = 1.5F; Int64 i; x2 = number * 0.5F; i = *(Int64*)&number; i = 0x5fe6ec85e7de30da - (i >> 1);// y = *(double*)&i; y = y * (threehalfs - (x2 * y * y)); y = y * (threehalfs - (x2 * y * y)); return 1 / y; } unsafe internal static float SingleSqrt0x5f375a86(float number) { int i; float x2, y; const float threehalfs = 1.5F; x2 = number * 0.5F; y = number; i = *(int*)&y; // evil floating point bit level hacking i = 0x5f375a86 - (i >> 1); // Chris Lomont's number y = *(float*)&i; y = y * (threehalfs - (x2 * y * y)); return 1/y; } unsafe internal static float SingleSqrt0x5f3759df(float number) { int i; float x2, y; const float threehalfs = 1.5F; x2 = number * 0.5F; y = number; i = *(int*)&y; // evil floating point bit level hacking i = 0x5f3759df - (i >> 1); // John Carmack's number y = *(float*)&i; y = y * (threehalfs - (x2 * y * y)); return 1 / y; } //意外收获,C#中定义联合体的方法,虽然和本内容无关 [System.Runtime.InteropServices.StructLayout(LayoutKind.Explicit)] public struct Double_Long_UNION { [FieldOffset(64)] internal Int64 intNum; [FieldOffset(64)] internal double doubleNum; } }
列位可以自己调用尝试下,今天收获不小,向先人致敬。