fctrl1()
’, ‘ fctrl2()
’ is easier to program as well as to read, but is subject to runtime error that is caused by the excessive use of stack memory as the number of recursive calls increases with large n
. Another disadvantage of ‘ fctrl2()
’ is that it is time‐inefficient for the number of function calls, which increases with the input argument ( n
). In this case, a professional programmer would consider the standpoint of users to determine the programming style. Some algorithms like the adaptive integration (Section 5.8), however, may fit the recursive structure perfectly.
function m=<b>fctrl1</b><![CDATA[(n) m=1; for k=2:n, m=m*k; end
|
function m=<b>fctrl2</b><![CDATA[(n) if n<=1, m=1; else m=n*fctrl2(n-1); end
|
1.3.4 To Avoid Runtime Error
A good program guides the program users who do not know much about the program and at least give them a warning message without runtime error for their minor mistake. If you do not know what runtime error is, you can experience one by taking the following steps:
function m=<b>fctrl</b><![CDATA[(n) if n<0, error('The factorial of negative number ??'); else m=1; for k=2:n, m=m*k; end end
1 Make and save the following routine ‘ fctrl()’ in an M‐file named “fctrl.m” in a directory listed in the MATLAB search path.
2 Type fctrl(‐1) into the MATLAB Command window. Then you will see>fctrl1(-1) ans = 1
This seems to imply that (−1)! = 1, which is not true. It is caused by the mistake of the user who tries to find (−1)! without knowing that it is not defined. This kind of runtime error seems to be minor because it does not halt the process. But it needs special attention for it may not be easy to detect. If you are a good programmer, you will insert some error handling statements in the function ‘ fctrl()
’ as above. Then, when someone happens to execute fctrl(‐1)
in the Command window or through an M‐file, the execution stops and he will see the error message in the Command window as
Error using fctrl (line 2) The factorial of negative number ??
This shows the error message (given as the input argument of the ‘ error()
’ routine) together with the name of the routine in which the accidental ‘error’ happens, which is helpful for the user to avoid the error.
Most common runtime errors are caused by an ‘out of domain’ index of array and the violation of matrix dimension compatibility, as illustrated in Section 1.1.7. For example, consider the ‘ Gauss(A,B)
’ routine in Section 2.2.2, whose job is to solve a system of linear equations Ax=B
for x
. To appreciate the role of the fifth line handling the dimension compatibility error in the routine, remove the line (by putting the comment mark %
before the line in the M‐file defining ‘ Gauss()
’) and type the following statements in the Command window:
>A=rand(3,3); B=rand(2,1); x=Gauss(A,B) Index exceeds matrix dimensions. Error in Gauss (line 10) AB=[A(1:NA,1:NA) B(1:NA,1:NB)]; % Augmented matrix
Then MATLAB gives you an error message together with the suspicious statement line and the routine name. But it is hard to figure out what caused the runtime error and you may get nervous lest the routine should have some bug. Now, restore the fifth line in the routine and type the same statements in the Command window:
>x=Gauss(A,B) Error using Gauss (line 8) A and B must have compatible dimension
This error message (provided by the programmer of the routine) helps you to realize that the source of the runtime error is the incompatible matrices/vectors A
and B
given as the input arguments to the ‘ Gauss()
’ routine. Very like this, a good program has a scenario for possible user mistakes and fires the ‘ error
’ routine for each abnormal condition to show the user the corresponding error message.
Many users often give more/fewer input arguments than supposed to be given to the MATLAB functions/routines and sometimes give wrong types/formats of data. To experience this type of error, let us try using the MATLAB function ‘ sinc1(t,D)
’, that is defined in an M‐file named “sinc1.m” as
function x=<b>sinc1</b><![CDATA[(t,D) if nargin<2, D=1; end %t(find(t==0))=eps; x=sin(pi*t/D)./(pi*t/D);
to plot the graph of a sinc function
With this purpose, type the following statements in the Command window:
D=0.5; b1=-2; b2=2; t=b1+[0:100]/100*(b2-b1); subplot(221), plot(t,sinc1(t,D)), axis([b1 b2 -0.4 1.2]) hold on, plot(t,sinc1(t),'r:')
The two plotting commands ‘ sinc1(t,D)
’ and ‘ sinc1(t)
’ yield the solid and dotted line graphs, respectively, as shown in Figure 1.7a where it should be noted that ‘ sinc1()
’ does not bother us and works fine even without the second input argument D
. We owe the second line in the function ‘ sinc1()
’ for the nice error‐handling service:
Figure 1.7 Graphs of sinc functions. Using ‘ sinc1()
’ without division‐by‐zero handling (a) and with division‐by‐zero handling (b).
if nargin<2, D=1; end
This line takes care of the case where the number of input arguments ( nargin
) is <2, by assuming that the second input argument is D=1
by default. This programming technique is the key to making the MATLAB functions adaptive to different number/type of input arguments, which is very useful for adding the user‐convenience into the MATLAB functions. To appreciate its role, we remove the second line or deactivate it by putting the comment mark %
in the beginning of the line in the M‐file defining ‘ sinc1()
’, and type the same statement in the Command window, trying to use ‘ sinc1()
’ without the second input argument.
>plot(t,sinc1(t),'k:') Not enough input arguments. Error in sinc1 (line 4) x=sin(pi*t/D)./(pi*t/D);
This time we get a serious error message with no graphic result. It is implied that the MATLAB function without appropriate error‐handling capability does not allow the user's default or carelessness.
However, you may feel annoyed by the hole at t = 0 in the graphs shown in Figure 1.7a. What caused such an ‘accident of hole’? It happened (with no warning message about ‘division‐by‐zero’) because not only the denominator but also the numerator of Eq. (1.3.6) becomes for t = 0 to make the value of Eq. (1.3.6) NaN
(not a number : undetermined
) while the true value of the sinc function at t = 0 is sinc(0) = 1 as obtained by applying the L'Hopital's rule [W-7]. To avoid the ‘accident of hole’ due to the NaN problem, activate the third line (in ‘ sinc1()
’) by deleting the comment mark %
in the beginning of the line where