Reputation: 23
My professor is having me write a program to perform the bisection routine to find the root of an equation. Before I go on, here are the program files so far:
function [l,r,nf] = bisect(fname,a,b,tol)
nf=0;
if (fname(a)*fname(b))>0
errflag='Choose an interval (a,b) where f(a)*f(b) is negative'
root='N/A'
else
while abs(fname(a)-fname(b))>tol
p=a+(b-a)/2;
if (fname(a)*fname(p))<0
b=p;
else
a=p;
end
nf=nf+1;
end
end
nf
l=a
r=b
end
Aside from the bisect.m
file, he had us write a simple program fofx.m
to evaluate the equation at whatever point. It looks like:
function [y]=fofx(x)
y=cos(x)-sin(x);
end
He wants us to have the fofx.m
entered as an input argument so one can use any generic equation .m file. He has assigned us a test routine to operate the program. The test routine (which I am not allowed to change), is
try
delete('prog4run');
end
diary prog4run
format long e
[l,r,nfb] = bisect('fofx',0.7,0.9,1e-6);
p = l+(r-l)/2;
disp(' ')
disp(' ')
disp(' Bisect output:')
disp('root approx:'),p
disp(' ')
disp('error:'),abs(p-pi/4)
disp(' ')
disp('number of fcn evals:'),nfb
disp(' ')
disp(' ')
When I invoke the program in the command window by typing in:
bisect(@fofx,0.7,0.9,1e-6)
Bisect works perfectly. But when his test routine uses the line:
[l,r,nfb] = bisect('fofx',0.7,0.9,1e-6)
Even if I type this into the command window, I get the error:
Attempted to access fname(0.7); index must be a positive integer or logical.
Error in bisect (line 5)
if (fname(a)*fname(b))>0
Error in SCProg4Test (line 13)
[l,r,nfb] = bisect('fofx',0.7,0.9,1e-6);
Can anyone help me?
Upvotes: 2
Views: 193
Reputation: 8401
The problem is that the bisect
function expects fname
to be a function handle.
If fname
is a string, the parentheses intended to indicate passing arguments are actually indexes to the string array, and if the indexes are not integers or logicals, MALTAB throws that error.
The best thing to do is some upfront input checking before going to the routine. For example:
if ~isa(fname,'function_handle')
if ischar(fname)
fname = str2func(fname);
else
error('Input ''fname'' must be either a function handle or the name of a valid function.')
end
end
If fname
is a string that is also the name of a file in the current working directory or on the MATLAB path, str2func
will convert it into a handle and all will be well.
You can check if the string is a valid filename using exist(fname,'file')==2
if you wanted to be sure MATLAB can find the file.
You can also use the feval
function which excepts either a function handle or function name (a string) as the first argument and the inputs to the function as subsequent arguments:
vala = feval(fname,a);
I think this is a bit clunkier, but this is the process that the ode
suite in the MATLAB uses, which is why the first argument to ode45
can either be a handle or a string.
Upvotes: 2