【Python】二分法求函数零点

本文由阅教材拓展,灵感而生。

流程图

这里直接放上《普通高中教科书 数学 必修 第一册(RJ)》的 P146 页,包含笔算和流程图,写的过程中也是需要配合看的,而且程序逻辑比笔算逻辑更严密。

据此,我们基本上可以开始用编程语言编写程序了。

一个小插叙

这是我在晚修时花了两分钟手写的草稿代码:

我拿出来展示只是为了让大家函数名要牢记,不要像我一样。请把目光从那个 绝对值() 上移开

开始写程序

定义数学函数

首先我们需要定义函数,即把所需要的数学函数转化为编程用的函数,这个过程别无他法,只能靠手动,因为符合手写习惯的数学表达式不是合法的编程表达式。

你可以用 def 代码块或者直接用 lambda 语句定义函数(其中 lambda 语句产生的函数为匿名函数)。如果你的函数里包含一些基础运算符无法表示的运算,可以去 math 标准库里看看有没有符合要求的函数。下面是一些函数定义示例

# Linear Function
lambda x: x + 1  # y = x + 1

# Quadratic Function
def f(x):
    # y = x^2
    return x**2

主函数

在主函数里,我根据流程图的内容先设置了三个输入,分别获取精确度(ε),区间头(a),区间尾(b)。

还做了取模处理,让等于整数的浮点数直接显示为整数。

epsilon = float(input("ε= "))  # Accuracy
a = float(input("a="))  # Start of range
b = float(input("b="))  # End of range

if a % 1 == 0:
    a = int(a)
if b % 1 == 0:
    b = int(b)

主循环

while True:
    c = (a+b) / 2
    if c % 1 == 0:
        c = int(c)
    else:
        pass

    if f(a) * f(c):
        b = c
    else:
        if f(c) == 0:
            a = c
            break
        else:
            a = c

跳出循环后,就只有输出结果了,再加上一点人性化处理,就是下面这样:

x = a
if x % 1 == 0:
    x = int(x)
else:
    pass
print("x=" + str(x))

效果

程序写到这,基本上运行起来就已经很正常了,就是在你输完三个参数后,回车,结果就出来了(速度取决于电脑计算速度和精确度的大小)

# y = x - 1

[Input]
ε= 1
a=0
b=2

[Output]
x=1

这里拿的是课本里的练习题,最终用作业帮查答案验证:

例1

# y = x ** 3 + 1.1 * x ** 2 + 0.9 * x - 1.4

[Input]
ε= 0.1
a=0
b=1

[Output]
x=0.625

验证,答案正确。

如果你把精确度设置得非常小,那么结果也可以更精确,就是耗时更长(精确度大概为 10e-20,记不清了,耗时 2.5s):

[Output]
x=0.6706573107258097

完整代码

"""
@File   : bisection.py
@Author : @灰尘疾客
"""
def f(x):
    return x**2

def legality(f, a, b):
    return f(a) * f(b) < 0

def find_zero(f, a, b, eps):
    while abs(a - b) > eps:

        c = (a + b) / 2
        if c % 1 == 0:
            c = int(c)
        else:
            pass

        if f(c) == 0:
            a = c
            break
        elif f(a) * f(c) < 0:
            b = c
        else:
            a = c

    return a

def main():
    eps = 0.00000000000001
    a = 0
    b = 3

    if a % 1 == 0:
        a = int(a)
    if b % 1 == 0:
        b = int(b)

    if legality(f, a, b):
        a = find_zero(f, a, b, eps)
        x = a
        if x % 1 == 0:
            x = int(x)
    else:
        pass

    print(a)

if __name__ == "__main__":
    main()

总结

二分法求零点是在难以直接用 y=0 算出结果时才使用的,且要求图像在 y=0 附近连续不断;再这种方法算出来的只是估值,除非你把精确度设置得非常小(难以想象的那种小);最后你得把范围 ab 输对,否则会解出错误答案。

综上,建议大家能算出精确值时不要过度依赖二分法。

如何使用 Python 解方程(组)?

你可以试试使用 SumPy 库,参考链接

阅读剩余
THE END