弦截法(Secant Method)迭代求根的python程序

迭代法的作用

许多复杂的求解问题,都可以转换成方程f(x)=0的求解问题。这一系列的解叫做方程的根。对于非线性方程的求解,在自变量范围内往往有多个解,我们将此变化区域分为多个小的子区间,对每个区间进行分别求解。我们在求解过程中,选取一个近似值或者近似区间,然后运用迭代方法逐步逼近真实解。
方程求根的常用迭代法有:二分法不动点迭代牛顿法弦截法

弦截迭代法

弦截法又称弦位法、弦割法、弦法或割线法
牛顿迭代法的优点是收敛速度快,但其明显的缺点是每次迭代需要计算导数值f’(xk),如果函数f(x)比较复杂,使用牛顿迭代法是不方便的。为了避开导数的计算,改用差商替换牛顿迭代法中的导数,这就是弦截法的基本思想。

单点弦法

在这里插入图片描述
这个公式的几何意义是过两个点作弦,这个弦与x轴的交点即是根的新的近似值,因为弦的一个端点(x0,f(x0))始终不变,另一个端点变动,所以这种方法称为单点弦法

单点弦法例题——有区间

求方程式:x3- 0.165x2 + 3.993×10-4 = 0在(0,0.11)的根

先看看不用迭代法计算的结果

from sympy import *
from sympy.abc import x

def func(x):
    return x**3 - 0.165*x**2 + 3.993*10**(-4)
result = solveset(func(x), x, Interval(0, 0.11))
print(result)

结果:

FiniteSet(0.0623775815137495)

约定一个误差,当误差小于某个数值的时候,迭代停止

代码:

x0 = 0  #区间下限
x1 = 0.11  #区间上限

x_list = [x1]
i = 0

def f(x):
    f = x**3 - 0.165*x**2 + 3.993*10**(-4)
    return f

while True:
    x2 = x1 - f(x1)*(x1-x0)/(f(x1)-f(x0))
    x1 = x2
    x_list.append(x2)
    if len(x_list) > 1:
        i += 1
        error = abs((x_list[-1] - x_list[-2]) / x_list[-1])
        if error < 10**(-6):
            print(f'迭代第{i}次后,误差小于10^-6')
            break
    else:
        pass

print(f'所求方程式的根为{x_list[-1]}')

结果:

迭代第14次后,误差小于10^-6
所求方程式的根为0.06237756428811298

迭代至电脑默认误差为0

代码:

x0 = 0  #区间下限
x1 = 0.11  #区间上限

x_list = [x1]
i = 0

def f(x):
    f = x**3 - 0.165*x**2 + 3.993*10**(-4)
    return f

while True:
    x2 = x1 - f(x1)*(x1-x0)/(f(x1)-f(x0))
    x1 = x2
    x_list.append(x2)
    if len(x_list) > 1:
        i += 1
        error = abs((x_list[-1] - x_list[-2]) / x_list[-1])
        if error == 0:
            print(f'迭代第{i}次后,误差为0')
            break
    else:
        pass

print(f'所求方程式的根为{x_list[-1]}')

结果:

迭代第39次后,误差为0
所求方程式的根为0.06237758151374951

画迭代图

代码:

import matplotlib.pyplot as plt
x0 = 0  #区间下限
x1 = 0.11  #区间上限

x_list = [x1]
i = 0
x_values = []
y_values = []

def f(x):
    f = x**3 - 0.165*x**2 + 3.993*10**(-4)
    return f

while True:
    x2 = x1 - f(x1)*(x1-x0)/(f(x1)-f(x0))
    x1 = x2
    x_list.append(x2)
    if len(x_list) > 1:
        i += 1
        error = abs((x_list[-1] - x_list[-2]) / x_list[-1])
        x_values.append(i)
        y_values.append(error)
        if error == 0:
            print(f'迭代第{i}次后,误差为0')
            break
    else:
        pass

print(f'所求方程式的根为{x_list[-1]}')

