python二分法、牛顿法求根

二分法求根

思路:对于一个连续函数,左值f(a)*右值f(b)如果<0,那么在这个区间内[a,b]必存在一个c使得f(c)=0

那么思路便是取中间点,分成两段区间,然后对这两段区间分别再比较,跳出比较的判断便是精确度

# 二分法求根
# 函数为exp(x)*lnx - x**2
import math
# 定义需要求根的函数,等会方便调用
def func(x):
    result = math.exp(x)*math.log(x) - x**2
    return result

def binary(accuracy,left,right):
    root = left
    count = 1
    acc = accuracy + 1
    while acc > accuracy:
        # 如果一开始左值或者右值满足条件,则打印
        if abs(func(left)) < accuracy:
            print(left)
        elif abs(func(right)) < accuracy:
            print(right)
        else:
            # 如果都不满足,那么进行二分
            print(left)
            mid = (left+right)/2
            if func(left)*func(mid) < 0:
                right = mid
            else:
                left = mid
        count += 1
        root = left
        acc = abs(func(root))
    # 这里分两次打印,是对不同需求进行输出,比如作为一个接口,那么上面的打印注释掉,下面的换成return即可
    print("final %d round is %.6f"%(count,root))
1
1
1
1.375
...
1.6945991516113281
final 22 round is 1.694601

牛顿法求根

运用泰勒展开

$f(x) \approx f(x_0) + f'(x_0)(x-x_0)$

即假定一开始的点为$x_0$,那么即将更新的点$x$,应该令$f(x)=0$,那么进行迭代之后,有 $x_{k+1}=x_k-\frac{f(x_0)}{f'(x_0)}$,那么代码即可得到

# 牛顿法求根
# 函数为exp(x)*lnx - x**2
# 导数为exp(x)lnx+exp(x)*(1/x)-2*x
import math
def newton(accuracy,root):
    new_root = root
    acc = accuracy +1
    count = 1
    while acc > accuracy:
        print("%d round is %.6f"%(count,new_root))
        # 求值
        y = math.exp(new_root)*math.log(new_root)-new_root**2
        # 求导
        y_hat = math.exp(new_root)*math.log(new_root)+math.exp(new_root)*(1/new_root)-2*new_root
        # 牛顿法迭代求新值
        # 牛顿法对于导数为0的地方比较难跨越,是个缺陷
        new_root = new_root - y/y_hat
        count += 1
        acc = abs(y)
    print("final %d round is %.6f"%(count,new_root))
1 round is 4.000000
...
8 round is 1.694601
final 9 round is 1.694601

posted on 2021-11-29 16:14  lpzju  阅读(872)  评论(0编辑  收藏  举报

导航