Python: Finding multiple roots of nonlinear equation

前端 未结 3 1444
死守一世寂寞
死守一世寂寞 2020-12-03 05:38

Assume the following function:

f(x) = x * cos(x-4)

With x = [-2.5, 2.5] this function crosses 0 at f(0) = 0

3条回答
  •  伪装坚强ぢ
    2020-12-03 06:03

    I once wrote a module for this task. It's based on chapter 4.3 from the book Numerical Methods in Engineering with Python by Jaan Kiusalaas:

    import math
    
    def rootsearch(f,a,b,dx):
        x1 = a; f1 = f(a)
        x2 = a + dx; f2 = f(x2)
        while f1*f2 > 0.0:
            if x1 >= b:
                return None,None
            x1 = x2; f1 = f2
            x2 = x1 + dx; f2 = f(x2)
        return x1,x2
    
    def bisect(f,x1,x2,switch=0,epsilon=1.0e-9):
        f1 = f(x1)
        if f1 == 0.0:
            return x1
        f2 = f(x2)
        if f2 == 0.0:
            return x2
        if f1*f2 > 0.0:
            print('Root is not bracketed')
            return None
        n = int(math.ceil(math.log(abs(x2 - x1)/epsilon)/math.log(2.0)))
        for i in range(n):
            x3 = 0.5*(x1 + x2); f3 = f(x3)
            if (switch == 1) and (abs(f3) >abs(f1)) and (abs(f3) > abs(f2)):
                return None
            if f3 == 0.0:
                return x3
            if f2*f3 < 0.0:
                x1 = x3
                f1 = f3
            else:
                x2 =x3
                f2 = f3
        return (x1 + x2)/2.0
    
    def roots(f, a, b, eps=1e-6):
        print ('The roots on the interval [%f, %f] are:' % (a,b))
        while 1:
            x1,x2 = rootsearch(f,a,b,eps)
            if x1 != None:
                a = x2
                root = bisect(f,x1,x2,1)
                if root != None:
                    pass
                    print (round(root,-int(math.log(eps, 10))))
            else:
                print ('\nDone')
                break
    
    f=lambda x:x*math.cos(x-4)
    roots(f, -3, 3)
    

    roots finds all roots of f in the interval [a, b].

提交回复
热议问题