MATLAB程序设计与应用 4.3 函数文件

MATLAB程序设计与应用

4. 第4章 MATLAB程序流程控制

4.3 函数文件

许多时候希望将特定的算法写成函数的形式,以提高程序的可重用性和程序设计的效率。

函数文件定义了输出参数和输入参数的对应关系,以方便外部调用。事实上
MATLAB提供的标准函数都是由函数文件定义的。

4.3.1 函数文件的基本结构

函数文件由function语句引导,其基本结构如下:

function 输出形参表 = 函数名(输入形参表)
注释说明部分
函数体语句

其中,以 function开头的一行为引导行,表示定义一个函数。函数名的命名规则与变量名相同。在函数定义时,输入输出参数没有分配存储空间,所以称为形式参数,简称形参。当有多个形参时,形参之间用逗号分隔:组成形参表。当输出形参多于一个时,则应该用方括号括起来,构成一个输出矩阵。

说明:

(1)关于函数文件名。函数文件名通常由函数名再加上扩展名.m组成,不过函数文件名与函数名也可以不相同。当两者不同时,MATLAB将忽略函数名,调用时使用函数文件名。为理解和记忆的方便,一般建议函数文件名和函数名统一。

(2)关于注释说明部分。注释说明包括如下3部分内容。

  • 紧随函数文件引导行之后以%开头的第一注释行。这一行一般包括大写的函数文件名和函数功能简要描述,供 lookfor关键词查询和help在线帮助用。
  • 第一注释行及之后连续的注释行。通常包括函数输入输出参数的含义及调用格式说明等信息,构成全部在线帮助文本。
  • 与在线帮助文本相隔一空行的注释行。包括函数文件编写和修改的信息,如作者、修改日期、版本等内容,用于软件档案管理。

(3)关于return 语句。如果在函数文件中插入了return语句,则执行到该语句就结束函数的执行,程序流程转至调用该函数的位置。通常,在函数文件中也可不使用returmn语句,这时在被调用函数执行完成后自动返回。

示例——编写函数文件,求半径为r的圆的面积和周长。

function [s , p] = fcircle(r)
% r 圆半径
% s 圆面积
% p 圆周长

s = pi * r * r;
p = 2 * pi * r;

调用函数

>> [s,p] = fcircle(10)

s =

  314.1593


p =

   62.8319

采用help命令或lookfor 命令可以显示出注释说明部分的内容,其功能和一般MATLAB函数的帮助信息是一致的。

>> help fcircle
  r 圆半径
  s 圆面积
  p 圆周长

也可以用 lookfor命令在 MATLAB的搜索路径中寻找并列出所有第一注释行包括指定关键词的文件。

4.3.2 函数调用
  1. 函数调用的格式

    函数文件建立好后,就可以调用该函数了,调用格式如下:

    [输出实参表] = 函数名(输入实参表)
    

    在调用函数时,函数输入输出参数称为实际参数,简称实参。要注意的是,函数调用时各实参出现的顺序、个数,应与函数定义时形参的顺序、个数一致,否则会出错。函数调用时,先将实参传递给相应的形参,从而实现参数传递,然后再执行函数的功能。

    示例——利用函数文件,实现直角坐标(x , y)和极坐标(p , θ)之间的转换。转换公式:

    在这里插入图片描述

    编写函数文件tran.m,再在main1.m脚本文件中调用函数

    %函数
    function [rho , theta] = tran(x , y)
    rho = sqrt(x * x + y * y);
    theta = atan(y / x);
    
    %脚本
    x = input('Please input x = ');
    y = input('Please input y = ');
    
    [rho , the] = tran(x , y);
    
    disp(['rho = ',num2str(rho)])
    disp(['the = ',num2str(the)])
    

    在这里插入图片描述

    运行脚本

    >> main1
    Please input x = 45
    Please input y = 45
    rho = 63.6396
    the = 0.7854
    

    实际上,MATLAB提供了直角坐标与极坐标之间转换的函数,分别如下:

    (1)[th,r]=cart2pol(x,y):将直角坐标转换为极坐标。

    (2) [x,y]=pol2cart(th,r):将极坐标转换为直角坐标。

    >> 
    >> [rho , the] = cart2pol(45 ,45)
    
    rho =
    
        0.7854
    
    
    the =
    
       63.6396
    
  2. 函数的递归调用

    在 MATLAB 中,函数可以嵌套调用,即一个函数可以调用其他函数,甚至调用它自身。一个函数调用它自身称为函数的递归调用。

    示例——利用函数的递归调用,求n的阶乘。

    在这里插入图片描述

    函数文件factor.m

    function f = factor(n)
    if n <= 1
        f = 1;
    
    else
        f = factor(n - 1) * n; % 递归调用
    end
    

    脚本文件

    % 求 s = 1! + 2! + 3! + 4! + 5!
    
    s = 0;
    
    n = input('Please input n = ');
    
    for i = 1 : n
        s = s + factor(i);
    end
    disp(['1到',num2str(n),'的阶乘和为:',num2str(s)])
    

    运行脚本文件

    K>> main2
    Please input n = 5
    1到5的阶乘和为:153
    

    示例——任意排列问题。MATLAB提供的函数randperm(n)可以产生一个从整数1到整数n的任意排列。编写一个函数来实现 randperm(n)函数的功能,即给出一个由任意数组成的行向量,然后产生这个行向量元素的任意排列。

    rndprm1.m

    function Y = rndprm1(X)
    
    [m , n] = size(X);
    if m > 1
        error('RNDPRM1 accepts as inputs only vectors');
    end
    
    Y = [];
    l = n;
    for i = 1 : n
        k = 1 + fix(1 * rand);
        x = X(k);
        Y = [Y , x];
        X(k) = [];
        l = l - 1;
    end
    

    rndprm2.m

    function Y = rndprm2(X)
    
    [m , n] = size(X);
    
    l = n;
    if m > 1
        error('RNDPRM2 accepts as inputs only vectors')
    end
    
    if n <= 1
        Y = X;
    else
        k = 1 + fix(1 * rand);
        x = X(k);
        X(k) = [];
    
        Z = rndprm2(X);
        Y = [Z , x];
        l = l - 1;
    end
    

    调用函数

    K>> rndprm1([34,6,3,54,2,5,454])
    
    ans =
    
        34     6     3    54     2     5   454
    
    K>> rndprm2([34,6,3,54,2,5,454])
    
    ans =
    
       454     5     2    54     3     6    34
    