#设置绘图风格
plt.style.use('ggplot')
#处理中文乱码
plt.rcParams['font.sans-serif'] = ['Microsoft YaHei']
#坐标轴负号的处理
plt.rcParams['axes.unicode_minus']=False
#横坐标是迭代次数
#纵坐标是误差值
plt.plot(x_values,
         y_values,
         color = 'steelblue', # 折线颜色
         marker = 'o', # 折线图中添加圆点
         markersize = 3, # 点的大小
         )
# 修改x轴和y轴标签
plt.xlabel('迭代次数')
plt.ylabel('误差值')
# 显示图形
plt.show()

结果:

迭代第39次后,误差为0
所求方程式的根为0.06237758151374951

在这里插入图片描述

单点弦法例题——单点

求方程式:x = exp(-x)在0.5附近的根
即求方程式xexp(x)-1=0在0.5附近的根
单点弦法是需要两个初始点,只是初始点x0在迭代过程中不变。所以另一个初始点可以取x0=0.5附近的值,这里我取x1=0.6。
代码:

from sympy import *
import matplotlib.pyplot as plt
x0 = 0.5
x1 = 0.6

x_list = [x1]
i = 0
x_values = []
y_values = []

def f(x):
    f = x * exp(x) - 1
    return f

while True:
    x2 = x1 - f(x1)*(x1-x0)/(f(x1)-f(x0))
    x1 = x2
    x_list.append(x2)
    if len(x_list) > 1:
        i += 1
        error = abs((x_list[-1] - x_list[-2]) / x_list[-1])
        x_values.append(i)
        y_values.append(error)
        if error == 0:
            print(f'迭代第{i}次后,误差为0')
            break
    else:
        pass

print(f'所求方程式的根为{x_list[-1]}')

#设置绘图风格
plt.style.use('ggplot')
#处理中文乱码
plt.rcParams['font.sans-serif'] = ['Microsoft YaHei']
#坐标轴负号的处理
plt.rcParams['axes.unicode_minus']=False
#横坐标是迭代次数
#纵坐标是误差值
plt.plot(x_values,
         y_values,
         color = 'steelblue', # 折线颜色
         marker = 'o', # 折线图中添加圆点
         markersize = 3, # 点的大小
         )
# 修改x轴和y轴标签
plt.xlabel('迭代次数')
plt.ylabel('误差值')
# 显示图形
plt.show()

结果:

迭代第14次后,误差为0
所求方程式的根为0.567143290409784

在这里插入图片描述

双点弦法

为了加速收敛,改用两个端点都在变动的弦,即用商差(f(xk)-f(xk-1))/(xk-xk-1)替代牛顿公式中的导数f’(x),而导出下图的弦截公式。这种迭代法称为双点弦法、快速弦法或离散牛顿法。
双点弦法的收敛速度比单点弦法快,仅稍慢于牛顿法,是超线性收敛的。
双点弦法在计算xk+1时要用到前面两点的值xk,xk+1,这种迭代法称为两步法,使用这类方法,在计算前必须先提供两个初始值。
在这里插入图片描述
在这里插入图片描述

双点弦法的例题——有区间

求方程式:x3- 0.165x2 + 3.993×10-4 = 0在(0,0.11)的根

约定一个误差,当误差小于某个数值的时候,迭代停止

代码:

x0 = 0  #区间下限
x1 = 0.11  #区间上限

x_list = [x1]
i = 0

def f(x):
    f = x**3 - 0.165*x**2 + 3.993*10**(-4)
    return f

while True:
    x2 = x1 - f(x1)*(x1-x0)/(f(x1)-f(x0))
    x0 = x1
    x1 = x2
    x_list.append(x2)
    if len(x_list) > 1:
        i += 1
        error = abs((x_list[-1] - x_list[-2]) / x_list[-1])
        if error < 10**(-6):
            print(f'迭代第{i}次后,误差小于10^-6')
            break
    else:
        pass

print(f'所求方程式的根为{x_list[-1]}')

结果:

迭代第6次后,误差小于10^-6
所求方程式的根为0.06237758151374951

迭代至电脑默认误差为0

代码:

from sympy import *

x = symbols('x')
x0 = 0  #区间下限
x1 = 0.11  #区间上限

x_list = [x1]
i = 0

