pythonmachine-learningdata-science-experience

Finding the root of an equation using binary search python


help me here, estimating the root of the equation. Here is a code:

def binary_search(f,domain, MAX = 1000):
    start, end = domain
    if start >= end:
        raise ValueError("Domain is empty")
    mid = (start + end) / 2
    fmid = f(mid)
    step = 0
    while abs(fmid) > 0.0001 and step < MAX:
        if fmid < 0:
            start = mid
        else:
            end = mid
        mid = (start + end) / 2
        fmid = f(mid)
        step += 1
    return round(mid, 2)

Here are inputs:

import numpy as np

f = lambda x:(np.sin(x)**2)*(x**2)-2
domain = (0,2)
x=binary_search(f,domain)
x

The problem with this code is not consistent. When the domain is (0, 2) it gives the expected answer, which is 1.43. However, in the domain (2, 3) and (-2, -1) it gives wrong answers which are 2.0 and -2.0 respectively. But I noticed that when I change the if statement under ‘while loop’ from "f mid < 0” to “fmid > 0”, the domains (2, 3) and (-2, -1) give correct answers, which are 2,56 and -1,43 respectively. But now, the domain (0, 2) gives the wrong answer. How can I fix this?


Solution

  • The problem lies in the fact that your code assumes whether the function is increasing or decreasing. And the logic you are refering to just changes this assumption. However your function is increasing in some intervals and decreasing in the others.

        if fmid < 0:
            start = mid
        else:
            end = mid
    

    should be (using import numpy as np)

        if np.sign(fmid) == np.sign(f(start)):
            start = mid
        else:
            end = mid
    

    or without numpy

        if fmid * f(start) >= 0:
            start = mid
        else:
            end = mid
    

    In other words we move the left limit iff the signs between mid and left match. Alternatively you could just run your function twice with arguments shuffled and get the smaller absolute value.