曾經面試遇到過一道編程題:
給出一個整數,求其近似平方根。
當時沒有想到更好的方法,就暴力進行了破解,這當然不會留下好的印象。其實,這道題使用牛頓迭代法可以十分高效的解決。
一、什麼是牛頓迭代法
假設有函數:,要想求出其根,則可以:
- 給出一個初始點,則在該點的切線爲:;
- 沿着切線方向,與橫軸相交,也即令:,則求得:;
- 更新,令:;
- 按照1~3步驟迭代下去,直到精度滿足要求;
上述算法的第1、2步,其實也就是函數在處的泰勒展開取前兩項:
上述泰勒展開式,取前兩項並使之等於0,則有:,同樣可以得到步驟2中的迭代公式。
二、解決求根問題
對於求一個整數近似平方根這個問題,我們可以簡單做一個轉換,使得問題變爲一個方程:。對於方程,是已知待求平方根的整數,爲我們的求解目標,此時,我們的目的就變成了求解的根了!
那麼,利用上述的牛頓迭代法,即可輕鬆解決。廢話少說,直接上碼:
def square_root(n:int)->float:
""" f(x) = x^2 - n = 0,求該方程的根
"""
x0 = 1
i = 0
while True:
i += 1
x1 = x0 - (x0**2 - n)/(2*x0)
if x1 - x0 < 1e-10 and x1-x0> -1e-10:
print("total iterations: ", i+1)
break
x0 = x1
return x1
代碼中:
我們給定初始值爲1,這裏需要注意的是,我們給的初始值不能是方程的極值點,否則利用牛頓迭代法則無法繼續優化下去;
設定了迭代結束條件:,當滿足該條件時,說明求解的精度已經很高了,此時的迭代結果即可作爲近似根了。
三、拓展一下
第二部分,給出了使用牛頓迭代法求解給定整數近似平方根的方法,我們同樣可以用於處理其他問題,如求解給定整數立方根..n次方根、給定任意方程,求其近似解等問題。
下面給出求解立方根的解法,與求解平方根十分相似,唯一不同之處就在於目標迭代公式稍微發生一點變化:
def cube_root(n:int)->float:
""" f(x) = x^3 - n = 0,求該方程的根
"""
x0 = 1
i = 0
while True:
i += 1
x1 = x0 - (x0**3 - n)/(3*x0**2)
if x1 - x0 < 1e-20 and x1-x0> -1e-20:
print("total iterations: ", i+1)
break
x0 = x1
return x1