3.1 顺序结构程序

程序设计的基本步骤

step.png

程序

  • 在matlab中程序文件扩展名为**.m** ,因此程序文件又叫 M文件
  • 程序文件分两种
    • 脚本文件:是可以在命令行窗口直接执行的文件,也叫命令文件。
    • 函数文件:定义一个函数,以函数调用方式来调用,不能单独执行。

文件的建立

  • 可以在主页点击新建脚本,即可创建脚本文件,并且打开MATLAB编辑器。
  • 在命令行窗口写 edit test 即可在当前文件下创建 test 脚本文件。
%利用脚本文件求两矩阵乘积
%脚本文件f1.m
A=[1:3;4:6];
B=[1,2;3,4;5,6];
C=A*B;
%在命令行窗口运行脚本文件
>> f1

C =

    22    28
    49    64
%利用函数文件求两矩阵乘积
%函数文件f1.m
function C=f2(A,B)
C=A*B;
end
>> C=f1(A,B)

C =

    22    28
    49    64

顺序结构

  • 数据的输入 : A=input(提示信息,参数选项) ,输入时会将提示信息打印出来,后面的参数选项用于限定输入数据的类型等。
  • 数据的输出: disp(输出项)
  • 程序的暂停: pause(延迟秒数)如果延迟秒数省略,那么就会一直暂停直到用户下次动作。如果程序运行中要强行暂停可以通过 Ctrl+C 实现。

例程

  1. 通过脚本文件和函数文件求一个向量的四舍五入向量。
脚本
A=[1.2,3.4,4.7,0.5];
B=round(A);
disp(B)
函数
function B=f2(A)
B=round(A);
end
  1. 求两点之间距离以及黄金分割点坐标(其中点坐标通过复数形式输入)。
a=input('a=');
b=input('b=');
c=a+0.618*(b-a);
s=abs(b-a);
disp(s)
disp(c)

3.2 用if语句实现选择结构

单分支if语句

如果成立执行语句组,如果不成立则跳出if,语句格式如下:

if 条件(关系运算或逻辑运算)
   语句组
end

双分支if语句

如果成立执行语句组1,不成立执行语句组2,然后跳出if,语句格式如下:

if 条件(关系运算或逻辑运算)
   语句组1
else
   语句组2
end

多分支if语句

根据上述双分支的类推,依次判断条件1~n,成立则执行对应语句组,然后跳出if,不成立则往下寻找,语句格式如下:

if 条件1
   语句组1
elseif 条件2
   语句组2
elseif 条件3
   语句组3
···
elseif 条件n-1
   语句组n-1
else 语句组n
end

条件成立的判断

  • 当条件结果为标量,非零表示真,零表示假。
  • 当条件为矩阵,如果矩阵非空且不包含零元素,则条件成立,否则不成立。

3.3 用switch语句实现选择结构

switch语句的基本格式

表示在C++里面就不喜欢用switch,感觉太麻烦了。这个和多分支if有点像吧,只是他的区别在于首先给出一个表达式,在下方每一个语句组对应着一个结果表,如果结果表对应着表达式的值,就执行当前语句组,执行完之后跳出switch语句,这个和C++的有所区别。此外,如果都不满足的话,我们还可以加入一个条件otherwise,顾名思义,如果上述结果都不满足,就执行这个otherwise下对应的语句,switch的语句格式如下:

switch 表达式
  case 结果表1
     语句组1
  case 结果表2
     语句组2
···
  case 结果表n
     语句组n
  otherwise
     语句组k
end

switch的使用规则

  • case结果表为switch表达式的取值,当取值有多个时,我们可以用单元数据表示。将这多个结果用大括号{}括起来,如果表达式值满足其中一个,就执行相应语句组。

用for语句实现循环结构

常用的for语句

% for语句格式:
for 循环变量=表达式1:表达式2:表达式3
    循环体语句
end
  • 我们可以发现循环变量后面对应的是一个冒号表达式,分别是起始,步长,终止。
  • 循环执行时,先求出冒号表达式对应的行向量,然后依次遍历行向量中的每一个元素,执行循环体语句。
  • for语句针对向量每一个元素执行一次循环体,有几个元素执行几次,当冒号表达式对应的向量为空向量,则一次也不执行。
  • 当退出循环后,循环变量值为行向量组中的最后一个元素。

更一般的for语句

for 循环变量=矩阵表达式
	循环体语句
end
  • 更一般的for语句循环遍历后对应的是矩阵表达式,执行过程中将矩阵的各列元素,赋值给循环变量,这时候,循环变量为一个列向量,而不是上述常用for语句中的标量,可以发现,常用的for语句是一般格式下的特例。循环的次数为矩阵的列数。

例程

计算圆周率 $\pi$

  • 利用循环求无穷级数展开求 $\pi$

$$ 1-\frac{1}{3}+\frac{1}{5}-\frac{1}{7}+\cdots+(-1)^{n+1}\frac{1}{2n-1} =\frac{\pi}{4} $$

