matlab从无到有系列(八):M文件及函数的编写

目前持续更新的专栏:

大家好,我是左手の明天

  最近更新:2022 年 3 月31 日,左手の明天的第 213 篇原创博客

往期必看

matlab从无到有系列(二):矩阵运算基础

matlab从无到有系列(三):数值计算基础

matlab从无到有系列(四):符号数学基础

matlab从无到有系列(五):基本图形图像处理功能

matlab从无到有系列(六):高级图形处理功能(多窗口绘图以及花瓶绘制)

matlab从无到有系列(七):GUI程序设计

目录

往期必看

M-script 文件的编写

MATLAB控制流

for循环结构⭐️

while 循环结构⭐️

if-else-end 结构⭐️

分支语句switch-case-otherwise⭐️

try-catch 结构⭐️

交互式输入

用户输入提示命令input⭐️

等待用户反应命令pause⭐️

中断命令break⭐️

等待键盘输入 keyboard⭐️

显示文字或数组 disp⭐️

MATLAB 函数的编写

函数的基本结构⭐️

函数编写注意事项⭐️

程序设计的优化

以矩阵作为操作主体⭐️

数据的预定义⭐️

程序调试

M文件错误的种类⭐️

处理异常的常用方法⭐️

常见的错误提示及其解决方法⭐️

️1.Undefined function or variable “U”

️2.Unexpected MATLAB expression.

️3.Subscript indices must either be real positive integers or logicals

️4.Matrix dimensions must agree

️5.Function definitions are not permitted at the prompt or in scripts

️6.One or more output arguments not assigned during call to ‘…’

️7.??? Index exceeds matrix dimensions.

️8.In an assignment   A(I) = B, the number of elements in B and I must be the same

调试过程⭐️

命令文件与函数文件的区别⭐️

M文件其实是一个像命令集一样的ASCII(纯文本) 码文件。正是M文件的这个特点造就了MATLAB 强大的可开发性和可扩展性。

M文件的两种形式:

  • 命令式(M_Script)
  • 函数式(Function)

命令式文件就是命令行的简单叠加,MATLAB会 自动按顺序执行文件中的命令。

函数式文件主要用以解决参数传递和函数调用的 问题。

M-script 文件的编写

一般过程:

  • 新建M文件
  • 编写指令
  • 调试运行

用户在编制此类文件时,只需把所要执行的命令 按行编辑到指定的文件中,程序运行时,MATLAB按行执行这些指令。

规则:

  • 建立好的书写风格,保持程序的可读性;
  • m为文件的扩展名,在低版本的MATLAB中 还要注意文件名不超过8位,文件名和变量的命 名规则相同;
  • 以符号%引导的行是注释行、不可执行, 可供heIp命令查询;
  • 不需要用end语句作为M文件的结束标志;
  • 在运行此函数之前,需要把它所在目录加到MATLAB的搜索路径上去或将文件所在目录设为当前日录。新版本会提示,老版本则出错。
  • 运行一个程序,有多种方式。

MATLAB控制流

for循环结构⭐️

for循环语句的一 般格式如下:

for  v = expression (表达式)

     commands     (执行语勾)

end

while 循环结构⭐️

while循环语句的一 般格式如下:

While expression(条件式)
             
      statements

End

例如1:用循环求解《matlab从无到有系列(八):M文件及函数的编写》

>>s=0;
for i=1:100
      s=s+i;
end
>>s=0;i=1;
while i<=100
      s=s+i;
      i=i+1;
end

《matlab从无到有系列(八):M文件及函数的编写》不用循环的方法:s=sum(1:100)

例如2:用循环求解求最小的 m,《matlab从无到有系列(八):M文件及函数的编写》

在这种情况下,最好用while.

s=0;i=0;
while s<=10000
           i=i+1;
           s=s+i;
end
[s, i]

if-else-end 结构⭐️

循环语句的一 般格式如下:

if logical expression
   statements
end

或者

if logical expression
   statements 1
else
   statements 2
end

