迭代法求解非线性方程(含python代码)

1. 几种迭代法的基本原理

        参考西交大数值分析教材

迭代法求解非线性方程(含python代码)_第1张图片

迭代法求解非线性方程(含python代码)_第2张图片

迭代法求解非线性方程(含python代码)_第3张图片

迭代法求解非线性方程(含python代码)_第4张图片

迭代法求解非线性方程(含python代码)_第5张图片

2. 迭代法求解非线性方程的计算过程

        据迭代法的局部收敛性定理,在使用迭代法前需要先是用二分法确定含根区间,在这个区间内x充分接近于真实解,使得迭代法收敛。此外对于简单迭代法,需要以收敛为原则构造迭代格式。如果迭代法收敛,则通过一定次数的迭代,计算结果逐步向真实解靠近,给定精度要求后,通过一定次数的迭代,就可以获得满足要求的解。迭代法的伪代码如下:

(1)使用二分法确定隔根区间[a, b]

(2)给定初始值x0,迭代格式

(3)while 不满足精度要求

              计算

              令

       直到计算结果满足精度要求

(4)返回计算结果

 3. 程序使用说明

        为了使用方便,程序将三种求解方法封装为一个类solve_nonlinear_equation()。使用方法如下:(1)实例化该类;(2)给定区间,精度以及方程组(方程组字符串形式的表达式);(3)调用具体的求解函数string_cut(),Newton(),SimpleIteration(),其分别对应弦割法,牛顿法和简单迭代法。

迭代法求解非线性方程(含python代码)_第6张图片

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]) 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)

你可能感兴趣的:(算法学习,python,算法)