四、程序控制之循环结构
循环结构的基本思想是重复,即利用计算机运算速度快以及能进行逻辑控制的特点,重复执行某些语句,以满足大量的计算要求。
虽然每次循环执行的语句相同,但语句中一些变量的值是变化的,而且当循环到一定次数或满足条件后能结束循环。
MATLAB 提供了两种实现循环结构的语句:for 语句和 while 语句。
1. for 语句
- 一般情况下,对于能事先确定循环次数的循环结构,使用 for 语句是比较方便的。其语法格式如下:
for 循环变量=表达式1:表达式2:表达式3 循环体语句 end
其中,表达式1:表达式2:表达式3 是一个冒号表达式,将产生一个行向量,3 个表达式分别代表初值、步长和终值。当步长为 1 时,表达式2 可以省略。
对于 for 语句,首先计算 3 个冒号表达式,形成一个行向量,再将向量中的元素逐个赋给循环变量,每次赋值后都执行一次循环体语句,当向量的元素都被使用完时,结束 for 语句的执行,而继续执行 for 语句后面的语句。
关于 for 语句的执行,还需要注意以下几点。
(1) for 语句针对向量的每一个元素执行一次循环体,循环的次数就是向量中元素的个数,也可以针对任意向量。
(2) 可以在 for 循环体中修改循环变量的值,但当程序执行流程再次回到循环开始时,就会自动被设成向量的下一个元素。
(3) for 语句中的 3 个表达式只在循环开始时计算一次, 也就是说,向量元素一旦确定将不会再改变。如果在表达式中含有变量,即便在循环体中改变变量的值,向量的元素也不改变。
(4) 推出循环后,循环变量的值就是向量中最后的元素值。
(5) 当向量为空时,循环体一次也不执行。
例如,一个 3 位整数各位数字的立方和等于该数本身则称该数为水仙花数。输出全部水仙花数。
首先考虑如何判断水仙花数,关键的一步是先分别求 3 位整数的个位、十位、百位数字,再根据条件判断该数是否为水仙花数。然后利用 for 语句穷举全部 3 位整数。程序如下:
shu=[] %用于存放结果,先赋空值 for m=100:1:999 m1=fix(m/100); %求 m 的百位数字 m2=rem(fix(m/10),10); %求 m 的十位数字 m3=rem(m,10); %求 m 的个位数字 if m==m1*m1*m1+m2*m2*m2+m3*m3*m3 shu=[shu,m]; %存入结构 end end disp(shu)
程序运行结果如下:
shu = [] 153 370 371 407
整体程序如下:
y=0; n=100; for i=1:1:n y=y+1/(i*i); end y
程序运行结果如下:
y = 1.6350
a=0; b=3*pi; n=1000; h=(b-a)/n; x=a; s=0; f0=exp(-0.5*x)*sin(x+pi/6); for i=1:n x=x+h; %下一个 x 坐标 f1=exp(-0.5*x)*sin(x+pi/6); %求新的函数值 s=s+(f0+f1)*h/2; %求小梯形面积并累加 f0=f1; %更新函数值 end s
运行结果如下:
s = 0.9008
上述程序来源于传统的编程思想。也可以利用向量运算,从而使得程序更加简洁,更加具有 MATLAB 的特点。程序如下:
a=0; b=3*pi; n=1000; h=(b-a)/n; x=a:h:b; %生成自变量向量 x f=exp(-0.5*x).*sin(x+pi/6); %求函数值向量 f for i=1:n s(i)=(f(i)+f(i+1))*h/2; %求各个小梯形面积,组成面积向量 f end s=sum(s) %求面积向量 s 元素之和
程序中 x、f、 s 均为向量,f 的元素为各个 x 点的函数值,s 的元素分别为 n 个梯形的面积,s 各元素之和即定积分近似值。事实上,MATLAB 提供了有关数值积分的标准函数,实际应用中可直接调用这些函数求数值积分。
2. while 语句
- while 语句就是通过判断循环条件是否满足来决定是否继续循环的一种循环控制语句,也称为条件循环语句。它的特点是先判断循环条件,条件满足时执行循环。
- while 语句的一般格式如下:
while 条件 循环体语句 end
其执行过程为,若条件成立,则执行循环体语句,执行后再判断条件是否成立,如果不成立则跳出循环。
- 例如,从键盘中输入若干个数,当输入 0 时结束输入,求这些数的平均值和它们之和。
- 这是一个典型的条件循环问题,用 while 语句实现。程序如下:
sum=0; n=0; x=input('Enter a number(end in 0):'); while x~=0 sum=sum+x; n=n+1; x=input('Enter a number(end in 0):'); end if n>0 sum mean=sum/n end
运行结果如下:
Enter a number(end in 0):67 Enter a number(end in 0):89 Enter a number(end in 0):93 Enter a number(end in 0):70 Enter a number(end in 0):0 sum = 319 mean = 79.7500
设 X XX 是给定的矩阵,E EE 是矩阵指数函数值,F FF 是展开式的项,n nn 是项数,循环一直进行到 F FF 很小,以至于 F FF 值加在 E EE 上对 E EE 的值影响不大时为止。
为了判断 F FF 是否很小,可利用求矩阵范数的函数 norm(F,1) 来计算。所以当 norm(F,1)=0 时,认为 F FF 很小,应退出循环的执行。程序如下:
X=input('Enter X:'); E=zeros(size(X)); %生成与 X 同样大小的零矩阵 F=eye(size(X)); %生成与 X 同样大小的单位矩阵 n=1; while norm(F,1)>0 E=E+F; %实现累加 F=F*X/n; %求累加项 n=n+1; end E expm(X) %调用 MATLAB 矩阵指数函数求矩阵指数
运行结果如下:
Enter X:[0.5,2,0;1,-1,-0.5;0.9,1,0.75] E = 2.6126 2.0579 -0.6376 0.7420 0.7504 -0.5942 2.5678 2.3359 1.5549 ans = 2.6126 2.0579 -0.6376 0.7420 0.7504 -0.5942 2.5678 2.3359 1.5549
- 运行结果表明,程序运行结果与 MATLAB 矩阵指数函数 expm(X) 的结果一致。
3. break 语句和 continue 语句
与循环结构相关的语句还有 break 语句和 continue 语句,它们一般与 if 语句配合使用。
break 语句用于终止循环的执行。当在循环体内执行到该语句时,程序将跳出循环,继续执行循环语句的下一语句。
continue 语句控制跳过循环体中的某些语句。当在循环体内执行到该语句时,程序将跳过循环体中所有剩下的语句,继续下一次循环。
例如,求 [ 100 , 200 ] [100, 200][100,200] 之间第一个能被 21 整除的整数。
程序如下:
for n=100:200 if(rem(n,21)~=0) continue end n break end
运行结果如下:
n = 105
当 n 不能被 21 整除时,执行 continue 语句直接进行下一次循环。一旦发现 n 能被 21 整除,执行 break 语句跳出循环体。
4. 循环的嵌套
如果一个循环结构的循环体又包括一个 循环结构,就称为循环的嵌套,或称为多重循环结构。
实现多重循环结构仍用前面介绍的循环语句。因为任一循环语句的循环体部分都可以包含另一个循环语句,这种循环语句的嵌套为实现多重循环提供了方便。
多重循环的嵌套层数可以是任意的,可以按照嵌套层数,分别叫做二重循环、三重循环等。处于内部的循环叫做内循环,处于外部的循环叫做外循环。
例如,若一个数等于它的各个真因子之和,则称该数为完数,如 6 = 1 + 2 + 3 6=1+2+36=1+2+3,所以 6 是完数。求 [ 1 , 500 ] [1, 500][1,500] 之间的全部完数。
对于此题,我们先考虑单个数是否为完数的问题,根据定义要用到一个循环结构。再求指定范围内的全部完数,在前一循环结构基础上,再嵌套一个循环结构。程序如下:
for m=1:500 s=0; for k=1:m/2 if rem(m,k)==0 s=s+k; end end if m==s disp(m); end end
运行结果如下:
6 28 496
例如,用筛选法求出某自然数范围内的全部素数。
素数是大于 1,且除了 1 和它本身以外,不能被其他任何整数所整除的整数。
用筛选法求素数的基本思想是,要找出 2~m 之间的全部素数,首先在 2~m 中划去 2 的倍数(不包括 2),然后划去 3 的倍数(不包括 3),由于 4 已被划去,再找 5 的倍数(不包括 5),…,直到再划去不超过 m \sqrt{m}
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)