或者

if logical expression 1
   statements 1
elseif logical expression 2
   statements 2
else 
   statements 3
end

例如:编写M文件求

《matlab从无到有系列(八):M文件及函数的编写》

 

>> A=[];
for  k=1:5
    for  j=1:5
        if  k==j
            A(k,k)=5;
        elseif  abs(k-j)==1
            A(k,j)=1;
        else 
            A(k,j)=0;
       end
   end
end

分支语句switch-case-otherwise⭐️

循环语句的一 般格式如下:

Switch expression
    case case_1
            (commands 1)
    case case_2
            (commands 2)
     ……
    case case_k
            (commands k)
    otherwise,
            (commands)
end     

注意 :在执行过程中,只执行一个case后面的命令并跳出开关, 程序在end后继续执行。

例如:检测掷一次骰子所得的点数是单数还是双数

switch result
     case{1,3,5}
              disp('odd numbers')
     case{2,4,6}
              disp('even numbers')
     otherwise
              disp ('mistake!')
end

分支语句和C语言的区别:

  • 当开关表达式的值等于某表达式,执行该语句 后结束该结构,不用 break
  • otherwise 语句,不是 default
  • 程序的执行结果和各个case顺序无关
  • case 语句中条件不能重复,否则列在后面的条件将不能执行

try-catch 结构⭐️

循环语句的一 般格式如下:

try 
    (commands1)-----该命令总被执行,若正确,则跳出此结构

catch
    (commands2)-----仅当组命令1出现执行错误,才执行该命令

end

说明break语句和return语句的用法:

break语句用于终止for循环和while循环的执行。如果遇到break语句,则退出循环体,继续执行循环体外的下一行语句。在嵌套循环中,break只存在于最内层的循环中。

return语句用于终止当前的命令序列,并返回到调用的函数或键盘,也用于终止keyboad方式,在MATLAB中,被调用的函数运行结束后会自动返回调用函数,使用return语句时将return插入被调用函数的某一位置,根据某种条件迫使被调用函数提前结束并返回调用函数。

典例总结:

1、有一组学生的考试成绩(见表),根据规定,成绩在100分时为满分,成绩在90~99之间时为优秀,成绩在80~89分之间时为良好,成绩在60~79分之间为及格,成绩在60分以下时为不及格,编制一个根据成绩划分等级的程序。

学生姓名

成  绩

72

83

56

94

100

88

96

68

54

65

   Name=['王','张','刘','李','陈','杨','于','黄','郭','赵'];
   Marks=[72,83,56,94,100,88,96,68,54,65];
   % 划分区域:满分(100),优秀(90-99),良好(80-89),及格(60-79),不及格(<60)。
   n=length(Marks);
   for i=1:n
      a{i}=89+i;
      b{i}=79+i;
      c{i}=69+i;
      d{i}=59+i;
   end;
   c=[d,c];
   % 根据学生的分数,求出相应的等级。
   for i=1:n
      switch Marks(i)
      case 100 					%得分为100时
         Rank(i,:)=' 满分';
      case a         			    %得分在90~99之间
         Rank(i,:)=' 优秀';
      case b    					%得分在80~89之间
         Rank(i,:)=' 良好';
      case c     				    %得分在60~79之间
         Rank(i,:)=' 及格';
      otherwise  				    %得分低于60。
         Rank(i,:)='不及格';
      end
   end
   % 将学生姓名,得分,级等信息打印出来。
   disp(' ')
   disp(['学生姓名  ','  得分  ','   等级']);
   disp('--------------------------')
   for i=1:10;
     disp(['   ',Name(i),'	   ',num2str(Marks(i)),'	  ',Rank(i,:)]);
   end  
    学生姓名    得分     等级
    -----------------------------------------
       王	    72 	     及格
       张	    83	     良好
       刘	    56	    不及格
       李	    94	     优秀
       陈	    100	     满分
       杨	    88       良好
       于	    96 	     优秀
       黄	    68 	     及格
       郭	    54	    不及格
       赵	    65	     及格

