9.3 参数传递
MATLAB中参数传递过程是按值传递。也就是说,在函数调用过程中,MATLAB将传入的实际变量值赋值为形式参数指定的变量名,这些变量都存储在函数的变量空间中,这和工作区变量空间是独立的,每一个函数在调用中都有自己独立的函数空间。
例如,在MATLAB中编写函数:
function y = myfun(x, y)
在命令行窗口中通过a = myfun(3,2)调用此函数,那么MATLAB首先会建立myfun函数的变量空间,把3赋值给x,把2赋值给y,然后执行函数实现的代码。在执行完毕后,把myfun函数返回的参数y的值传递给工作区变量a,调用过程结束后,函数变量空间被清除。
9.3.1 输入和输出参数的数目
MATLAB的函数可以具有多个输入或输出参数。通常在调用时,需要给出和函数声明语句中一一对应的输入参数;而输出参数个数可以按参数列表对应指定,也可以不指定。在不指定输出参数调用函数时,MATLAB默认把输出参数列表中的第一个参数的数值返回给工作区变量ans。
在MATLAB中可以通过nargin和nargout函数确定函数调用时实际传递的输入和输出参数个数,结合条件分支语句,就可以处理函数调用中指定不同数目的输入和输出参数的情况。
例9-8:输入和输出参数数目的使用示例。
创建M文件并命名为mythe.m,利用M文件编辑器在M文件中输入:
function [n1, n2] = mythe(m1, m2) if nargin == 1 n1 = m1; if nargin == 2 n2 = m1; end else if nargout == 1 n1 = m1 + m2; else n1 = m1; n2 = m2; end end
在命令行窗口中依次运行mythe函数,输出结果如下:
>> m = mythe(4) m = 4 >> [m, n] = mythe(4) m = 4 n = 4 >> m = mythe(4, 8) m = 12 >> [m, n] = mythe(4, 8) m = 4 n = 8 >> mythe(4, 8) ans = 4
指定输入和输出参数个数的情况比较好理解,只要对应函数M文件中对应的if分支项即可;而不指定输出参数个数的调用情况,MATLAB是按照指定了所有输出参数的调用格式对函数进行调用的,不过在输出时只把第一个输出参数对应的变量值赋给工作区变量ans。
9.3.2 可变数目的参数传递
函数nargin和nargout结合条件分支语句,可以处理可能具有不同数目的输入和输出参数的函数调用,但这要求对每一种输入参数数目和输出参数数目的结果分别进行代码编写。
在有些情况下,用户可能并不能确定具体调用中传递的输入参数或输出参数的个数,即具有可变数目的传递参数,在MATLAB中可通过varargin和varargout函数实现可变数目的参数传递,使用这两个函数对于处理具有复杂的输入和输出参数个数组合的情况也是便利的。
函数varargin和varargout把实际的函数调用时传递的参数值封装成一个元胞数组,因此,在函数实现部分的代码编写中,就要用访问元胞数组的方法访问封装在varargin和varargout函数中的元胞或元胞内的变量。
例9-9:可变数目的参数传递示例。
创建M文件并命名为myth.m,利用M文件编辑器在M文件中输入:
function y = myth(x) a = 0; for i = 1 : 1 : length(x) a = a + mean(x(i)); end y = a / length(x);
函数myth以x作为输入参数,从而可以接收可变数目的输入参数,函数实现部分首先计算了各个输入参数(可能是标量、一维数组或二维数组)的均值,然后计算这些均值的均值。在命令行窗口中依次运行myth函数,结果如下:
>> myth([4 3 4 5 1]) ans = 3.4000 >> myth(4) ans = 4 >> myth([2 3; 8 5]) ans = 5 >> myth(magic(4)) ans = 8.5000
9.3.3 返回被修改的输入参数
前面已经讲过,MATLAB函数有独立于MATLAB工作区的自己的变量空间,因此输入参数在函数内部的修改,都只具有和函数变量空间相同的生命周期,如果不指定将此修改后的输入参数值返回到工作区间,那么在函数调用结束后,这些修改后的值将被自动清除。
例9-10:函数内部的输入参数修改示例。
创建M文件并命名为mytha.m,利用M文件编辑器在M文件中输入:
function y = mytha(x) x = x + 2; y = x .^ 2;
在mythe函数的内部,首先修改了输入参数x的值(x=x+2),然后以修改后的x值计算输出参数y的值(y = x.^2)。在命令行窗口中依次运行,结果如下:
>> x = 2 x = 2 >> y = mytha(x) y = 16 >> x x = 2
由此结果可见,调用结束后,函数变量区中的x在函数调用中被修改,但此修改只在函数变量区有效,这并没有影响到MATLAB工作区变量空间中变量x的值,函数调用前后,MATLAB工作区中的变量x始终取值为2。
那么,如果用户希望函数内部对输入参数的修改也对MATLAB工作区的变量有效,就需要在函数输出参数列表中返回此输入参数。对于例9-10中的函数,则需要把函数修改为function[y,x] = mytha(x),而在调用时也要通过[y,x] = mytha(x)语句。
例9-11:将修改后的输入参数返回给MATLAB工作区。
创建M文件并命名为mythb.m,利用M文件编辑器在M文件中输入:
function [y, x] = mythb(x) x = x + 2; y = x .^ 2;
随后在命令行窗口中运行,结果如下:
>> x = 3 x = 3 >> [y, x] = mythb(x) y = 25 x = 5 >> x x = 5
通过函数调用后,MATLAB工作区中变量x的取值从3变为8,可见通过[y,x]=mythb(x)调用,实现了函数对MATLAB工作区变量的修改。
9.3.4 全局变量
通过返回修改后的输入参数,可以实现函数内部对MATLAB工作区变量的修改,而另一种殊途同归的方法是使用全局变量。声明全局变量需要用到global关键词,其调用格式为global variable。
通过全局变量可以实现MATLAB工作区变量空间和多个函数的函数空间共享,这样,多个使用全局变量的函数和MATLAB工作区共同维护这一全局变量,任何一处对全局变量的修改,都会直接改变此全局变量的取值。
在应用全局变量时,通常在各个函数内部通过global variable语句声明,在命令行窗口或脚本M文件中也要先通过global声明,然后进行赋值。
例9-12:全局变量的使用示例。
创建M文件并命名为mythc.m,利用M文件编辑器在M文件中输入:
function y = mythc(x) global a; a = a + 9; y = cos(x);
随后在命令行窗口中声明全局变量赋值调用:
>> global a >> a = 2 a = 2 >> mythc(pi) ans = -1 >> cos(pi) ans = -1 >> a a = 11
通过例9-12可见,用global将a声明为全局变量后,函数内部对a的修改也会直接作用到MATLAB工作区中。函数调用一次后,a的值从2变为11。
本章小结
MATLAB提供了极其丰富的内部函数,使得用户可以通过命令行调用就可以完成很多工作,但是想要更加高效地利用MATLAB建模,离不开MATLAB编程。
通过本章的学习,读者应该熟悉并掌握MATLAB中各种类型的函数,尤其对曲线拟合函数、参数估计函数和插值函数,需要熟练运用。