4.3.3 函数参数的可调性

MATLAB在函数调用上有一个特点,就是函数所传递参数数目的可调性。凭借这一点,一个函数可完成多种功能。
在调用函数时,MATLAB用两个预定义变量nargin和nargout分别记录调用该函数时的输入实参和输出实参的个数。只要在函数文件中包含这两个变量,就可以准确地知道该函数文件被调用时的输入/输出参数个数,从而决定函数如何进行处理。

nargin用法示例

函数文件charray.m

function fout = charray(a , b ,c)

if nargin == 1
    fout = a;

elseif nargin == 2
    fout = a + b;

elseif nargin == 3
    fout = (a * b * c) / 2;
end

脚本文件mydemo.m

a = 1 : 3;
b = a';

x = charray(a);
y = charray(a,b');
z = charray(a , b ,3);


disp(['x =    ',num2str(x)])
disp(['y =    ',num2str(y)])
disp(['z =    ',num2str(z)])

运行脚本

>> mydemo
x =    1  2  3
y =    2  4  6
z =    21
>> 

在脚本文件 mydemo.m中,3次调用函数文件charray.m,因输入参数的个数分别是1、2,3,从而执行不同的操作,返回不同的函数值。

4.3.4 全局变量与局部变量

在MATLAB中,函数文件中的变量是局部的,与其他函数文件及 MATLAB工作空间相互隔离,即在一个函数文件中定义的变量不能被另一个函数文件引用。如果在若干函数中,都把某一变量定义为全局变量,那么这些函数将共用这个变量。全局变量的作用域是整个MATLAB工作空间,即全程有效,所有的函数都可以对它进行存取和修改,因此,定义全局变量是函数间传递信息的一种手段。

全局变量用global命令定义,格式如下:

global变量名

示例

函数文件wadd.m,该函数将输入的参数加权相加

function f = wadd(x , y)

global ALPHA BETA

f = ALPHA * x + BETA * y;

命令行调用

>> global ALPHA BETA
>> ALPHA = 1;
>> BETA = 2;
>> s = wadd(1,2)

s =

     5

由于在函数wadd和基本工作空间中都把 ALPHA 和 BETA两个变量定义为全局变量,所以只要在命令行窗口中改变 ALPHA 和 BETA 的值,就可改变函数中x、y的权值,而无须修改wadd.m文件。
在实际程序设计时,可在所有需要调用全局变量的函数中定义全局变量,这样就可实现数据共享。在函数文件中,全局变量的定义语句应放在变量使用之前,为了便于了解所有的全局变量,一般把全局变量的定义语句放在文件的前部。为了在工作空间中使用全局变量,也要定义全局变量。
值得指出的是,在程序设计中,全局变量固然可以带来某些方便,但却破坏了函数对变量的封装,降低了程序的可读性,因此,在结构化程序设计中,全局变量是不受欢迎的,尤其当程序较大,子程序较多时,全局变量将给程序调试和维护带来不便,故不提倡使用全局变量。如果一定要用全局变量,最好给它起一个能反映变量含义的名字,以免和其他变量混淆。

相关文章

显卡天梯图2024最新版,显卡是电脑进行图形处理的重要设备,...
初始化电脑时出现问题怎么办,可以使用win系统的安装介质,连...
todesk远程开机怎么设置,两台电脑要在同一局域网内,然后需...
油猴谷歌插件怎么安装,可以通过谷歌应用商店进行安装,需要...
虚拟内存这个名词想必很多人都听说过,我们在使用电脑的时候...