2、编写一段程序,能够把输入的摄氏温度转化成华氏温度,也能把华氏温度转换成摄氏温度。

   k=input('选择转换方式(1--摄氏转换为华氏,2--华氏转换为摄氏):');
   if k~=1 & k~=2
      disp('请指定转换方式')
      break
   end
   tin=input('输入待转变的温度(允许输入数组):');
   if k==1
      tout=tin*9/5+32;        % 摄氏转换为华氏
      k1=2;
   elseif k==2
      tout=(tin-32)*5/9;       % 华氏转换为摄氏
      k1=1;
   end
   str=[' C';' F'];
   disp(['转换前的温度', '    ', '转换后的温度'])
   disp(['   ',num2str(tin),str(k,:), '          ', num2str(tout),str(k1,:)])

交互式输入

用户输入提示命令input⭐️

input  命令用来接收用户从键盘输入数据、字符串或表达式,并接收输入值。其常用格式:

 R=input ('How many apples')

运行此命今后,将给出文字提示,并等待键盘输入。

R=input('what is your name ?','s')

运行此命令后,MATLAB将等待输入,并把输入 当做字符串,赋给变量R。

等待用户反应命令pause⭐️

此命令用于使程序暂时终止运行,等待用户按任 意键后继续运行。

此函数的调用形式如下:

Pause         暂停程序等待回应;
Pause(n)      程序运行中等待n秒后继续运行;
Pause on      显示其后的 Pause命令,并且执行pause命令;
Pause off     显示其后的pause命令,但不执行该命令。

中断命令break⭐️

break语句常常用在循环语句中。通过使用break语句,可不必等待循环的自然结束,而根据循环只设的条件来判断是否跳出循环。

等待键盘输入 keyboard⭐️

使程序进入暂时等待状态,但并没退出执行,可以修改参数,和运行其他指令等。

显示文字或数组 disp⭐️

如何定义全局变量?

用关键字global可以把一个变量定义为全局变量,在M文件中定义全局变量时,如果在当前工作空间已经存在了相同的变量,系统将会给出警告,说明由于将该变量定义为全局变量,可能会使变量的值发生改变,为避免发生这种情况,应该在使用变量前先将其定义为全局变量。

keyboard命令的作用是什么?当在函数中使用keyboard命令时,是否可以在工作空间浏览器中观察和修改函数中的局部变量?退出keyboard状态的命令是什么?编一个函数文件,在其中设置keyboard,观察变量情况。

当运行中的程序遇到keyboard命令时会暂时停止运行,将控制权交给键盘,这时命令窗口的提示符变为K>>,可以在命令窗口或工作空间浏览器中观察和修改变量内容,如果keyboard命令设置在函数中,则可以观察和修改函数中的局部变量,检查或修改完成后,键入return命令,退出keyboard状态,控制权交还给系统,程序将继续运行。

MATLAB 函数的编写

M-script 适合于小规模

函数的基本结构⭐️

函数定义行(关键字function)

function[out1,out2,..]=funcname(in1,in2,..)

    注释段
   
    输入返回变量的检测 
    
    函数体语句

输入和输出(返回)的参数个数分别由nargin和nargout 两个MATLAB保留的变量来给出。

注意:若一个function作为一个M文件存储,切记其存储文件名应和函数名一样!

第一行帮助行

以(%)开头,作为lookfor指令搜索的行

函数体说明及有关注解

以(%)开头,用以说明函数的作用及有关内容

函数体语句

函数体内使用的除返回和输入变量这些在function语句中直接引用的变量以外的所有变量都是局部变量,即在该函数返回之后,这些变量会自动在MATLAB的工作空间中清除掉。如果希望这些中间变量成为在整个程序中都起作用的变量,则可以将它们设置为全局变量。

例如1: 《matlab从无到有系列(八):M文件及函数的编写》若最大值不为 10000,需修改程序对 m 和 10000 值的设置,不适合于M-script.

1、定义 findsum.m文件