def f(x):
    f = x**3 - 0.165*x**2 + 3.993*10**(-4)
    return f

while True:
    x2 = x1 - f(x1)*(x1-x0)/(f(x1)-f(x0))
    x0 = x1
    x1 = x2
    x_list.append(x2)
    if len(x_list) > 1:
        i += 1
        error = abs((x_list[-1] - x_list[-2]) / x_list[-1])
        if error == 0:
            print(f'迭代第{i}次后,误差为0')
            break
    else:
        pass

print(f'所求方程式的根为{x_list[-1]}')

结果:

迭代第7次后,误差为0
所求方程式的根为0.06237758151374951

画迭代图

代码:

import matplotlib.pyplot as plt

x0 = 0  #区间下限
x1 = 0.11  #区间上限

x_list = [x1]
i = 0
x_values = []
y_values = []

def f(x):
    f = x**3 - 0.165*x**2 + 3.993*10**(-4)
    return f

while True:
    x2 = x1 - f(x1)*(x1-x0)/(f(x1)-f(x0))
    x0 = x1
    x1 = x2
    x_list.append(x2)
    if len(x_list) > 1:
        i += 1
        error = abs((x_list[-1] - x_list[-2]) / x_list[-1])
        x_values.append(i)
        y_values.append(error)
        if error < 10**(-6):
            print(f'迭代第{i}次后,误差小于10^-6')
            break
    else:
        pass

print(f'所求方程式的根为{x_list[-1]}')

#设置绘图风格
plt.style.use('ggplot')
#处理中文乱码
plt.rcParams['font.sans-serif'] = ['Microsoft YaHei']
#坐标轴负号的处理
plt.rcParams['axes.unicode_minus']=False
#横坐标是迭代次数
#纵坐标是误差值
plt.plot(x_values,
         y_values,
         color = 'steelblue', # 折线颜色
         marker = 'o', # 折线图中添加圆点
         markersize = 3, # 点的大小
         )
# 修改x轴和y轴标签
plt.xlabel('迭代次数')
plt.ylabel('误差值')
# 显示图形
plt.show()

结果:

迭代第6次后,误差小于10^-6
所求方程式的根为0.06237758151374951

在这里插入图片描述
可与牛顿迭代法进行比较:
牛顿迭代法(Newton’s Method)迭代求根的Python程序

双点弦法例题——单点

求方程式:x = exp(-x)在0.5附近的根
即求方程式xexp(x)-1=0在0.5附近的根
双点弦法需要两个初始点,所以另一个初始点可以取x0=0.5附近的值,这里我取x1=0.6。
代码:

from sympy import *
import matplotlib.pyplot as plt
x0 = 0.5
x1 = 0.6

x_list = [x1]
i = 0
x_values = []
y_values = []

def f(x):
    f = x * exp(x) - 1
    return f

while True:
    x2 = x1 - f(x1)*(x1-x0)/(f(x1)-f(x0))
    x0 = x1
    x1 = x2
    x_list.append(x2)
    if len(x_list) > 1:
        i += 1
        error = abs((x_list[-1] - x_list[-2]) / x_list[-1])
        x_values.append(i)
        y_values.append(error)
        if error == 0 :
            print(f'迭代第{i}次后,误差为0')
            break
    else:
        pass

print(f'所求方程式的根为{x_list[-1]}')

#设置绘图风格
plt.style.use('ggplot')
#处理中文乱码
plt.rcParams['font.sans-serif'] = ['Microsoft YaHei']
#坐标轴负号的处理
plt.rcParams['axes.unicode_minus']=False
#横坐标是迭代次数
#纵坐标是误差值
plt.plot(x_values,
         y_values,
         color = 'steelblue', # 折线颜色
         marker = 'o', # 折线图中添加圆点
         markersize = 3, # 点的大小
         )
# 修改x轴和y轴标签
plt.xlabel('迭代次数')
plt.ylabel('误差值')
# 显示图形
plt.show()

结果:

迭代第6次后,误差为0
所求方程式的根为0.567143290409784

在这里插入图片描述

  • 12
    点赞
  • 78
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值