2

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?

3
  • Your bisect function assumes that the first arg is a function handle, but apparently his test routine assumes that it's a string. Have you tried checking the type for the first arg and making it a function handle if it's not already. I don't have access to matlab right now, but something like this: if(ischar(fname)), eval( 'fhand = @(x)fname(x)' ); else fhand = fname; end Commented Oct 22, 2014 at 23:08
  • Seeing the code of the test routine would be more helpful than your own code as that's where the error originates. Make sure your providing use with the entire error message too. Commented Oct 22, 2014 at 23:10
  • @horchler , I added the full test routine and error message. Commented Oct 22, 2014 at 23:17

1 Answer 1

2

str2func

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.


feval

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.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.