1.牛頓疊代
假設方程 在 附近有一個根,那麼根據f(x)在x0附近的值和斜率,就能估計f(x)和x軸的交點用。疊代式子: 依次計算、、、……,那麼序列将無限逼近方程的根。
用牛頓疊代法開平方】令: 是以f(x)的一次導是: 牛頓疊代式: 随便一個疊代的初始值,例如,代入上面的式子疊代。例如計算,即a=2。 …… 電腦上可給出
根據果殼文章以上闡述,由此我們可以寫出如下代碼:
求9的平方根,嘗試 : 3次 , point : 3 , point的平方 : 9 , point平方與target的內插補點 : 0
到此為此,似乎問題已經得到了圓滿的答案,但緊接着我就發現了更有趣的解法
2.魔法數開方倒數
暴雪是一家神奇的公司,它的代碼總是能給人驚喜,例如 One-way Hash 被業内贊為最優秀的hash表改良算法(timer33算法應該才是最快的,One-way Hash 在Timer33的基礎上改用兩次Hash計算來比對Key是否一緻,在資料結構沒有根本變化的情況下,理論上來說應該更慢)。
下面是暴雪的開平方算法源碼,它對上述的牛頓疊代做了一些改進:
這個算法的牛逼之處在于,經典的牛頓疊代裡猜測值是随便取的一個值,而這段代碼裡卻用了一個魔法數0x5f3759df來作為猜測值。這個算法隻用了一次位運算,根本沒有多次疊代就得到了結果,比直接用sqrt(n)快了大約四倍。
但是,我要說但是了,這個算法并不是暴雪原創的。它更早的時候出現在 雷神之錘3 這個遊戲的3D引擎代碼裡,作者是約翰-卡馬克(John Carmack),江湖人稱卡神。
注意看代碼
這個魔法數 0x5f3759df 。它是從哪來的,又起到了什麼作用?
單精度的浮點數結構是這樣:那麼現在,每個正浮點數 y 可以用尾數和指數的形式寫成![]()
開方的幾種寫法 ,其中 m 是尾數部分,取值範圍是![]()
開方的幾種寫法 ;e 是指數部分,一個整數。每個浮點數所對應的「整數形式」則可以用![]()
開方的幾種寫法 表示,其中 L 是指數部分需要的位移次數(用 2 的幂表示),E 和 M 是指數部分和小數部分的整數版本。兩者之間的關系是![]()
開方的幾種寫法 對單精度浮點而言,![]()
開方的幾種寫法 。 考慮對數![]()
開方的幾種寫法 ,由于![]()
開方的幾種寫法 ,![]()
開方的幾種寫法 ,取近似![]()
開方的幾種寫法 ,可以算出整體「偏差」最小的![]()
開方的幾種寫法 ,此時兩者基本相當。是以我們可以說![]()
開方的幾種寫法 ……………… (1) 那麼,對于 y 的整數形式 Y 而言,展開并帶代入 (1) 有:![]()
開方的幾種寫法 即![]()
開方的幾種寫法 ………………(2) 那麼對于![]()
開方的幾種寫法 來說,![]()
開方的幾種寫法 ,代入 (2) 得:![]()
開方的幾種寫法 解得![]()
開方的幾種寫法 ![]()
開方的幾種寫法
這個就是代碼
的秘密所在。
程式員多學點數學,總是會有用的,與君共勉
附錄:java版算法實作
引用文獻: