《MATLAB编程(第二版) 第三章.doc》由会员分享,可在线阅读,更多相关《MATLAB编程(第二版) 第三章.doc(39页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、目录第三章 分支语句和编程设计13.1 自上而下的编程方法简介13.3 关系运算符和逻辑运算符43.3.1 关系运算符43.3.2 小心=和=运算符53.3.3 逻辑运算符6例3.173.3.4 逻辑函数7测试3.173.4 选择结构(分支语句)83.4.1 if结构83.4.2 if结构举例9例3.29例3.3123.4.3 关于if结构使用的注意事项13例3.4143.4.4 switch结构153.4.5 try/catch结构的应用16测试3.2173.5 附加的画图特性173.5.1 控制x,y轴绘图的上下限183.5.2 在同一坐标系内画出多个图象203.5.3 创建多个图象203
2、.5.4 子图象213.5.5 对画线的增强控制223.5.6 文本字符串的高级控制223.5.7极坐标图象23例3.524例3.625例3.7263.5.8 注释并保存图象28测试3.3303.6 程序调试的进一步说明303.7 总结333.7.1 好的编程习惯的总结343.7.2 matlab总结343.8 练习343.1343.2343.3343.4353.5353.6353.7353.8353.9353.10363.11363.12363.13363.1437第三章 分支语句和编程设计在前面的章节中,我们开发了几个完全运转的MATLAB程序。但是这些程序都十分简单,包括一系列的MATL
3、AB语句,这些语句按照固定的顺序一个接一个的执行。像这样的程序我们称之顺序结构程序。它首先读取输入,然后运算得到所需结果,打印出结果,并退出。至于要多次重复运算程序的某些部分是没有办法的,也不能根据输入的值,有选择地执行程序的某些部分。在下面的两章中,我们将向大家介绍大量的MATLAB语句,这些语句允许我们来控制中语句的执行顺序。有两大类控制顺序结构:选择结构,用选择执行特定的语句;循环结构,用于重复执行特定部分的代码。选择结构将会本章讨论,循环结构我们将会在第四章讨论。随着选择和循环介绍,我们的程序也将变得复杂,对于解决问题来说,将会变得简单。为了帮助大家避免在编程过程中出现大量的错误,我们
4、将向大家介绍正式的编程步骤,即自上而下的编程方法。我们也会向大家介绍一些普通的算法开发工具即伪代码。3.1 自上而下的编程方法简介假设你是在工厂工作的工程师,为了解决某些问题,你要编写一个程序。你如何开始呢?当遇到一个新问题时,我们的心里会自然而然的产生这样的想法:马上坐在计算机前,开始编程,而不用浪费大量的时间思考我们所要解决的问题是什么?用这种不切实际的想法来编一些非常小的程序可能会成功。但在现实中,问题可能会非常的大,程序员再用这种方法编程将会陷入困境。对于一个大的程序来说,在编写代码之前你要通盘的思考你所要面临的问题和解决的方法。在本节中,我们将向大家介绍正式的编程设计步骤,然后应用这
5、个步骤来编写本书所有的大的应用程序。对于我们所遇到一些简单的例子来说,这个步骤好像有些画蛇添足。但是当我们解决的问题变得越来越大的时侯,这个步骤将会变得异常重要。当我还没有毕业的时侯,一个教授喜欢说:“编程很简单,因为我知道在编程的过程的困难”。当我们离开学校,在工厂从事于大规模软件工程编写时,我深深地理解了它所说的话。我发现在工作中我遇到的大多数困难都是对所要解决问题的理解。一旦你真正理解了问题,你就会把这个问题分解成许多小的问题,更加易于管理的小块,然后逐一解决某一个小块。自上而下的编程方法是我们正规编程设计的基础。我们现在向大家介绍这些在图3.1说明的步骤细节。步骤如下:1.清晰地陈述你
6、所要解决的问题编写的程序大多数情况下要满足一些感觉上的需要,但这种需要不一定能够被人清晰地表达出来。例如,用户需要一个解线性方程组的表达式。像这样的要求就不够清楚,程序员就很难编出一个使他满意的程序。他必须弄清楚要有多少问题需要解决?在这些方程式中有没有对称的形式使我们的开发变得简单?程序设计者必须和使用者讨论所需的程序,他们必须要对完成的任务有一个精确细致的描述。对问题清晰的描述可以防止误解,并且能够帮助程序员合理的组织他的思想。上面的例子对问题合适的陈述应为:设计一个用于解决联立线性方程组的程序,这些方程中未知数的系数为实数,最多有20个未知数。图3.12.定义程序所需的输入量和程序所产生
7、的输出量指定输入量和输出量,只有这样新的程序才能适应全过程计划。在这个例子中方程式的系数可能有其预先存在的顺序,我们的新程序必须能按照顺序读取它们。相似地,也需要产生出这个程序所要求的结果,即输出量,我们还要以一定的格式打印出来。3.设计你的程序得以实现的算法开始陈述你要求解决的问题选定所需的输入和输出设计算法把算法转化为MATLAB语言检测产生的MATLAB程序完成分解逐步求精算法是指为某个问题找到答案一步接一步的程序。在这个阶段自上而下的编程方法发挥了作用。编程设计者开始对这个问题进行逻辑划分,把它逐步分解为一个又一个子工作。这个过程叫做分解(decomposition)。如果一些子工作还
8、是比较大,设计者还可以把他它分解成更小的块。这个过程将会继续到问题被分解成许多简单且易理解的小块为止。在问题被分解成小块之后,每一个小块要被进一步的求精,这个过程叫做逐步求精(stepwise refinement)。在这个过程中,设计者开始于对本小块代码总括性的描述,然后开始一步一步地定义所需的函数,越来越具体,直到他能够转化为MATLAB语句。逐步求精的过程中,我们要用到的伪代码将会在下节为大家介绍。在算法开发过程中,这个方法是非常有用的。如果设计者真正理解了解决问题这个些步骤,他将会对问题进行分解和逐步求精。4.把算法转化为代码如果分解和逐步求精的过程已经顺利完成,那么这一步将会异常地简
9、单。所有程序员都会将伪代码一句一句地转化为合适地MATLAB语句。5检测产生的MATLAB程序这一步是真正的拦路虎。首先,程序的每一部分将会被单独地检测,如果有可能的话,整个程序还要被检测一遍。在我们检测程序时,我们必须证明所有合法输入数据值都能够正常运行。用标准的输入值检测程序,看它是否产生了值。如果在一个程序中执行的算法包含了不同的分支,你必须检测每一个分支,以保证产生正确的答案。大程序在交付大众使用之前,必须经过一系列地检测(图3.2)。检测的第一步有时被称为单元检测(unit testing)。在单元检测过程中,程序的子程序将会被独立地检测以证明它的正确性。当单元检测结束之后,这个程序
10、将进行一系列的组合,把独立的子程序联合产生出最后的程序。程序第一步的联合通常只包括很少的子程序。通过组合这些子程序,经常用检查子程序或函数之间的联系。在一系列地组合过程中,越来越多的子程序被加了进来,直到整个程序的完成。在每一次组合的过程中,每一个错误都会被发现并在进行下一次组合之前纠正过来。开始独立子程序的单元检测一系列的组合(把一些子程序添加到程序中)alpha版本beta版本程序结束分别使每一个子程序生效次数根据需要而定将子程序联合成一个独立的程序极其严重的错误的修改小错误修改次数根据需要而定次数根据需要而定图3.2大程序典型地调试过程在整个程序被组合之后,调试继续进行。程序第一个版本我
11、们通常称之为“alpha版本”。程序员和其他有机会接近它的人可以想尽一切办法应用它,以发现其中的漏洞,然后改正之。当许许多多大的错误从程序中去除,一个新的版本出现了,我们称之“beta版本”。beta版本就要公开地发行给天天需要这个程序工作的人。这些用户使这个程序在不同的环境下,在不同的输入条件下工作,会发现许多的错误,并报告给程序员。当这些错误被更正后,这个程序就能够发行给公众使用了。因为本书中的程序都比较小,没有必要进行上述的大规模的检测。但是我们会遵循基本的调试原则。程序设计的基本步骤如下:1.清晰地陈述出你要解决的问题。2.确定程序所需地输入量和程序所产生的输出量。3.为你的程序设计算
12、法4.将算法转化为MATLAB语句5.调试MATLAB程序好的编程习惯遵循上面的步骤编写可靠,易理解的MATLAB程序。在大的编程项目中,花在编程序的时间是出奇的少。Frederick P Brooks在他的the Mythical ManMonth书中写道,对于大的软件工程来说,三分之一的时间花在计划如何来做上(第一步到第三步),六分之一的时间花在编写程序上,近一半的时间用来调试程序。而我们能做的只有压缩调试用的时间。在计划阶段做好充分的准备和在编程过程使用良好的编程习惯,这样会大大降低我们调试所用的时间。好的编程习惯能减少出错的数量,也能使别人迅速地找出其中的错误。3.2伪代码的应用作为我
13、们设计步骤的一部分,描述出你要执行的算法是非常必要的。算法的描述有一种标准形式,能让你和大家都能理解,这种描述将帮助你的内容转化为MATLAB代码。我们用于描述算法的标准形式叫做构造(constructs有时也称structure)。用这些结构描述出的算法,我们称之为结构化算法。当在我们在MATLAB程序中执行这个算法时,产生的程序叫做结构化程序。我们可以用伪代码的形式建立算法的结构。伪代码是MATLAB和英语的混合体。和MATLAB一样,它是结构化的,一行表达一个明确的意思或代码的片段,但每一行的描述用的是英语或其他人类语言。伪代码的每一行都应用普通简单且易于理解的英语或中文描述。因为修改简
14、单灵活,所以伪代码在开发算法的过程中非常的有用。因为伪代码给编辑器或字处理器(通常用于编写MATLAB程序)的,而不需要其他的可视化功能。例如下面是例2.3的算法伪代码Prompt user to enter temperature in degrees FahrenheitRead temperature in degrees Fahrenheit(temp_f)temp_k in kelvins (5/9) * (temp_f - 32) + 273.15Write temperature in kelvins注意用向左指的箭头替代等号(=)指出一个值将存储到对应的变量中,这样就避免了赋值
15、号与等号的混淆。在把它们转化为MATLAB代码之前,伪代码将有助于你思想的组织。3.3 关系运算符和逻辑运算符选择结构的运算由一个表达式控制的,这个表达式的结果只有true(1)和false(0)。有两种形式的运算符可以在MATLAB中关系得到true/false:关系运算符和逻辑运算符。跟C语言一样,MATLAB没有布尔型和逻辑数据类型。MATLAB把0值作为结果false,把所有的非0值作为结果ture。3.3.1 关系运算符关系运算符是指两数值或字符操作数的运算符,这种运算将会根椐两操作数的关系产生结果true或false。关系运算的基本形式如下a1 op a2其中a1和a2是算术表达式
16、,变量或字符串,op代表表3.1中的关系运算符中的一个。如果两者的关系为真(true)时,那么这个运算将会返回1值;否则将会返回0值。表3.1 关系运算符运算符运算=等于=不等于大于=大于或等于小于=小于或等于下面是一些关系运算和它的结果运算结果3 413 404 = 41A b将会产生结果。关系运算符也可比较两个关系运算符,只要两个数组具有相同的大小。例如,表达式a=b将会产生结果。如果这个数组具有不同的大小,那么将会产生运行时错误。注意因为字符串实际上是字符的数组,关系运算符也比较两个相同长度的字符串。如果它们有不同的长度,比较运算将会产生一个错误。在第六章中我们将会学到一个更普遍的方法。
17、等于关系运算符由两个等号组成,而赋值运算符只有一个等号。它们是完全不同的两个符号,初学者极易混淆。符号=是一个比较运算符,返回一个逻辑数,而符号=是将等号右边的表达式的值赋给左边的变量。当进行比较运算的时候,初学者经常用误用符号=。常见编程错误小心谨慎不要混淆了等于关系运算符(=)和赋值运算符(=)。在运算的层次中,关系运算在所有数学运算的之后进行。所以下面两个表达式是等价的,均产生结果1。7 + 3 2 + 11(7 + 3) a = 0; b = sin(pi); a = bans = 0MATLAB报告了a和b不同因为他产生了一个round off错误,在计算中sin(pi)产生了结果1
18、.224610-16而不是0。两个理论上相等的值因为round off错误而失之发生了细微的差别。我们可以通过检测两数之间在一定的范围内是不是近似相等,在这个精确范围内可能会产生round off错误。例如测试 abs(a - b) b2. b d;3. a b & c d4. a = b5. a & b c6. b变量a,b,c,d定义如下,计算后面的表达式。a = 2;b = c = d = 7. (a b);8. a c & b c;9. c a*c11. d | b b a12. (d | b) a变量a,b,c,d定义如下,计算后面的表达式。a = 20;b = -2;c = 0;d
19、 = Test;13. isinf(a/b)14. isinf(a/c)15. a b & ischar(d)16. isempty(c)3.4 选择结构(分支语句)选择结构可以使MATLAB选择性执行指定区域内的代码(称之为语句块blocks),而跳过其他区域的代码。选择结构在MATLAB中有三种具体的形式:if结构,switch结构和try/catch结构。3.4.1 if结构if结构的基本形式如下:if control_expr_1 elseif control_expr_2 else end其中control expression控制if结构的运算。如果control_expr_1的值
20、非0,那么程序将会执行语句块1(block1),然后跳到end后面的第一个可执行语句继续执行。否则,程序将会检测control_expr_2的值,。如果control_expr_2的值非0,那么程序将会执行语句块2(block2),然后跳到end后面的第一个可执行语句继续执行。如果所有的控制表达式(control expression)均为0,那么程序将会执行与else相关的语句块。在一个if结构中,可以有任意个elseif语句,但else语句最多有一个。只要上面每一个控制表达式均为0,那么下一个控制表达式将会被检测。一旦其中的一个表达式的值非0,对应的语句块就要被执行,然后跳到end后面的第
21、一个可执行语句继续执行。如果所有的控制表达式(controlexpression)均为0,那么程序将会执行else语句。如果没有else语句,程序将会执行end后面的语句,而不执行if结构中的部分。注意MATLAB在if结构中的关键字end与第二章中提到的返回已知下标最大值函数end完全不同。matlab通过end在M文件中的上下文来区分开它的两个用途。在大多数情况下,控制表达式均可以联合关系运算符和逻辑运算符。正像我们在本章早些时侯学到的,当对应的条件为真时,关系运算和逻辑运算将会产生1,否则产生0。所以当一个运算条件为真时,运算结果为非0,则对应的语句块,就会被执行。例如,一元二次方程的基
22、本形式如下:ax2 + bx + c = 0(3.1)其解为(3.2)其中b2 - 4ac是我们熟知的判别式,当b2 - 4ac0时,方程式有两个不同的实数根,当b2 - 4ac=0,有两个相同的实数根,当b2 - 4ac0时,方程式有两个不同的复根。假设我们检测某一元二次根的情况,并告诉使用者这个方程有两个复根,还是两个相等的实根和两个不相等的实根。用伪代码这个结构的形式如下:if (b2 - 4*a*c) 0 Write msg that equation has two complex roots.elseif (b2 - 4*a*c) =0 Write msg that equatio
23、n has two identical real roots.else Write msg that equation has two distinct real roots.end转化为MATLAB语言:if (b2 - 4*a*c) 0 disp(This equation has two complex roots.);elseif (b2 - 4*a*c) = 0 disp(This equation has two identical real roots.);else disp(This equation has two distinct real roots.);end回忆一下,
24、判断为真时,关系运算符将会返回一个非0值,从而导致对应语句的执行。为增加程序的可读性,在if结构中的语句块中最好缩进2到3个空格,而实际上没有必要。好的编程习惯if结构体经常缩进2到3个空格,以增强程序的可读性。你可以在一行内写完一个完整的if结构,只需把结构的每一部分后面加上分号或逗号,所以下面的两个结构是等价的:if x 0 y = abs(x);end和if x 0 x1 (-b + sqrt(discriminant) / (2*a) x1 (-b - sqrt(discriminant) / (2*a) Write msg that equation has two distinct
25、 real roots. Write out the two roots.elseif discriminant = 0 x1 -b / (2*a) Write msg that equation has two identical real roots. Write out the repeated roots.else real_part -b / (2*a) imag_part sqrt(abs(discriminant) / (2*a) Write msg that equation has two complex roots. Write out the two roots.end4
26、.把算法转化为MATLAB语言%Script file: calc_roots.m% Purpose:% This program solves for the roots of a quadratic equation% of the form a*x2 + b*x + c = 0. It calculates the answers% regardless of the type of roots that the equation possesses.% Record of revisions:% Date Programmer Description of change% = = =%
27、 12/04/98 S. J. Chapman Original code% Define variables:% a -Coefficient of x2 term of equation% b-Coefficient of x term of equation% c-Constant term of equation% discriminant -Discriminant of the equation% imag_part-Imag part of equation (for complex roots)% real_part-Real part of equation (for com
28、plex roots)% x1-First solution of equation (for real roots)% x2-Second solution of equation (for real roots)% Prompt the user for the coefficients of the equationdisp (This program solves for the roots of a quadratic );disp (equation of the form A*X2 + B*X + C = 0.);a = input(Enter the coefficient A
29、: );b = input(Enter the coefficient B: );c = input(Enter the coefficient C: );% Calculate discriminantdiscriminant = b2 - 4 * a * c;% Solve for the roots, depending on the vlaue of the discriminant.if discriminant 0 % there are two real roots, so . x1 = (-b + sqrt(discriminant) / (2*a); x2 = (-b - s
30、qrt(discriminant) / (2*a); disp(This equation has two real roots:); fprintf(x1 = %fn, x1); fprintf(x2 = %fn, x2);elseif discriminant = 0 % there is one repeated root, so . x1 = ( -b ) / (2*a); disp(This equation has two identical real roots:); fprintf(x1 = x2 = %fn, x1);else % there are complex root
31、s, so . real_part = (-b) / (2*a); imag_part = sqrt( abs(discriminant) / (2*a); disp(This equation has complex roots:); fprintf(x1 = %f + i %f n,real_part, imag_part); fprintf(x1 + %f - i %f n, real_part, imag_part);end5.检测这个程序下一步,我们必须输入实数来检测这个程序。因这个程序有三个可能的路径。所以在我们确信每一人路径都工作正常之前,必须把这三个路径检测一遍。从式子(3.2
32、)中,我们可以有用下面的方法来验证程序的正确性。x2 + 5x + 6 = 0x = -2, and x = -=3x2 + 4x + 4 = 0x = -2x2 + 2x + 5 = 0x = -1 i2如果输入上面三个方程的系数得到对应的结果,则说明程序是正确的。 calc_rootsThis program solves for the roots of a quadratic equation of the form A*X2 + B*X + C = 0.Enter the coefficient A: 1Enter the coefficient B: 5Enter the coef
33、ficient C: 6This equation has two real roots:x1 = -2.000000x2 = -3.000000 calc_rootsThis program solves for the roots of a quadratic equation of the form A*X2 + B*X + C = 0.Enter the coefficient A: 1Enter the coefficient B: 4Enter the coefficient C: 4This equation has two identical real roots:x1 = x
34、2 = -2.000000 calc_rootsThis program solves for the roots of a quadratic equation of the form A*X2 + B*X + C = 0.Enter the coefficient A: 1Enter the coefficient B: 2Enter the coefficient C: 5This equation has complex roots:x1 = -1.000000 + i 2.000000 x1 + -1.000000 - i 2.000000 在三种不同的情况下,程序都给出了正确的结果
35、。例3.3编写一个程序,求以x,y为自变量函数f(x,y)的值。函数f(x,y)的定义如下:f(x,y) = 答案:根据自变量x和y的正负符号的不同,而采取不同的求值表达式。为选取合适的表达式,检查用户输入的x,y的正负符号是必要的。1.陈述问题这个问题的陈述非常简单:根据用户输入的x,y,求函数f(x,y)的值。2.确定输入输出量程序的输入量为函数的自变量x,y。输出量为函数值f(x,y)。3.设计算法这个问题可以把他分解成三个大块,即输入,计算过程,和输出。我们把这三大块再分解成小的,精细的工作。在计算f(x,y)时,我们有4种选择,选哪一种取决于x,y的值。所以及逻辑上我们要用4个选择的if结构来实现。产生的伪代码如下:Prompt the user for the values x and yRead x and yif x0 and y0 fun x + yelseif x0 and y0 fun x + y2elseif x=0 and y=0%| x + y2x=0 and y0%f(x,y)=| x2 + yx=0%| x2 + y2x0 and y0%|_% Record of revisions:% DateProgrammerDescription of change% =% 12/05/98S.J.ChapmanOriginal code
限制150内