[数值计算-7]:一元n次非线性方程求解-单点盲探-牛顿迭代法&Python法代码示例

Posted 文火冰糖的硅基工坊

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[数值计算-7]:一元n次非线性方程求解-单点盲探-牛顿迭代法&Python法代码示例相关的知识,希望对你有一定的参考价值。

 作者主页(文火冰糖的硅基工坊):https://blog.csdn.net/HiWangWenBing

本文网址:https://blog.csdn.net/HiWangWenBing/article/details/119813740


目录

1. 一元n次非线性方程

1.1 非线性函数

1.2 非线性函数案例

1.3 非线性函数的几何图形

2. 牛顿迭代法求非线性方程解的基本原理

2.1 概述

2.2 中值定理

2.3 确定误差或收敛条件

2.4 迭代过程

2.5 牛顿迭代法的条件

2.6 牛顿迭代法的优缺点

3. Python代码示例

3.1 案例1:初值= +2

3.1 案例2:初值= -2



1. 一元n次非线性方程

1.1 非线性函数

线性函数是一次函数的别称,则非线性函数即函数图像不是一条直线的函数。

非线性函数包括指数函数、幂函数、对数函数、多项式函数等等基本初等函数以及他们组成的复合函数

1.2 非线性函数案例

 y = f(x) = a3*x^3 + a2*x^1 +  a0 

另a3 = 1, a2=-1, a0=-1;得到:

y=f(x) = x^3 - x^2 - 1

1.3 非线性函数的几何图形

2. 牛顿迭代法求非线性方程解的基本原理

2.1 概述

