The function below, bisection
, is supposed to find a root given three inputs: a function f
, and an interval defined using the two parameters a
and b
. The intention is that the value of a
and b
are changed within the function to approach a common point, as long as their signs are different.
When I call my function like this:
bisection( @(x)x-1 ,-2,3)
no output is returned. What am I doing wrong?
function X = bisection(f,a,b)
if ge((f(a)*f(b)),0)
disp('Wrong')
return;
end
X = (a+b)/2;
while abs(X)>0.01
if f(X)*f(a)>0
X=a;
else
X=b;
end
end
Enter the Infinite!
Well done! You've written your first (and not last, believe me) infinite loop. The problem is threefold. Firstly your stop condition was abs(X)
and should have been abs(f(X))
- you don't care for X
to be zero, you want f(X)
to be zeros. Secondly you don't update your your X
correctly so your break condition is never hit (unless you are lucky to give this function symmetrical a,b
bounds around the zero of the function). You could see this easily by adding a line like disp(f(X)); pause(0.5);
somewhere in the while-loop.
In general try to avoid infinite loops with some explicit stop condition. In my code below I've put in the interaction limit past which the algorithm will just stop (it would be more elegant to catch that condition and warn the user of hitting the iteration limit...).
function x0 = bisection(f,a,b)
assert(f(a)*f(b)<0,'Invalid f(x) range. f(a)*f(b) >= 0');
tol = 0.00001; % Tolerance
iter_limit = 10000; % Limit of number of iterations
iter = 0;
x0 = (a+b)/2; % Midpoint
while abs(f(x0)) > tol && iter < iter_limit
if f(x0)*f(a) > 0
a = x0; % Zero to the right of the midpoint
else
b = x0; % Zero to the left
end
x0 = (a+b)/2; % Recalculate midpoint
iter = iter + 1;
end
end
This should work no problem with
f = @(x)x-1;
bisection(f,-2,3);
I get something like 0.999992370... which is within specified tolerance from the actual answer (1).