1. 程式人生 > 其它 >newton_raphson 牛頓-拉夫遜(拉弗森)方法

newton_raphson 牛頓-拉夫遜(拉弗森)方法

newton_raphson 牛頓-拉夫遜(拉弗森)方法

參考: https://baike.baidu.com/item/牛頓迭代法/10887580?fromtitle=牛頓法&fromid=1384129&fr=aladdin

牛頓迭代法(Newton's method)又稱為牛頓-拉夫遜(拉弗森)方法(Newton-Raphson method),它是牛頓在17世紀提出的一種在實數域和複數域上*似求解方程的方法。

  • 產生背景

    多數方程不存在求根公式,因此求精確根非常困難,甚至不可解,從而尋找方程的*似根就顯得特別重要。方法使用函式 的泰勒級數的前面幾項來尋找方程 的根。牛頓迭代法是求方程根的重要方法之一,其最大優點是在方程 的單根附*具有*方收斂,而且該法還可以用來求方程的重根、復根,此時線性收斂,但是可通過一些方法變成超線性收斂。另外該方法廣泛用於計算機程式設計中。

  • 牛頓迭代公式

    設 $ r $ 是$ f(x)=0 $ 的根,選取$ x_0 $ 作為 $ r $ 的初始*似值,過點$(x_0,f(x_0)) $ 做曲線 $ y= f(x) $ 的切線 $ L \(,\) L: y=f(x_0)+f^{'}(x_0)(x-x_0) $,則 $L \(與\) X $ 軸交點的橫座標 $X_1=X_0-\frac{f(x_0)}{f^{'}(x_0)} $,稱 $ X_1$為 $ r $的一次*似值。

    過點 $(x_1,f(x_1)) $ 做曲線 $ y= f(x) $ 的切線,並求該切線與\(x\) 軸交點的橫座標 ,稱 $X_2=X_1-\frac{f(x_1)}{f^{'}(x_1)} $ 為r的二次*似值。

    重複以上過程,得 $ r $ 的*似值序列,其中,$X_{n+1}=X_n-\frac{f(x_n)}{f^{'}(x_n)} $ 稱為 $ r \(的\)

    n+1 $ 次*似值,上式稱為牛頓迭代公式。

用牛頓迭代法解非線性方程,是把非線性方程 $f(x)=0 $ 線性化的一種*似方法。把$ f(x) $ 在點 $ x_0 $ 的某鄰域內展開成泰勒級數
$
f(x)=f(x_0)+ f{'}(x_0)(x-x_0)+\frac{f{"}(x_0)(x-x_0)^2}{2!}+\cdots+ \frac{f{(n)}(x_0)(x-x_0)n}{n!}+R_n(x)
$
,取其線性部分(即泰勒展開的前兩項),並令其等於0,即
$
f(x)=f(x_0)+ f^{'}(x_0)(x-x_0)
$
,以此作為非線性方程 $ f(x) =0 $ 的*似方程,若 $ f^{'}(x_0) \neq 0 $,則其解為 $ x_1=x_0-\frac{f(x_0)}{f^{'}(x_0)} \(, 這樣,得到牛頓迭代法的一個迭代關係式:\)

x_{n+1}=x_n-\frac{f(x_n)}{f^{'}(x_n)} $ 。

已經證明,如果是連續的,並且待求的零點是孤立的,那麼在零點周圍存在一個區域,只要初始值位於這個鄰*區域內,那麼牛頓法必定收斂。 並且,如果不為0, 那麼牛頓法將具有*方收斂的效能. 粗略的說,這意味著每迭代一次,牛頓法結果的有效數字將增加一倍。
迭代法也稱輾轉法,是一種不斷用變數的舊值遞推新值的過程,跟迭代法相對應的是直接法(或者稱為一次解法),即一次性解決問題。迭代演算法是用計算機解決問題的一種基本方法。它利用計算機運算速度快、適合做重複性操作的特點,讓計算機對一組指令(或一定步驟)重複執行,在每次執行這組指令(或這些步驟)時,都從變數的原值推出它的一個新值。
利用迭代演算法解決問題,需要做好以下三個方面的工作:

  • 1、確定迭代變數

    在可以用迭代演算法解決的問題中,至少存在一個可直接或間接地不斷由舊值遞推出新值的變數,這個變數就是迭代變數。

  • 2、建立迭代關係式

    所謂迭代關係式,指如何從變數的前一個值推出其下一個值的公式(或關係)。迭代關係式的建立是解決迭代問題的關鍵,通常可以使用遞推或倒推的方法來完成。

  • 3、對迭代過程進行控制

    在什麼時候結束迭代過程?這是編寫迭代程式必須考慮的問題。不能讓迭代過程無休止地執行下去。迭代過程的控制通常可分為兩種情況:一種是所需的迭代次數是個確定的值,可以計算出來;另一種是所需的迭代次數無法確定。對於前一種情況,可以構建一個固定次數的迴圈來實現對迭代過程的控制;對於後一種情況,需要進一步分析得出可用來結束迭代過程的條件。

  • 演算法

def newton_raphson(   
    func: str,          # 函式字串
    a: Union[float, Decimal],   # 初始值
    precision: float = 10 ** -10  # 精度
    ) -> float:  <br>
  • 準備
pip install sympy     

程式碼

[newton_raphson.py]{..\src\arithmetic_analysis\newton_raphson.py}

"""
Prepare
   1. sys.path 中增加 TheAlgorithms\src 子模組
"""
import sys
sys.path.append('E:\dev\AI\TheAlgorithms\src')

** 案例一

    >>> newton_raphson("sin(x)", 2)
    3.1415926536808043
    >>> newton_raphson("x**2 - 5*x +2", 0.4)
    0.4384471871911695
    >>> newton_raphson("x**2 - 5", 0.1)
    2.23606797749979
    >>> newton_raphson("log(x)- 1", 2)
    2.718281828458938
from arithmetic_analysis.newton_raphson import  newton_raphson
# import math
# from sympy import diff

"""
"""
print(newton_raphson("sin(x)", 2))  #    3.1415926536808043
print(newton_raphson("x**2 - 5*x +2", 0.4))  #    0.4384471871911695
print(newton_raphson("x**2 - 5", 0.1))  #   2.23606797749979
print(newton_raphson("log(x)- 1", 2))  #    2.718281828458938
    
3.141592653680804
0.4384471871911695
2.23606797749979
2.718281828458938

** 案例二

# Find root of trigonometric function 求三角函式的根
# Find root of polynomial
# Find Square Root of 5
# Exponential Roots

from arithmetic_analysis.newton_raphson import  newton_raphson
 # Find value of pi
print(f"The root of sin(x) = 0 is {newton_raphson('sin(x)', 2)}")
# Find root of polynomial# Find root of polynomial
print(f"The root of x**2 - 5*x + 2 = 0 is {newton_raphson('x**2 - 5*x + 2', 0.4)}")
# Find Square Root of 5
print(f"The root of log(x) - 1 = 0 is {newton_raphson('log(x) - 1', 2)}")
# Exponential Roots
print(f"The root of exp(x) - 1 = 0 is {newton_raphson('exp(x) - 1', 0)}")


The root of sin(x) = 0 is 3.141592653680804
The root of x**2 - 5*x + 2 = 0 is 0.4384471871911695
The root of log(x) - 1 = 0 is 2.718281828458938
The root of exp(x) - 1 = 0 is 0.0