牛顿迭代法(Newton's method)又称为牛顿-拉夫逊(拉弗森)方法(Newton-Raphson method),它是牛顿在17世纪提出的一种在实数域和复数域上近似求解方程的方法。 

2.2 中值定理

 中值定理是反映函数本身与其在某一点处的导数之间联系的重要定理

函数与其导数是两个不同的函数;而导数只是反映函数在一点的局部特征;如果要了解函数在其定义域上的整体性态,就需要在导数及函数间建立起联系,微分中值定理就是这种作用。

微分中值定理,包括罗尔定理、拉格朗日定理柯西定理、泰勒定理。是沟通导数值与函数值之间的桥梁,是利用导数的局部性质推断函数的整体性质的工具。

拉格朗日中值定理:

内容是说一段连续光滑曲线中必然有一点,它的斜率与整段曲线平均斜率相同。

上述公式既是牛顿迭代法误差公式的基础,也是迭代公式的基础。

2.3 确定误差或收敛条件

 当X接近真实根的时候,X与真实值的误差约等于Xk+1与Xk之间的差值。

2.4 迭代过程

 

2.5 牛顿迭代法的条件

(1)在真实解附近是可导

(2)初始值需要靠近真实解附近

2.6 牛顿迭代法的优缺点

(1)优点:

  • 在真实解附近,收敛快

  • 能够体现导数对迭代收敛意义和作用

(2)缺点:

如果初始点离真实解较远,且中间的单调的,就可以切线与X轴的交点,不能向真实解收敛,即y=f(x)不能向0方向收敛。因为所谓求方程解,就是求y=f(x)=0处的x值,如果y=f(Xk)不能向0收敛,则x就无法向真实解收敛。

解决次问题的方法:就是“牛顿下山法”对牛顿迭代法进行优化和限制。

3. Python代码示例

3.1 案例1:初值= +2

(1)源代码:

#导入库
from math import *
import time
import numpy
import matplotlib.pyplot as plt


# 一元N次非线性函数
# y=f(x) = x^3 - x - 1
def f(x,derive):
    #定义函数参数
    if(derive == 0):
        return(1.0*x**3 - 1.0*x**1 -1)  #原函数 
    elif (derive == 1):
        return(3.0*x**2 - 1.0)         #导函数
    else:
        print("Input Error")
        return(0)

#定义精度
accuracy = 0.0001

#定义起始点
x1 = 2

#log data
count = 0
x_data  = []
y_data  = []

#记录初始节点
x_data.clear()
y_data.clear()
x_data.append(0)
y_data.append(x1)

#迭代起始时间
start = time.time()

while True:
    #新的一轮迭代
    x2 = x1 - f(x1,0)/f(x1,1) # X值的迭代
    Err = fabs(x2-x1)         # 迭代后误差
    x1 = x2                   # 保留当前x值
    
    #增加log记录
    count = count + 1
    x_data.append(count)
    y_data.append(x1)
    
    if (Err <= accuracy):
        break;
    
#迭代终止时间
end = time.time()

print("耗时=", end-start)
print("迭代次数=", count)
print("方程解=", x2)
print("实际误差=", Err)
print("迭代数据序列..........")

print("\\n迭代过程")
for x in x_data:
    print("X{}={}".format(x,y_data[x]))

plt.scatter(x_data, y_data)

(2)输出结果

耗时= 0.00099945068359375
迭代次数= 5
方程解= 1.3247179572458576
实际误差= 1.0921712676470463e-06

迭代过程
X0=2
X1=1.5454545454545454
X2=1.359614915915184
X3=1.325801345005845
X4=1.3247190494171253
X5=1.3247179572458576

(3)图形显示收敛过程

3.1 案例2:初值= -2

(1)源代码

#定义精度
accuracy = 0.0001

#定义起始点
x1 = -2

#log data
count = 0
x_data  = []
y_data  = []

#记录初始节点
x_data.append(0)
y_data.append(x1)

#迭代起始时间
start = time.time()

while True:
    #新的一轮迭代
    x2 = x1 - f(x1,0)/f(x1,1) # X值的迭代
    Err = fabs(x2-x1)         # 迭代后误差
    x1 = x2                   # 保留当前x值
    
    #增加log记录
    count = count + 1
    x_data.append(count)
    y_data.append(x1)
    
    if (Err <= accuracy):
        break;
    
#迭代终止时间
end = time.time()

print("耗时=", end-start)
print("迭代次数=", count)
print("方程解=", x2)
print("实际误差=", Err)

print("\\n迭代过程")
for x in x_data:
    print("X{}={}".format(x,y_data[x]))

plt.scatter(x_data, y_data)

(2)输出

耗时= 0.0
迭代次数= 65
方程解= 1.3247179574157972
实际误差= 1.3548153629638904e-05

迭代过程
X0=-2
X1=-1.3636363636363638
X2=-0.8892353134230391
X3=-0.29609491722682657
X4=-1.2864352364252927
X5=-0.8217128731113184
X6=-0.10691984835296464
X7=-1.03298211799929
X8=-0.5472085094190648
X9=-6.611274711607757
X10=-4.433702585989313
X11=-2.989538057557567
X12=-2.031496813533126
X13=-1.3854649531667529
X14=-0.9075970552862211
X15=-0.33661987193684095
X16=-1.3994357597139493
X17=-0.9192055355939536
X18=-0.3605283713478141
X19=-1.4855582794693762
X20=-0.9886592503827742
X21=-0.4826912520186133
X22=-2.5747641103691308
X23=-1.7544435797503293
X24=-1.190229561606389
X25=-0.7299425321629264
X26=0.37120956464817956
X27=-1.8791055025333052
X28=-1.2790826744313537
X29=-0.8150369612962106
X30=-0.08343010635041948
X31=-1.0201408804244034
X32=-0.5293414717824825
X33=-4.4127113786720065
X34=-2.9756275206939176
X35=-2.0222349844904874
X36=-1.3790536473294959
X37=-0.9022331545785207
X38=-0.3251428738220351
X39=-1.3637814489635551
X40=-0.8893583038994928
X41=-0.2963784747231665
X42=-1.2871128668662455
X43=-0.822325743167123
X44=-0.10902119046333758
X45=-1.0342878895057943
X46=-0.5489915337873275
X47=-6.9822885227693545
X48=-4.680020332909626
X49=-3.1527764448637754
X50=-2.140083129871087
X51=-1.4602171044569312
X52=-0.9685635995638602
X53=-0.4504371240959939
X54=-2.0883677454698484
X55=-1.4247054725546997
X56=-0.9399406438426444
X57=-0.40040427420864433
X58=-1.6793109477226182
X59=-1.1355642957994752
X60=-0.6723450974394425
X61=1.1010597171365635
X62=1.3916209468034497
X63=1.3285408122104765
X64=1.3247315055694269
X65=1.3247179574157972

(3)图形 


作者主页(文火冰糖的硅基工坊):https://blog.csdn.net/HiWangWenBing

本文网址:https://blog.csdn.net/HiWangWenBing/article/details/119813740

以上是关于[数值计算-7]:一元n次非线性方程求解-单点盲探-牛顿迭代法&Python法代码示例的主要内容,如果未能解决你的问题,请参考以下文章

[数值计算-5]:一元二次非线性方程求解 - 解析法直接求解

[数值计算-8]:一元n次非线性方程求解-双点区间-弦截迭代法&Python法代码示例

[数值计算-4]:一元一次线性方程求解 - 解析法直接求解

如何用matlab来求解多元一次现性方程

[数值计算-16]:最小二乘法求的解法1 - 一元2次方程解析法求解

一元线性最小二乘法正规方程组的求解过程