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
posted @ 2021-06-15 14:43  IT88老兵  阅读(1199)  评论(0编辑  收藏  举报