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


    MATLAB程序设计与应用

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

    4.3 函数文件

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

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

    4.3.1 函数文件的基本结构

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

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

    其中,以 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;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    调用函数

    >> [s,p] = fcircle(10)
    
    s =
    
      314.1593
    
    
    p =
    
       62.8319
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

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

    >> help fcircle
      r 圆半径
      s 圆面积
      p 圆周长
    
    • 1
    • 2
    • 3
    • 4

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

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

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

      [输出实参表] = 函数名(输入实参表)
      
      • 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)])
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13

      在这里插入图片描述

      运行脚本

      >> main1
      Please input x = 45
      Please input y = 45
      rho = 63.6396
      the = 0.7854
      
      • 1
      • 2
      • 3
      • 4
      • 5

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

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

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

      >> 
      >> [rho , the] = cart2pol(45 ,45)
      
      rho =
      
          0.7854
      
      
      the =
      
         63.6396
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
    2. 函数的递归调用

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

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

      在这里插入图片描述

      函数文件factor.m

      function f = factor(n)
      if n <= 1
          f = 1;
      
      else
          f = factor(n - 1) * n; % 递归调用
      end
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7

      脚本文件

      % 求 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)])
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10

      运行脚本文件

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

      示例——任意排列问题。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
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16

      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
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20

      调用函数

      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
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
    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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    脚本文件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)])
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    运行脚本

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

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

    4.3.4 全局变量与局部变量

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

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

    global变量名
    
    • 1

    示例

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

    function f = wadd(x , y)
    
    global ALPHA BETA
    
    f = ALPHA * x + BETA * y;
    
    • 1
    • 2
    • 3
    • 4
    • 5

    命令行调用

    >> global ALPHA BETA
    >> ALPHA = 1;
    >> BETA = 2;
    >> s = wadd(1,2)
    
    s =
    
         5
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

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

  • 相关阅读:
    Leetcode148. 排序链表
    第二部分—C语言提高篇_12. 动/精态库的封装和使用
    esp32系列(5):esp32 蓝牙架构学习
    LeetCode_单调栈_中等_907.子数组的最小值之和
    OpenGL ES EGL 名词解释
    【Linux】基础IO_1
    某音网页端 X-Bogus 参数
    Android-Handler源码解析-Message
    Mac系统PR2022安装BeatEdit插件遇到各种问题解决
    45、tomcat+课后实验
  • 原文地址:https://blog.csdn.net/weixin_44226181/article/details/126497194