function [s,m]=findsum(k)
s=0;
m=0;
while(s<=k)
    m=m+1;
    s=s+m;
end

2、在command window中调用:

 [s,m]=findsum(10000)

例如2: 函数的递归调用:阶乘 n!=n(n-1)!

1、定义fact.m文件

function k=fact(n)
if n>1
    k=n*my_fact(n-1);
elseif n==0|n==1
    k=1;
else
    error(' input a wrong parameter!')
end

2、在command window中调用:

num=fact(11)

MATLAB函数为:prod(1:1000)

使用tictoc函数, 测试一下该函数的运行效率,显式程序运行的时间:

tic;
num=fact(500);
toc

函数编写注意事项⭐️

  • 函数的函数名与存储名要一致。
  • 函数名首字符必须为字母。其后可为字母数字下划线等。长度小于31个字符。
  • 不推荐在同一文件中,写多个函数。
  • 建议每个函数单独写成一个文件,由主程序调用,主程序不要写成函数形式。

程序设计的优化

虽然MATLAB程序语言高度集成,但由于MATLAB属于解释型语言,在执行效率方面还是存在一些不足,因此,如何优化程序,特别是在大型的运算与仿真中,是一个很重要的话题。

以矩阵作为操作主体⭐️

  • 循环运算是MATLAB语言的最大弱点。
  • 在程序设计时应当尽可能避免循环运算,尽量用向量化的运算来代替循环操作多重循环, 将执行次数少循环的放在外环。
  • 在MATLAB编程过程中应当强调对矩阵本身 整体的运算,避免对矩阵元素的操作。
  • 绝大多数的循环运算是可以转换为向量运算; 尽量使用内部函数

举些简单的例子,说明c语言和matlab的区别:

例:找出数组A=[2,5,7,8,4,9,12]中,所有大于6 的元素及其下标

x=find(A>6);   % 找出下标
B=A(x);        % 找出所有大于6的元素

数据的预定义⭐️

对存储的合理操作及管理也会提高程序运行的效率。MATLAB语言提供了一系列的函数用以管理内存。

函数名

说明

clear

从内存中清除所有变量及函数

pack

重新分配内存

quit

退出MATLAB环境,释放所有内存

save

把指定变量存储至磁盘

load

从磁盘中调出指定变量

程序调试

M文件错误的种类⭐️

M文件一般有语法错误和执行错误两种:

  • 语法错误发生在M文件程序代码的解释过程中, 一般是由函数参数输入类型有误或矩阵运算阶数 不符等引起的。
  • 执行错误的发生是由于在程序运行过程中,出现溢出或死循环等引起的,这些错误都与程序本身有关,并且较难发现解决。

处理异常的常用方法⭐️

  • 避免出现NaN、Inf或空矩阵等;
  • 在可能出现上述异常数值的地方提供控制语句来识别;
  • 识别函数有isnan、isinf、isempty1sn等。

常见的错误提示及其解决方法⭐️

1.Undefined function or variable “U”

中文解释:函数或变量 U 没有定义

出错原因:函数或变量 U 没有定义

解决办法:仔细检查错误所指向的位置,寻找没有定义的函数或者变量,加以定义。

2.Unexpected MATLAB expression.

中文解释:不规范的matlab表达式

出错原因:少了运算符号,或者括号等情况

解决办法:仔细检查错误所指向的位置,检查是否少了乘号,或者逗号、分号、括号等。

3.Subscript indices must either be real positive integers or logicals

中文解释:下标索引必须是正整数类型或者逻辑类型

出错原因:在访问矩阵(包括向量、二维矩阵、多维数组,下同)的过程中,下标索引要么从 0 开始,要么出现了负数。

注:matlab 的语法规定矩阵的索引从 1 开始,这与 C 等编程语言的习惯不一样。

解决办法:自己调试一下程序,把下标为 0 或者负数的地方修正。

4.Matrix dimensions must agree

中文解释:矩阵的维数必须一致