y=0;
g=-1;
n=input('n=');
for i=1:n
	g=-g;
	y=y+g*1/(2*i-1);
end
disp(4*y)
  • 利用矩阵求和求无穷级数展开求 $\pi$
n=input('n=');
x=1:2:(2*n-1);
y=(-1).^(2:n+1)./x;
disp(sum(y)*4)

3.5 用while语句实现循环结构

while语句

通过一个条件来判定是否执行循环体语句,当条件成立时,成立。不像是for循环先去设定循环多少次,循环变量依次取什么值,这个是根据条件限定,又叫条件循环语句

while 条件
     循环体语句
end

break语句和continue语句

  • break语句:当循环执行到break语句会跳出当前循环,进行循环外的语句。
  • continue语句:当循环执行到continue语句,会结束本次循环,进行下一次判断是否继续循环体。

循环嵌套

如果一个循环结构循环体又包括循环结构,那么就称为循环嵌套or多重循环结构。通过嵌套的层数不同来不同的命名,例如二重循环,三重循环等等。

例程

  1. 从键盘输入若干数,当输入0时结束输入,求这些数的和和他们的平均值

    msum=0;
    cnt=0;
    x=input('Enter your numbers: ');
    while x~=0
        msum=msum+x;
        cnt=cnt+1;
        x=input('Enter your numbers: ');
    end
    if cnt>0
        disp(msum);
        disp(msum/cnt);
    end
    
  2. 用筛法求 1~m 范围内的素数。

    m=input('m=');
    p=1:m;
    p(1)=0;
    for i=2:sqrt(m)
    	for j=2*i:i:m
    		p(j)=0;
    	end
    end
    n=find(p~=0);
    p(n)
    

3.6 函数文件的定义与调用

函数文件的基本结构

function 输出参数表=函数名(输入形参表)
注释说明部分
函数体语句
end
  • 当有多个形参时,形参之间用 , 逗号分隔,组成形参表。当输出形参多于一个,用方括号 [] 括起来,形成输出矩阵。

函数使用中的一些规定

  • 函数文件名通常由 函数名再加上拓展名.m 组成,函数文件名与函数名也可以不同,当两者不同时,MATLAB默认忽视函数名,调用时使用函数文件名。但一般我们将函数名和函数文件名进行统一

  • 如果函数文件中有 return 语句,就结束函数的执行,返回栈底。

函数调用

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

匿名函数

MATLAB提供了一种特殊的函数,函数句柄变量相当于这个函数的别名,通过函数句柄可以间接的调用函数,多个参数之间用逗号分隔。

  • 函数定义的基本格式如下

    函数句柄变量 = @(匿名函数输入参数) 匿名函数表达式
    
  • 函数调用的基本格式如下

    函数句柄变量(匿名函数输入实参)
    
  • 特殊的,我们可以将一个已知的内部函数或者自定义函数,赋值给一个函数句柄变量,这样我们就可以通过函数句柄变量变量来简洁的调用函数。(类似于改个名字)

例程

  • 通过函数文件和匿名函数两个形式,求出 $x^2+y^2$ 的值。

    • 函数文件
    function z=f2(x,y)
        z=x^2+y^2;
    end
    
    • 匿名函数
    f=@(x,y) x^2+y^2
    

3.7 函数的递归调用

函数的递归调用

如果一个函数在函数体内部调用自己本身称为递归调用(如果是其他函数称为嵌套调用)。递归是把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解。

  • 直接递归调用:在一个函数体内部直接调用自己本身。
  • 简介递归调用:在一个函数体内不嵌套调用其他函数,其他函数又调用自己。

例程

  • 求 $n!=1\times2\times3\cdots \times n$
function f=fact(n)
if n<=1
   f=1;
else
   f=fact(n-1)*n;
end

3.8 函数参数与变量的作用域

函数参数的可调性

可调性顾名思义,就是可以调节的。MATLAB函数在调用过程中函数传递参数的数目是可以调节的。在调用时,函数有两个预定义变量,narginnargout ,前者记录调用函数时输入实参的个数,后者记录调用函数时输出实参的个数。通过这两个变量,可以针对不同的变量个数进行不同的处理。

全局变量和局部变量

  • 函数中定义的变量是局部变量,不能被其他函数引用
  • 我们可以通过 global 变量名 来定义一个全局变量,如果不加 global ,默认是局部变量。
  • 全局变量的作用域是整个MATLAB工作空间,全程有效,所有函数都可以对他进行存取和修改。
  • 但是要注意的是,这里的全局变量使用方式和C++的有所区别,如果你要在函数中调用工作区中的全局变量,那么你需要在函数体内部定义相同的全局变量,这样才可以对其进行引用,函数体内部和工作区中的变量值是共享的。

例程

  • 求 $x1\times x+y1\times y$ ,其中x1y1 是全局工作区中全局变量的值。
%函数文件
function f=solve(x,y)
global x1 y1
f=x1*x+y1*y
%工作区
global x1 y1;
x1=1;
y1=2;
s=solve(1,2)