MATLAB系列05:自定义函数
- 5. 自定义函数
- 5.1 MATLAB函数简介
- 5.2 在MATLAB中传递变量:按值传递机制
- 5.3 选择性参数
- 5.4 用全局内存分享数据
- 5.5 在函数两次调用之间本地数据的存储
- 5.6 函数的函数(function functions)
- 5.7 子函数和私有函数
- 5.8 总结
5. 自定义函数
MATLAB 有一个专门的机制,在建立最终的程序之前用于独立地开发与调试每一个子程序。每一个子程序都可以独立函数的形式进行编程,在这个程序中,每一个函数都能独立地检测与调试,而不受其他子程序的影响。良好的函数可以大大提高编程的效率。它的好处如下:
-
子程序的独立检测
每一个子程序都可以当作一个独立的单元来编写。在把子程序联合成一个的大程序之前,我们必须检测每一个子程序以保证它运转的正确性。
-
代码的可复用性
在许多的情况下,一个基本的子程序可应用在程序的许多地方。可重用性代码有两大好处:它大大提高了整体编程效率,它更易于调试。
-
远离意外副作用
函数通过输入参数列表(input argument list)从程序中读取输入值,通过输出参数列表(output argument list)给程序返回结果。程序中,只有在输入参数列表中的变量才能被函数利用。函数中,只有输出参数列表中的变量才能被程序调用。好的函数的应用可以通过数据隐藏使问题最小化。在主函数中的变量在函数中是不可见的(除了在输入变量列表中的变量),在主程序中的变量不能被函数任意修改。所以在函数中改变变量或发生错误不会在程序的其他部分发生意外的副作用。
5.1 MATLAB函数简介
MATLAB 函数是一种特殊形式的 M 文件,它运行在独立的工作区。它通过输入参数列表接受输入数据,它通过输出参数列表返回结果给输出参数列表。 MATLAB 函数的基本形式如下:
function [outarg1, outarg2, ...] = fname(inarg1, inarg2, ...)
%H1 comment line
%Other comment lines
...
(Executable code)
...
(return)
在一个函数中的初始注释行有特定的目的。在 function 语句的第一个行注释被称为 H1注释行。它应当是对本函数功能的总结。这一行的重要性在于,通过lookfor
命令它能被搜索到并显示出来。从 H1 注释行到第一个空行或第一个可执行性语句可以通过 help 命令或帮助窗口搜索到。
输入参数列表是名字的列表,这些名字代表从调用者到函数的值。这些名字被称作形参。当函数被调用时,它们只是从调用者得来实际变量的占位符而已。相似地,输出参数列表也形参组成,当函数结束运行时,这些形参是返回到调用者的值的占位符。
在一个表达式中,调用一个函数需要用到实参列表。在命令窗口直接(或在脚本文件中,另一个函数中)键入函数的名字就可以调用这个函数了。当调用一个函数时,第一个实参的值用在第一个形参的位置,而且其余的形参和实参都一一对应。
5.2 在MATLAB中传递变量:按值传递机制
maltab 程序与它们函数之间的交互用是按值传递机制。当一个函数调用发生时, MATLAB将会复制实参生成一个副本,然后把它们传递给函数。这次复制是非常重要的,因为它意味着虽然函数修改了输入参数,但它并没有影响到调用者的原值。这个特性防止了因函数修改变量而导致的意想不到的严重错误。
实际上, MATLAB 用了两种方法,它先对函数的每一个参数进行分析,确定函数的那些参数进行了修改。如果函数没有修改这个参数,它将不会对此参数进行复制,而是简单地指向程序外面的变量,如果函数修改了这个参数,那么这个复制就会被执行)。示例:
5.3 选择性参数
许多的 MATLAB 函数都支持选择性输入参数和输出参数。例如,我们调用 plot 函数,输入参数既可以少到 2 个,也可以多到 7 个参数。从另一方面说,函数 max 既支持一个输出参数,也支持两个输出参数。如果只有一个输出参数, max 将会返回函数的最大值。如果有两个输出参数将会返回数组的最大值和最大值所在的位置。 在 MATLAB 中有八种专门的函数用于获取关于选择性参数的信息和用于报告这些参数的错误,这里介绍6个。
函数 nargin 和 nargout 只用在用户自定义函数中。当他们被调用时,这些函数将会分别返回实际输入、输出参数的个数。如果一个函数在被调用时含有过多或过少的参数,函数nargchk 将会产生一个包含标准错误的字符串。此函数的语法如下:
message = nargchk(min_args, max_args, num_args);
其中 min_args 是指参数的最小个数, max_args 是指参数的最大个数, num_args 是指参数的实际个数。如果参数的个数不在允许的范围,将会产生一个标准的错误信息。如果参数的个数在允许的范围之内,那么这个函数将返回一个空字符。
函数 error 是用于显示标准的错误信息和用于中止导致错误信息的自定义函数的一种标准方式。这个函数的语法是 error(‘msg’), 其中 msg 是一个包含错误信息的字符串。当 error函数执行,它将会中止当前函数,并返回到键盘输入状态,在命令窗中显示出错误信息。如果这个信息字符中为空, error 函数将什么也不做,当前函数继续执行。 函数 error 与函数nargchk 配合,当有错误发生时, error 将产生一个信息字符串,当没有错误时, error 将产生一个空字符。
数 warning 是显示警告的函数名及所在行的信息,并继续执行当前函数。此函数的语法为 warning(‘msg’),其中 msg 是指含有警告信息的字符串。当执行 waring 函数时,它将在命令窗口显示警告信息,列出警告的函数名及所在行的信息。如果信息子符串为空, warning将什么也不做。同时,当前函数将继续执行。
当一个函数被调用时, inputname 函数将会返回实参的名字。 inputname 函数的语法为
name = inputname(argno);
其中 argno 是参数的序号。如果这个参数是一个变量,那么返回将只是变量名。如果参数是一个表达式,那么这个函数将会返回空字符。例如考虑下面的函数
function myfun(x, y, z)
name = inputname(2);
disp(['The second argument is named ' name]);
>> dog='dog';
>> cat='cat';
>> my_fun(dog,cat)
The second argument is named cat
>> my_fun(dog,cat+1)
The second argument is named
5.4 用全局内存分享数据
全局内存是指内存的一种特殊类型,它能够被所有的工作区访问。如果一个变量在函数中被声明全局变量,那么它将占用的是全局内存,而不是本地工作区。如果相同的变量在另一个函数中被声明为全局变量,那么这个变量所占有内存区域就是第一个函数中的相同变量。声明有全局变量的脚本文件或函数将有办法访问相同的值,所以全局变量为函数之间分享数据提供了一个方法。 全局变量的声明要用到 global 主语句,基本形式如下:
global var1 var2 var3 ...
每一个全局变量在函数第一次使用之前必须声明如果在本地工作区中已经被创建,那么声明为再次声明全局变量将会产生错误。为了避免这种错误,在函数中的初始注释行之后和第一个可执行性语句之前声明全局变量。
5.5 在函数两次调用之间本地数据的存储
持久内存(persistent memory)是内存的一种类型, 在函数上一次调用之后, 这一步调用之前, 本地变量被保存在持久内存, 值不变。持久变量应用语句声明。 它的形式如下:
persistent var1 var2 var3 ...
5.6 函数的函数(function functions)
函数的函数(function functions)是指函数的输入参数中含有其他的函数,传递给函数的函数的变量名一般情况应用于这个函数执行的过程中。例如, MATLAB 中有一个函数的函数叫做 fzero。 这个函数用于找到传递给它的函数值为 0 时的自变量。例如,语句 fzero(‘cos’, (0, pi)), 它能确定 cos 函数在区间[0, π]中何时为 0。语句 fzero(‘exp(x)-2’, [0 1])在区间[0, 1]中何时为 0。当这些语句被执行时,将产生如下的结果:
>> fzero('cos',[0 pi])
ans =
1.5708
>> fzero('exp(x)-2',[0 1])
ans =
0.6931
常见函数的函数如下:
5.7 子函数和私有函数
在一个单个的文件中我们可以创建多个函数。如果超过 1 个的函数出现在一个文件中,那么最上面的那个函数为普通函数,下面的函数称为子函数或中间函数。子函数看起来和普通函数一样,但是只能被同一文件中的函数调用。示例:
function [avg, med] = mystats(u)
%MYSTATS Find mean and median with internal functions.
% Function MYSTATS calculates the average and median
% of a data set using subfunctions.
n = length(u);
avg = mean(u, n);
med = median (u, n);
function a = mean(v, n)
% Subfunction to calculate average.
a = sum(v) / n;
function m = median(v, n)
% Subfunction to calculate median
w = sort(v);
if rem(n, 2) ==1
m = w((n+1)/2);
else
m = (w(n/2) + w(n/2 + 1))/2;
end