1.從 1.414 向下一位開始,二分法查找平方最接近2的數字。效率比較差。
2.使用牛頓迭代法:
x初始等於1.414
不斷令x等於x和2/x的平均數,然後求每次x的平方,看與2的差距
這樣比之前的二分法要精簡很多次運算。
這種算法的原理很簡單,我們僅僅是不斷用(x,f(x))
的切線來逼近方程x^2-a=0
的根。根號a
實際上就是x^2-a=0
的一個正實根,這個函數的導數是2x
。也就是說,函數上任一點(x,f(x))
處的切線斜率是2x
。那麼,x-f(x)/(2x)
就是一個比x
更接近的近似值。代入 f(x)=x^2-a
得到x-(x^2-a)/(2x)
,也就是(x+a/x)/2
Chris Lomont 魔法數 + 牛頓迭代,這個偏離了本題條件,因爲本題給了初始數字
1.414
,但是對於沒有初始猜想的數字,使用魔法數字0x5f375a86
(源代碼註釋是:what the fxxk???,哈哈哈哈哈,這個數字太匪夷所思了,但是這就是數學的魅力)猜想初始數字,比x
等於x
和2/x
的平均數這個初始數字,進行開方平均效率高很多,具體計算過程是:
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;
}
這個函數返回的是1/sqrt(x)
,這個比sqrt(x)
更常用於圖像處理,參考這篇論文理解爲啥是 0x5f375a86
: http://www.matrix67.com/data/InvSqrt.pdf
本文分享自微信公衆號 - 我的編程喵(MyProCat)。
如有侵權,請聯繫 [email protected] 刪除。
本文參與“OSC源創計劃”,歡迎正在閱讀的你也加入,一起分享。