牛頓迭代法是求開n次方近似解的一種方法,本文參考。
引言
假如\(x^n = m\),我們需要求x的近似值。
- 我們設\(f(x) = x^n - m\), 那么也就是求該函數f(x)=0時與x軸的交點的值,也就是f(x)=0時方程的根。
算法介紹
感覺和物理做實驗一樣,先通過實驗觀察,再找出對應理論來解釋現象。
這個算法不是推導出來的,是首先通過觀察發現,再來證明推導,哈哈哈~
以下結論都是建立在f(x)二階可導的情況下成立。
牛頓發現隨便找一個曲線上的A點(為什么隨便找,根據切線是切點附近的曲線的近似,應該在根點附近找,但是很顯然我們現在還不知道根點在哪里),做一個切線,切線的根(就是和x軸的交點)與曲線的根,還有一定的距離。牛頓、拉弗森們想,沒關系,我們從這個切線的根出發,做一根垂線,和曲線相交於B點,繼續重復剛才的工作:
之前說過,B點比之前A點更接近曲線的根點,牛頓、拉弗森們很興奮,繼續重復剛才的工作:
經過多次迭代后會越來越接近曲線的根(下圖進行了50次迭代,哪怕經過無數次迭代也只會更接近曲線的根,用數學術語來說就是,迭代收斂了):
總結
已知曲線方程\(f(x) = x^n - m\),我們隨機取一點\(x_1\):
- \(x_1\)處切線方程為:\(y - f(x_1) = f^{'}(x_1)(x - x_1)\),此方程與x軸的交點為\(x_2\)為:
- \(x_2 = x_1 - \frac{f(x_1)}{f^{'}(x_1)} = x_1 - \frac{x_1^n - m}{nx_1^{n-1}}\)
- 一直到\(x_{N+1} = x_N - \frac{x_N^n - m}{nx_N^{n-1}}\),從而近似求解開n次方。
算法實現(go)
這是go tutorial里的一個練習,求開方。求開n次方同理。只需要改成z = z - (Pow(z,n) - m)/(n*Pow(z,(n-1)))
就行了。
注意這里的z = (z + x/z)/2
也就是\(z = \frac{z^2+x}{2z}\)也等於我們這里當\(n=2\)時,\(z - \frac{z^2-x}{2z}\),在代碼里也就是反復更新迭代z的值,縮小誤差。
package main
import (
"fmt"
"math"
)
func Sqrt(x float64) float64 {
z := float64(1)
tmp := float64(0)
for math.Abs(tmp - z) > 0.0000000001 {
tmp = z
z = (z + x/z)/2
}
return z
}
func main() {
fmt.Println(Sqrt(2))
fmt.Println(math.Sqrt(2))
}