尋找“最好”(8)——牛頓法


  牛頓是近代科學的先驅,智商290,碾壓無數學霸,一個蘋果都能砸出萬有引力定律。

  在力學上,牛頓闡明了動量和角動量守恆的原理,提出牛頓三大運動定律,它們和萬有引力定律奠定了此后三個世紀里物理世界的科學觀點,並成為無數中學生的噩夢。牛頓他通過論證開普勒行星運動定律與他的引力理論間的一致性,展示了地面物體與天體的運動都遵循着相同的自然定律;為太陽中心說提供了強有力的理論支持,並推動了科學革命。

  在天文學上,牛頓創制了反射望遠鏡。他還用萬有引力原理說明潮汐的各種現象,指出潮汐的大小不但同月球的位相有關,而且同太陽的方位有關。牛頓預言地球不是正球體。

  在哲學上,牛頓的哲學思想基本屬於自發的唯物主義,他承認時間、空間的客觀存在。如同歷史上一切偉大人物一樣,牛頓雖然對人類作出了巨大的貢獻,但他也不能不受時代的限制。例如,他把時間、空間看作是同運動着的物質相脫離的東西,提出了所謂絕對時間和絕對空間的概念;他對那些暫時無法解釋的自然現象歸結為上帝的安排,提出一切行星都是在某種外來的“第一推動力”作用下才開始運動的說法。

  在經濟學上,牛頓提出金本位制度。這是一種以黃金為本位幣的貨幣制度,當不同國家使用金本位時,國家之間的匯率由它們各自貨幣的含金量之比——金平價來決定。

  在數學上,我們已經見識過牛頓的微積分,他與萊布尼茨共同分享了微積分學的榮譽,盡管哥倆為誰的功勞大掐過架。

  此外,牛頓還提出了著名的牛頓法(Newton's method)也叫牛頓迭代法,它是牛頓在17世紀提出的一種在實數域和復數域上近似求解值的方法。

牛頓法

  先來看如何用牛頓迭代法求解5的平方根。

  首先令f(x)= x2 – 5,這是標准步驟,取得一個新函數;再令該函數為0,這樣原問題就可以看作是解方程x2 – 5 = 0。f(x)是一個拋物線:

  拋物線與x軸正方向的交點x就是方程的解,它比2稍大一點。

  現在在x = 2的點(2, -1)處對f(x)做切線,切線方程是y = kx + b,斜率k是f(x)在x = 2處的導數:

  將(2, -1)代入切線后得到截距b= -9:

 

  設f(x)與x軸正半軸的交點是x,切點是x0,切線與x軸的交點是x1,x1在x的右側:

  由於x1貼近x,所以只要求得x1就能近似地求出x。求解x1的方法之一是找出過x0的切線,之后計算切線與x軸的交點。設切線的斜率是k,根據斜率的公式:

  過x0的切線的斜率正式f(x)在x0處導數的定義,因此:

  這樣一來就找到了x的近似解x1。然而x1還沒達到標准,我們還想更貼近真實值一點,這次選取更進接近x的(x1, f(x1))做切點,新切點的切線與x軸的交點x2將比原來的x1更貼近x:

  計算器上計算根號5的結果是2.236067,x2的值已經相當接近。

  重復上面步驟,每一次迭代的結果都將更接近真實值:

  這就是牛頓迭代法的公式。

牛頓法的注意事項

  牛頓迭代法幾乎可以求解所有方程,但它仍然有一些限制。

  在使用牛頓迭代法時,需要選取x0作為迭代基數,x0如何選取呢?一句參考是:x0要在x附近,它是一個較為解接近真實解的值,這要憑經驗和感覺了,沒有什么太好的辦法。

  實際上,如果x0和x的差距過大,可能會得到一個沒譜的解。以計算5的平方根為例,如果選擇x0= -2,結果將偏向於-2.236067;如果選擇x0=0,則f’(0)=0,沒法繼續迭代:

  設第n次迭代的誤差是En=|x-xn|,那么需要滿足En+1<En。如果選擇和計算都正確,誤差縮小的速度將非常快。

從泰勒公式看牛頓法

  泰勒展開式是一種計算近似值的方法,是一個用函數某點的信息描述在該點附近取值的公式,這就與牛頓法有些相似了。

  把f(x)在x0的某鄰域內展開成泰勒級數:

  進一步得到:

  反復迭代就得到了牛頓法的公式:

解方程2cosx = 3x

  先作圖,畫出y = 2cosx和y = 3x的曲線:

  兩條曲線相交於一點,方程存在唯一解。根據牛頓法,先設置f(x):

  兩條曲線交點的位置似乎是π/6附近,所以選擇π/6作為x0,根據牛頓迭代法:

  第二次迭代與第一次迭代的差距已經非常微小,可以說x2就是最終的近似解。

求平方根

  在一次code review會議上,一個同事展示了一段他不理解的C++代碼:

 1 const float EPS = 0.00001;
 2 
 3 doublesqrt(doublex){
 4     if(x == 0)
 5         return 0;
 6 
 7     double result = x;
 8     double lastValue;
 9     do{
10         lastValue = result;
11         result = result/2.0f + x/2.0f/result;
12     }while(abs(result - lastValue) > EPS);
13 
14    return result;
15 }        

  sqrt函數是求平方根,並且運行的很好,雖然展示者能夠看懂每一行代碼,但不知道為什么要這么寫,不明白那個神奇的2.0是什么意思。

  現在看起來,不懂數學都沒法快樂地閱讀代碼了。這段代碼其實是在使用牛頓法計算平方根,過程是這樣的:

  如果改成計算機程序的寫法:

  現在可以和第9行代碼對應上了。

  


   作者:我是8位的

  出處:http://www.cnblogs.com/bigmonkey

  本文以學習、研究和分享為主,如需轉載,請聯系本人,標明作者和出處,非商業用途! 

  掃描二維碼關注公眾號“我是8位的”


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM