python二分法求方程的根_方程求根-二分法、牛顿法、割线法(Python)

课堂笔记整理:方程求根-二分法、牛顿法、割线法。

内容来自周善贵老师的《计算物理》课程。

二分法

数学基础:对于连续函数

构成的方程:

,如果在区间

上满足:

,则区间

内至少存在一点

,使得

基本思想:取区间中点

,如果

,则根位于区间

内;否则根位于区间

内。对根存在的区间继续取中点,以此类推,直到当前根(cur_root)的函数值小于可接受误差为止。

对于方程

,使用二分法求根的Python代码如下:

import math

def func(cur_root):

func = math.exp(cur_root) * math.log(cur_root) - cur_root ** 2

return func

def binary(convergence, left, right):

print('current acceptable error: ' + str(convergence) + '\n')

error = convergence + 1 # 循环开始条件

cur_root = left

count = 1

while error > convergence:

if abs(func(left)) < convergence:

print('root = ' + str(left))

elif abs(func(right)) < convergence:

print('root = ' + str(left))

else:

print(str(count) + ' root = ' +str(cur_root))

middle = (left + right) / 2

if (func(left) * func(middle)) < 0:

right = middle

else:

left = middle

cur_root = left

error = abs(func(cur_root))

count += 1

convergence = float(input("your acceptable error:"))

left = float(input('left: '))

right = float(input('right: '))

binary(convergence, left, right)

要求误差不高于

,区间取

left: 1

right: 4

current acceptable error: 1e-06

第21步后误差满足条件:

21 root = 1.6945991516113281

牛顿法

将函数在根附近泰勒展开:

取线性阶近似,可得:

可以解得:

即为牛顿法迭代公式。

在迭代公式中,每一个

都是由

减去

得到的。

对于方程

,使用牛顿法求根的Python代码如下:

import math

def newton(convergence, ini_root):

print('current acceptable error: ' + str(convergence) + '\n')

error = convergence + 1 #循环开始条件

cur_root = ini_root

count = 1 # 迭代计数

while error > convergence:

print(str(count) + ' root = ' +str(cur_root))

func = math.exp(cur_root) * math.log(cur_root) - cur_root**2

dif_func = math.exp(cur_root) * ((1 / cur_root) + math.log(cur_root)) - 2 * cur_root

cur_root = cur_root - func / dif_func # 进行迭代

error = abs(func) # 计算误差

count += 1

convergence = float(input("your acceptable error:"))

ini_root = float(input('your initial root '))

newton(convergence, ini_root)

依然要求误差不高于

,从4开始迭代:

your initial root 4

current acceptable error: 1e-06

只需迭代7次即可结束,比二分法效率高很多:

8 root = 1.6946010436031655

割线法(分立牛顿法)

在牛顿法中,每一步都需要计算当前点的导数值,需要手动求导。如果不想人工求导,可以使用两点割线来代替切线,从而得到割线法,因此割线法又称分立牛顿法。

使用

两点计算的割线斜率为:

代替牛顿法中的

,可得割线法迭代式:

import math

def func(cur_root):

func = math.exp(cur_root) * math.log(cur_root) - cur_root ** 2

return func

def secant(convergence, x_0, x_1):

print('current acceptable error: ' + str(convergence) + '\n')

error = convergence + 1

cur_root = x_1

count = 1

while error > convergence:

print(str(count) + ' root = ' + str(cur_root))

sect = (func(x_1) - func(x_0)) / (x_1 - x_0)

cur_root = cur_root - func(x_1) / sect

error = abs(func(cur_root))

x_0 = x_1

x_1 = cur_root

count += 1

convergence = float(input("your acceptable error:"))

x_0 = float(input('x_0: '))

x_1 = float(input('x_1: '))

secant(convergence, x_0, x_1)

继续要求误差不高于

,从4开始迭代:

x_0: 4

x_1: 3

current acceptable error: 1e-06

可以在8次迭代之后结束:

9 root = 1.694602010833161

可以看到,牛顿法及其变种割线法,相对于二分法是十分高效的,但是牛顿法也有局限。牛顿法在某些情况下并不收敛,例如牛顿法求方程

的根,每一次取切线进行迭代都会使当前

更加远离方程的根,最终跑到无穷大溢出报错:

1023 root = (inf-1.2158939983623275e+294j)

OverflowError: complex exponentiation

Reference:

周善贵,《计算物理》课程讲义

你可能感兴趣的:(python二分法求方程的根)