When i apply my bisection to a numbers in a function it only returns the correct values with certain functions.
import numpy as np
def x_2(x):
return x**2-5
def x_sin_exp(x):
return 0.5 + -(x + np.sin(x)) * np.exp(-x**2.0)
def bisection(f: callable, a: float, b: float, tol=0.001, maxiter=100)-> tuple[float, int]:
r=(a+b)/2
for nit in range(maxiter+1):
r = (a + b) / 2.0
if np.abs(f(r))<tol:
return (r,nit)
elif f(a)*f(r)<0:
b = r
else:
a = r
return (r,nit)
For example, when apllying the x_2 it works correctly, but not with x_sin_exp as shown bellow:
bisection(x_2,-3,3)
returns correctly (-2.236083984375, 12)
bisection(x_sin_exp,-3,3)
returns incorrectly (3.0,100)
I have tried checking the symbols on the bisection function, and drawing them to check if the first outputed values are correct. The main problem is when it has to enter the else part of the function, it never does. I have tried with an other elif, but doesnt correct it.
The problem in your code arises from the initial choice of ( a ) and ( b ) for the function x_sin_exp
. The function x_sin_exp
does not have a root in the interval ([-3, 3]) such that ( f(a) \times f(b) < 0 ). Therefore, your bisection method does not enter the "else" part, and you get incorrect results.
First, make sure ( f(a) \times f(b) < 0 ) before running the bisection algorithm. Second, it's good to check for cases where the function at the endpoints is already within the tolerance.
Here's a revised version of your function:
import numpy as np
def bisection(f: callable, a: float, b: float, tol=0.001, maxiter=100) -> tuple[float, int]:
if f(a) * f(b) >= 0:
raise ValueError("f(a) and f(b) must have different signs.")
for nit in range(1, maxiter + 1):
r = (a + b) / 2.0
if np.abs(f(r)) < tol:
return r, nit
elif f(a) * f(r) < 0:
b = r
else:
a = r
return r, nit
Now, calling bisection(x_sin_exp, 3, 3)
will raise a ValueError
with a message explaining that ( f(a) ) and ( f(b) ) must have different signs.