1. 几种迭代法的基本原理
参考西交大数值分析教材
2. 迭代法求解非线性方程的计算过程
据迭代法的局部收敛性定理,在使用迭代法前需要先是用二分法确定含根区间,在这个区间内x充分接近于真实解,使得迭代法收敛。此外对于简单迭代法,需要以收敛为原则构造迭代格式。如果迭代法收敛,则通过一定次数的迭代,计算结果逐步向真实解靠近,给定精度要求后,通过一定次数的迭代,就可以获得满足要求的解。迭代法的伪代码如下:
(1)使用二分法确定隔根区间[a, b]
(2)给定初始值x0,迭代格式
(3)while 不满足精度要求
计算
令
直到计算结果满足精度要求
(4)返回计算结果
3. 程序使用说明
为了使用方便,程序将三种求解方法封装为一个类solve_nonlinear_equation()。使用方法如下:(1)实例化该类;(2)给定区间,精度以及方程组(方程组字符串形式的表达式);(3)调用具体的求解函数string_cut(),Newton(),SimpleIteration(),其分别对应弦割法,牛顿法和简单迭代法。
4. python源代码
from sympy import *
class solve_nonlinear_equation():
'''
求解非线性方程类
输入参数:
a:区间左端点
b:区间右端点
precision:精度要求
f:求解函数(字符串)
'''
def __init__(self,a=-1,b=5,precision=0.00000001,
f='(x**6)-5*(x**5)+3*(x**4)+(x**3)-7*(x**2)+7*x-20'):
self.f=f
self.a=a
self.b=b
self.precision=precision
def calculate_function(self,x): #计算代数方程的值
result=eval(self.f)
return result
def change_calculate_function(self,x): #简单迭代法的迭代格式
f=self.f+'+x'
result = eval(f)
return result
def my_dichotomy(self,prec): #二分法找含根区间,同时保证局部收敛性
a=[self.a]
b=[self.b]
k=0
while True:
xk=(a[k]+b[k])/2
if abs(a[k]-b[k])<prec:
####
break
elif self.calculate_function(a[k])*self.calculate_function(xk)<0:
a.append(a[k])
b.append(xk)
else:
a.append(xk)
b.append(b[k])
k=k+1
return [a[-1],b[-1],k]
#简单迭代法
def SimpleIteration(self,x0):
x = symbols("x")
x_pre=x0
k=0
while abs(self.calculate_function(x_pre)) > self.precision:
#斯蒂芬森加速
x_new1 = self.change_calculate_function(x_pre)
x_new2 = self.change_calculate_function(x_new1)
x_new=x_new2-(x_new2-x_new1)**2/(x_new2-2*x_new1+x_pre)
x_pre=x_new
k=k+1
return [x_pre,k]
#牛顿法
def Newton(self,x0):
x=symbols("x")
f_diff=diff(self.f,x) #计算导数
x_pre=x0
k=0
while abs(self.calculate_function(x_pre)) > self.precision:
x_new=x_pre-self.calculate_function(x_pre)/f_diff.subs(x,x_pre)
x_pre=x_new
k=k+1
return [x_pre,k]
#两点弦割法
def string_cut(self,xk,x0):
x_pre=xk
x_0=x0
k=0
while abs(self.calculate_function(x_pre)) > self.precision:
temp1=self.calculate_function(x_pre)/self.calculate_function(x_0)
temp2=self.calculate_function(x_pre)/self.calculate_function(x_0)-1
x_new=x_pre-(temp1/temp2)*(x_pre-x_0)
x_0=x_pre
x_pre=x_new
k=k+1
return [x_pre,k]
if __name__ == "__main__":
f='(x**6)-5*(x**5)+3*(x**4)+(x**3)-7*(x**2)+7*x-20'
a=-1
b=5
precision=0.00000001
mytest=solve_nonlinear_equation(a, b, precision, f)#初始化
p=mytest.my_dichotomy(0.01) #使用二分法求解含根区间
print("二分法含根区间及迭代次数为",p)
x0=p[0]
x1=p[1]
result1=mytest.string_cut(x1,x0) #使用弦割法求解
result2=mytest.Newton(x0) #使用牛顿法求解
result3=mytest.SimpleIteration((x0+x1)/2) #使用简单迭代法求解
print("弦割法计算结果以及迭代次数为:",result1)
print("牛顿法计算结果以及迭代次数为:",result2)
print("简单迭代法计算结果以及迭代次数为:",result3)