求函数在给定范围内的一个根

朋友们 下面是原题:
假设 f 是一个连续函数,对于某些已知的 a 和 b,f (a) < 0和 f (b) > 0,为简单起见,假设 a < b,那么一定存在某些 c,使得 f (c) = 0。
(a)写一个函数根(f,a,b) ,它接受一个函数 f,两个浮点数 a 和 b,并返回根 c 提示: 检查间隔中点的符号。

在利用二分法求根的时候我这部分是这么写的:

img


报错:

img

但是我这么写了就可以了:

img


这是为什么呀😭

>>> def root(f, a, b):
    fa, fb = f(a), f(b)
    if fa * fb >= 0:
        return '函数f在%f和%f之间无解'%(a, b)
    c = (a + b) / 2
    fc = f(c)
    if fa * fc < 0:
        return root(f, a, c)
    elif fb * fc < 0:
        return root(f, b, c)
    else:
        return c

    
>>> def f(x):
    return 7 * x - 6


>>> root(f, 2, 3)
'函数f在2.000000和3.000000之间无解'
>>> root(f, 0.5, 1)
0.8571428571428572
>>> root(f, 1, 0)
0.8571428571428572

你如果不写b=c和a=c,根本就不符合二分法的定义呀,怎么也得按二分法写吧

keyboardinterrupt报错是因为循环无限进行,我最先开始也没看出原因,运行后发现原先的写法只有部分情况才报错,比如输入的a,b是相反数。我在博主第一次的基础上加了两个输出:

img

img


一段时间后,观察规律,它会以重复值无限循环下去:

img

但是输入其他值,比如0,1,c的取值就是有限的,不会报错。我猜测原因是:在不更改ab值的情况下,c每次取的是a/b(具体看此时fc与哪一个的函数异号)和上一次c的平均值,按理来说会使fc无限趋近0直到等于0,但有一种情况是在fc最接近0时,再取一次c和a/b的均值时c'恰好是之前取过的c值,也就是会再循环一次趋近于0的过程,而绝对不报错就需要每次给a/b赋予新值,就可以避免c取到之前取过的值。