出错原因:这是由于运算符(= + – / * 等)两边的运算对象维数不匹配造成的,典型的出错原因是错用了矩阵运算符。matlab 通过“.”来区分矩阵运算和元素运算。

解决办法:自己调试一下程序,保证运算符两边的运算对象维数一致。

5.Function definitions are not permitted at the prompt or in scripts

中文解释:不能在命令窗口或者脚本文件中定义函数

出错原因:一旦在命令窗口写 function c = myPlus(a,b),此错误就会出现,因为函数只能定义在 m 文件中。

          关于脚本文件和 m 文件的区别可查阅 matlab 基础书。

简言之:

    1) 如果你写成 function 的形式,那么必须写在 m 文件中,且以 function 开头(即 function 语句前不能包含其他语句,所有语句必须放在 function 中,当然,function 的定义可以有多个,各 function 之间是并列关系,不能嵌套);

    2) 如果你写成脚本的形式,则既可以写在命令窗口中,也可以写在 m 文件中,但两者均不能包含 function 语句(即不能进行函数的定义)

解决办法:新建一个 m 文件,然后再进行函数的定义

6.One or more output arguments not assigned during call to ‘…’

中文解释:在调用…函数过程中,一个或多个输出变量没有被赋值

出错原因:函数如果带有输出变量,则每个输出在返回的时候都必须被赋值。容易出现这个错误的两个地方是:

  • 在部分条件判断语句(如 if )中没有考虑到输出变量的返回值。
  • 在循环迭代过程中部分变量的维数发生了变化。

解决办法:在条件判断或者执行循环之前对所使用的变量赋初值。

7.??? Index exceeds matrix dimensions.

中文解释:索引超出矩阵的范围

出错原因:在引用矩阵元素的时候,索引值超出矩阵应有的范围

解决办法:检查所定义数组的维数,和引用的范围。

8.In an assignment   A(I) = B, the number of elements in B and I must be the same

中文解释:在赋值语句 A(I) = B 中,B 和 I 的元素个数必须相同

出错原因:矩阵维数不匹配,如矩阵乘法要求第一个矩阵的列数和第二个矩阵的行数相等。

解决办法:自己设置断点调试一下,看看 I 和 B 的维数、大小是否相同,不同的话就要修改成两者一致

还有一些隐性的错误,matlab不会报错也不会警告,但会造成结果的错误

比如由于 C 或 C++ 留下的编程习惯,我们常常会以i,j作为循环变量,但同时matlab中i,j又是复数单位,这样就会由于使用不慎,i,j被matlab认定为复数而造成结果错误。

如以下例子

for i = 1:3
    A(i) = 2i+1;
end

结果为:

A =

   1.0000 + 2.0000i   1.0000 + 2.0000i   1.0000 + 2.0000i

明显不是我们所要的结果,问题出在少了个乘号,但matlab并不会报错,而认为是复数单位。

正确情况是改为:

A(i) = 2*i+1;

A =

     3     5     7

但针对此情况更好的方法是不用i,j作为循环变量,比如用ii和jj作为循环变量。这样的话如果出现情况:

A(ii) = 2ii+1;

则matlab会报错,错误类型见上2。

调试过程⭐️

  • 在M文件中设置断点
  • 巧用“;”,运行到适当的地方输出信息,帮助分析
  • 单步运行,通过输出信息和workspace的变量 来查看程序是否运行正常
  • 改变输入信息,查看出错症结
  • 使用profile,tic,toc ,cputime函数查看文件运行耗时及各部分性能,以便化简

命令文件与函数文件的区别⭐️

(1)命令文件是一系列命令的组合,函数文件的第一行必须用function说明;

(2)命令文件没有输入参数,也不用返回参数,函数文件可以接受输入参数,也可以返回参数;

(3)命令文件处理的变量为工作空间变量,函数文件处理的变量为函数内部的局部变量,也可以处理全局变量。

    原文作者:左手の明天
    原文地址: https://blog.csdn.net/ywsydwsbn/article/details/123865614
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