第7章决策:控制流 计算机编程语言和可编程计算器提供许多功能,它允许你根据决策结构控制命令执行流 程。如果你以前已经使用过这些功能,对此就会很熟悉。相反,如果不熟悉控制流,本章材 料初看起来或许复杂些。如果这样,就慢慢来 控制流极其重要,因为它使过去的计算影响将来的运算。MA∏LAB提供三种决策或控 制流结构。它们是:For循环, While循环和 If-Else-En结构。由于这些结构经常包含大量 的 MATLAB命令,故经常出现在M文件中,而不是直接加在 MATLAB提示符下 7.1For循环 For循环允许一组命令以固定的和预定的次数重复。For循环的一般形式是 rray 在for和end语句之间的{ commands按数组中的每一列执行一次。在每一次迭代中,x被指 定为数组的下一列,即在第n次循环中,x=aray(:,n)。例如 for n=1: 10 n-sin(n Columns 1 through 7 0.30900.58780.80900.9511100000.95110.8090 Columns 8 through 10 0.5878 0.3090 0.0000 换句话,第一语句是说:对n等于1到10,求所有语句的值,直至下一个end语句。 第一次通过For循环n=1,第二次,n=2,如此继续,直至r=10。在m=10以后,For循环结 束,然后求end语句后面的任何命令值,在这种情况下显示所计算的x的元素 For循环的其它重要方面是 L.For循环不能用For循环内重新赋值循环变量n来终止。 for n=1: 10
第 7 章 决策:控 制 流 计算机编程语言和可编程计算器提供许多功能,它允许你根据决策结构控制命令执行流 程。如果你以前已经使用过这些功能,对此就会很熟悉。相反,如果不熟悉控制流,本章材 料初看起来或许复杂些。如果这样,就慢慢来。 控制流极其重要,因为它使过去的计算影响将来的运算。MATLAB 提供三种决策或控 制流结构。它们是:For 循环,While 循环和 If-Else-End 结构。由于这些结构经常包含大量 的 MATLAB 命令,故经常出现在 M 文件中,而不是直接加在 MATLAB 提示符下。 7.1 For 循环 For 循环允许一组命令以固定的和预定的次数重复。For 循环的一般形式是: for x = array {commands} end 在 for 和 end 语句之间的{commands}按数组中的每一列执行一次。在每一次迭代中,x 被指 定为数组的下一列,即在第 n 次循环中,x=array(:, n)。例如, » for n=1:10 x(n)=sin(n*pi/10); end » x x = Columns 1 through 7 0.3090 0.5878 0.8090 0.9511 1.0000 0.9511 0.8090 Columns 8 through 10 0.5878 0.3090 0.0000 换句话,第一语句是说:对 n 等于 1 到 10,求所有语句的值,直至下一个 end 语句。 第一次通过 For 循环 n=1,第二次,n=2,如此继续,直至 n=10。在 n=10 以后,For 循环结 束,然后求 end 语句后面的任何命令值,在这种情况下显示所计算的 x 的元素。 For 循环的其它重要方面是: 1. For 循环不能用 For 循环内重新赋值循环变量 n 来终止。 » for n=1:10
x(n)=sin(n*pi/l Columns 1 through 7 0.30900.58780.80900.9511100000.95110.8090 C columns 2.语句1:10是一个标准的 MATLAB数组创建语句。在For循环内接受任何有效的 MATLAB数组。 a=[39456,716-15 X=n(1)-n(2) 3.For循环可按需要嵌套。 1:5 A(n, m) disp(n)
x(n)=sin(n*pi/10); n=10; end » x x = Columns 1 through 7 0.3090 0.5878 0.8090 0.9511 1.0000 0.9511 0.8090 Columns 8 through 10 0.5878 0.3090 0.0000 2. 语句 1 :10 是一个标准的 MATLAB 数组创建语句。在 For 循环内接受任何有效的 MATLAB 数组。 » data=[3 9 45 6; 7 16 -1 5] data = 3 9 45 6 7 16 -1 5 for n=data x=n(1)-n(2) end x = -4 x = -7 x = 46 x = 1 3. For 循环可按需要嵌套。 for n=1:5 for m=5:-1:1 A(n,m)=n^2+m^2; end disp(n) end 1 2
A= 25 26 8132029 1013182534 2629344150 4.当有一个等效的数组方法来解给定的问题时,应避免用For循环。例如,上面的第 一个例子可被重写为 n=1:10 >)xsin(n*pi/10) Columns I through 7 0.30900.58780.80900.95111.00000.95110.8090 Columns 8 through 10 0.58780.30900.0000 两种方法得出同样的结果,而后者执行更快,更直观,要求较少的输入 5.为了得到最大的速度,在For循环(Whie循环被执行之前,应预先分配数组。例如 前面所考虑的第一种情况,在For循环内每执行一次命令,变量x的大小增加1。迫使 MATLAB每通过一次循环要花费时间对x分配更多的内存。为了消去这个步骤,For循环 的例子应重写为 D)zeros( 1, 10); preallocated memory forx n(n*pi/10) 现在,只有x(n)的值需要改变 7.2 While循环 与For循环以固定次数求一组命令的值相反, While循环以不定的次数求一组语句的值 While循环的一般形式是:
3 4 5 » A A = 2 5 10 17 26 5 8 13 20 29 10 13 18 25 34 17 20 25 32 41 26 29 34 41 50 4. 当有一个等效的数组方法来解给定的问题时,应避免用 For 循环。例如,上面的第 一个例子可被重写为 » n=1:10; » x=sin(n*pi/10) x = Columns 1 through 7 0.3090 0.5878 0.8090 0.9511 1.0000 0.9511 0.8090 Columns 8 through 10 0.5878 0.3090 0.0000 两种方法得出同样的结果,而后者执行更快,更直观,要求较少的输入。 5. 为了得到最大的速度,在 For 循环(While 循环)被执行之前,应预先分配数组。例如, 前面所考虑的第一种情况,在 For 循环内每执行一次命令,变量 x 的大小增加 1。迫使 MATLAB 每通过一次循环要花费时间对 x 分配更多的内存。为了消去这个步骤,For 循环 的例子应重写为 »x=zeros(1,10); % preallocated memory for x » for n=1:10 x(n)=sin(n*pi/10); end 现在,只有 x(n)的值需要改变。 7.2 While 循环 与For 循环以固定次数求一组命令的值相反,While 循环以不定的次数求一组语句的值。 While 循环的一般形式是:
(commands) 只要在表达式里的所有元素为真,就执行whle和end语句之间的{ commands。通常,表 达式的求值给出一个标量值,但数组值也同样有效。在数组情况下,所得到数组的所有元素 必须都为真。考虑下列例子 >)while(1+EPS)l ) num num三 EPS=2*EPS EPS 2.2204e-016 这个例子表明了计算特殊 MATLAB值eps的一种方法,它是一个可加到1,而使结果 以有限精度大于1的最小数值。这里我们用大写EPS,因此 MATLAB的eps的值不会被覆 盖掉。在这个例子里,EPS以1开始。只要(1+EPS)>1为真(非零),就一直求 While循环内 的命令值。由于EPS不断地被2除,EPS逐渐变小以致于EPS+1不大于1。(记住,发生这 种情况是因为计算机使用固定数的数值来表示数。 MATLAB用16位,因此,我们只能期望 EPS接近10-16。)在这一点上,(1+EPS)>1是假(零),于是 While循环结束。最后,EPS 与2相乘,因为最后除2使EPS太小。 7.3 IF-ELSE-END结构 很多情况下,命令的序列必须根据关系的检验有条件地执行。在编程语言里,这种逻辑 由某种If-Else-End结构来提供。最简单的 If-Else-End结构是: 如果在表达式中的所有元素为真半非零),那么就执行和end语言之间的{ commands 在表达式包含有几个逻辑子表达式时,即使前一个子表达式决定了表达式的最后逻辑状态
while expression {commands} end 只要在表达式里的所有元素为真,就执行 while 和 end 语句之间的{commands}。通常,表 达式的求值给出一个标量值,但数组值也同样有效。在数组情况下,所得到数组的所有元素 必须都为真。考虑下列例子: » num=0;EPS=1; » while (1+EPS)>1 EPS=EPS/2; num=num+1; end » num num = 53 » EPS=2*EPS EPS = 2.2204e-016 这个例子表明了计算特殊 MATLAB 值 eps 的一种方法,它是一个可加到 1,而使结果 以有限精度大于 1 的最小数值。这里我们用大写 EPS,因此 MATLAB 的 eps 的值不会被覆 盖掉。在这个例子里,EPS 以 1 开始。只要(1+EPS)>1 为真(非零),就一直求 While 循环内 的命令值。由于 EPS 不断地被 2 除,EPS 逐渐变小以致于 EPS+1 不大于 1。(记住,发生这 种情况是因为计算机使用固定数的数值来表示数。MATLAB 用 16 位,因此,我们只能期望 EPS 接近 10-16。) 在这一点上,(1+EPS)>1 是假(零),于是 While 循环结束。最后,EPS 与 2 相乘,因为最后除 2 使 EPS 太小。 7.3 IF-ELSE-END 结构 很多情况下,命令的序列必须根据关系的检验有条件地执行。在编程语言里,这种逻辑 由某种 If-Else-End 结构来提供。最简单的 If-Else-End 结构是: if expression {commands} end 如果在表达式中的所有元素为真(非零),那么就执行 if 和 end 语言之间的{commands}。 在表达式包含有几个逻辑子表达式时,即使前一个子表达式决定了表达式的最后逻辑状态
仍要计算所有的子表达式。例如, >)apples=10 number of apples >)cost=apples"25 >)if apples>5 give 20% discount for larger purchases cost=(1-20/100) end >> cost cost 200 假如有两个选择, If-Else- End结构是: if expression commands evaluated if True else commands evaluated if False 在这里,如果表达式为真,则执行第一组命令;如果表达式是假,则执行第二组命令 当有三个或更多的选择时,IfEe-End结构采用形式 if expression commands evaluated if expressionI is True elseif commands evaluated if expression2 is True elseif expression mands evaluated if expression is True commands evaluated if expression4 is True commands evaluated if no other expression is True
仍要计算所有的子表达式。例如, » apples=10; % number of apples » cost=apples*25 % cost of apples cost = 250 » if apples>5 % give 20% discount for larger purchases cost=(1-20/100)*cost; end » cost cost = 200 假如有两个选择,If-Else-End 结构是: if expression commands evaluated if True else commands evaluated if False end 在这里,如果表达式为真,则执行第一组命令;如果表达式是假,则执行第二组命令。 当有三个或更多的选择时,If-Else-End 结构采用形式 if expression1 commands evaluated if expression1 is True elseif expression2 commands evaluated if expression2 is True elseif expression3 commands evaluated if expression3 is True elseif expression4 commands evaluated if expression4 is True elseif …… . . . else commands evaluated if no other expression is True end
最后的这种形式,只和所碰到的、与第一个真值表达式相关的命令被执行;接下来的关 系表达式不检验,跳过其余的 If-Else-End结构。而且,最后的else命令可有可无 现在我们知道了如何用 If-Else-End结构来决策,就有可能提出一种合理的方法来跳出 或中断For循环和 While循环。 》EPS=1; > for num=1: 1000 EPS=EPSh2 f(l+EPS<= EPS=EPS 2 end 2.2204e-016 num 这个例子演示了估算EPS的另一种方法。在这种情况下,For循环构造成要执行足够多 的次数。If-Else-End结构检验要看EPS是否变得足够小。如果是,EPS乘2, break命令强 迫For循环提早结束,num=53。 在这个例子里,当执行 break语句时, MATLAB跳到循环外下一个语句。在现在情况 下,它返回到 MATLAB的提示符并显示EPS。如果一个 break语句出现在一个嵌套的For 循环或 While循环结构里,那么 MATLAB只跳出 break所在的那个循环,不跳出整个嵌套 结构。 7.4小结 MATLAB控制流功能可以概括如下: 控制流结构 for x= array For循环,每一次迭代将x赋以数组的 第i列,执行命令 while expression While循环,只要表达式的所有元素 为真或非零,执行命令
最后的这种形式,只和所碰到的、与第一个真值表达式相关的命令被执行;接下来的关 系表达式不检验,跳过其余的 If-Else-End 结构。而且,最后的 else 命令可有可无。 现在我们知道了如何用 If-Else-End 结构来决策,就有可能提出一种合理的方法来跳出 或中断 For 循环和 While 循环。 » EPS=1; » for num=1:1000 EPS=EPS/2; if (1+EPS)<=1 EPS=EPS*2 break end end EPS = 2.2204e-016 » num num = 53 这个例子演示了估算 EPS 的另一种方法。在这种情况下,For 循环构造成要执行足够多 的次数。If-Else-End 结构检验要看 EPS 是否变得足够小。如果是,EPS 乘 2,break 命令强 迫 For 循环提早结束,num=53。 在这个例子里,当执行 break 语句时,MATLAB 跳到循环外下一个语句。在现在情况 下,它返回到 MATLAB 的提示符并显示 EPS。如果一个 break 语句出现在一个嵌套的 For 循环或 While 循环结构里,那么 MATLAB 只跳出 break 所在的那个循环,不跳出整个嵌套 结构。 7.4 小结 MATLAB 控制流功能可以概括如下: 表 7.1 控 制 流 结 构 for x = array commands end For 循环,每一次迭代将 x 赋以数组的 第 i 列,执行命令 while expression commands end While 循环,只要表达式的所有元素 为真或非零,执行命令
if expression 简单的 If-Else-End结构,若在表达式 command 中的所有元素是真值或非零,执行 命令。 if expression 具有两条路径的 If-Else-End结构 commands evaluated if Tr 若表达式为真或非零,则执行一组 else expression 命令。若表达式为假或零, commands evaluated if False 则执行另一组命令 d commands evaluated if expression is True elseif expression2 commands evaluated if expression.2 is True最一般的 I f-Else-End结构。 if expression 只执行与第一个真值表达式相关 commands evaluated if expression3 is True的命令 commands evaluated if no other expression is True 结束For循环和 While循环的执行 7.5M文件举例 为了演示 If-Else-End结构,考虑精通 MATLAB工具箱中函数 mmono,它检查一个向 量的单调性 >)mmono(1: 12) strictly increasing input ))mmono([ 1: 1212 13: 24) non decreasing input mmono([132-1]) o not monotonic in any sense
if expression commands end 简单的 If-Else-End 结构,若在表达式 中的所有元素是真值或非零,执行 命令。 if expression commands evaluated if True else expression commands evaluated if False end 具有两条路径的 If-Else-End 结构, 若表达式为真或非零,则执行一组 命令。若表达式为假或零, 则执行另一组命令。 if expression1 commands evaluated if expression1 is True elseif expression2 commands evaluated if expression2 is True if expression3 commands evaluated if expression3 is True elseif …… · · · else commands evaluated if no other expression is True end 最一般的 If-Else-End 结构。 只执行与第一个真值表达式相关 的命令。 break 结束 For 循环和 While 循环的执行 7.5 M 文件举例 为了演示 If-Else-End 结构,考虑精通 MATLAB 工具箱中函数 mmono,它检查一个向 量的单调性。 » mmono(1:12) % strictly increasing input ans = 2 » mmono([1:12 12 13:24]) % non decreasing input ans = 1 » mmono([1 3 2 -1]) % not monotonic in any sense ans = 0
>)mmono((12: -1: 00-1 non increasing ans >)mmono(12: -1: 0) strictly decrasing 这个精通 MATLAB工具箱的函数主体给出如下 MMONO Test for monotonic vector o MMONO() where x is a vector return 2 if x is strictly increasing I if x is non decreasing I if x is non increasing, 2 if x is strictly decreasing 0 otherwise Copyright(c)1996 by Prentice-Hall, Inc make x a col =diff(x); find differences between consecutive elements if all(y>0) %o test for strict first elseif all(y>=0) f=1 elseif all(y<o) test for strict first f=-2: elseif all(y<=0) f=0; otherwise response end 函数 mmono直接利用了 If-Else-End结构。由于严格单调是一般单调的子集,首先检验 严格的单调是必要的,因为在所碰见的第一个真值分支里,其语句执行之后,结构就结束
» mmono([12:-1:0 0 -1]) % non increasing ans = -1 » mmono(12:-1:0) % strictly decrasing ans = -2 这个精通 MATLAB 工具箱的函数主体给出如下: function f=mmono(x) % MMONO Test for monotonic vector. % MMONO(x) where x is a vector return: % 2 if x is strictly increasing, % 1 if x is non decreasing, % -1 if x is non increasing, % -2 if x is strictly decreasing, % 0 otherwise. % Copyright (c) 1996 by Prentice-Hall,Inc. x=x(:); % make x a column vector y=diff(x); % find differences between consecutive elements if all(y>0) % test for strict first f=2; elseif all(y>=0) f=1; elseif all(y<0) % test for strict first f=-2; elseif all(y<=0) f=-1; else f=0; % otherwise response end 函数 mmono 直接利用了 If-Else-End 结构。由于严格单调是一般单调的子集,首先检验 严格的单调是必要的,因为在所碰见的第一个真值分支里,其语句执行之后,结构就结束