收藏 分销(赏)

Matlab教学资料:第四章循环结构.doc

上传人:二*** 文档编号:4533340 上传时间:2024-09-27 格式:DOC 页数:35 大小:529KB 下载积分:5 金币
下载 相关 举报
Matlab教学资料:第四章循环结构.doc_第1页
第1页 / 共35页
本文档共35页,全文阅读请下载到手机保存,查看更方便
资源描述
目录 第四章 循环结构 1 4.1 while循环 1 例4.1 1 4.2 for循环 5 例4.2 6 例4.3 6 例4.4 8 4.2.1 运算的细节 9 例4.5 11 4.2.2 break和continue语句 12 4.2.3 循环嵌套 13 4.3 逻辑数组与向量化 14 4.3.1 逻辑数组的重要性 15 例4.6 15 4.3.2 用if/else结构和逻辑数组创建等式 17 测试4.1 17 4.4 附加例子 18 例4.7 18 例4.8 23 4.5 总结 28 4.5.1 好的编程习惯总结 29 4.5.2 matlab总结 29 4.6 练习 29 4.1 29 4.2 29 4.3 29 4.4 29 4.5 29 4.6 30 4.7 30 4.9 31 4.10 31 4.11 31 4.12 31 4.13 31 4.14 31 4.15 31 4.16 31 4.17 32 4.18 32 4.19 32 4.20 32 4.21 33 4.22 33 4.23 33 4.24 33 4.25 34 4.26 34 4.27 34 4.28 34 1 第四章 循环结构 循环(loop)是一种matlab结构,它允许我们多次执行一系列的语句。循环结构有两种基本形式:while循环和for循环。两者之间的最大不同在于代码的重复是如何控制的。在while循环中,代码的重复的次数是不能确定的,只要满足用户定义的条件,重复就进行下去。相对地,在for循环中,代码的重复次数是确定的,在循环开始之前,我们就知道代码重复的次数了。 4.1 while循环 只要满足一定的条件,While循环是一个重复次数不能确定的语句块。它的基本形如下 while expression ... ... code block ... end 如果expression的值非零(true),程序将执行代码块(code block),然后返回到while语句执行。如果expression的值仍然非零,那么程序将会再次执行代码。直到expression的值变为0,这个重复过程结束。当程序执行到while语句且expression的值为0之后,程序将会执行end后面的第一个语句。 while循环的伪代码为 while expr ... ... ... end 我们将用whlie循环编写一个统计分析的程序。 例4.1 统计分析在科学工程计算中,跟大量的数据打交道是非常平常的事,这些数据中的每一个数据都是对我们关心的一些特殊值的度量。本课程的第一次测验的成绩就是一个简单的例子。每一个成绩都对某一个学生在本课程中学到多少东西的度量。 许多的时侯,我们并不关心某一个单个数据。我们可以通过总结得到几个重要的数据,以此告诉我们数据的总体情况。例如,一组数据的平均数(数学期望)和标准差。平均数的定义如下: (4.1) 其中xi代表n个样本中的第i个样本。如果所有的输入数据都可以在一个数组中得到,这些数据的平均数就可以通过公式(4.1)直接计算出来,或应用matlab的内建函数mean。 标准差的定义如下: (4.2) 标准差则体现随机变量取值与其期望值的偏差。标准差的值较大,则表明该随机变量的取值与其期望值的偏差较大,反之,则表明此偏差较小。如果所有的输入数据都可以在一个数组中得到,这些数据的平均数就可以通过公式(4.2)直接计算出来,或应用matlab的内建函数std。本例的目的是要通过公式4.1,4.2计算平均数和标准差,向大家介绍while循环的应用。我们要执行的算法是读取一个组数据,计算它们的平均数和标准差,最后输出结果。 答案: 程序必须能读取一系列的测量值,并能够计算出这些测量值的数学期望和标准差。在进行计算之前,我们有while循环来读取这些测量值。 当所有的测量值输入完毕,我们必须通过一定的方法来告诉程序没有其它的数据输入了。在这里,我们假设所有测量值均为非负数,我们用一个负数来表示数据输入完毕。当一个负数输入时,程序将停止读取输入值,并开始计算这些数据的数学期望和方差。 1.陈述问题因为我们假设所有的输入数据为非负数,则合适地问题陈述为:计算一组测量数的平均数和方差,假设所有测量值为非负数;假设我们事先不知道有多少个测量数。一个负数的输入值将代表测量值输入的结束。 2.定义输入值和输出值这个程序的输入是未知数目的非负数。输出为这些非负数的平均数和标准差。顺便还要打印出输入数据的数据,以便于检测程序的正确性。 3.设计算法这个程序可分为以下三大步: Accumulate the input data Calculate the mean and standard deviation Write out the mean, standard deviation, and number of points 每一大步的为读取输入值。为达此目的,我们必须提示用户输入合适的值。当数据输入完毕,我们将计算出数据的个数,它们的和与平方和。这些步骤的伪代码如下所示 Initialize n, sum_x, and sum_x2 to 0 Prompt user for first number Read in first x while x >=0 n←n+1 sum_x←sum_x + x sum_x2←sum_x2 + x^2 Prompt user for next number Read in next x end 注意我们必须在while循环开始之前,我们必须读取第一个值,这样在while循环第一次运行中才有了检测值。 下一步,我们要计算出数学期望和标准差。这个步骤的伪代码就是公式(4.1)和(4.2) 的matlab版本。 x_bar ← sum_x / n std_dev ← sqrt((n*num_x2 – sum_x^2) / (n*(n-1))) 最后我们写出输出结果: Write out the mean value x_bar Write out the standard deviation std_dev Write out the number of input data points n 4.将伪代码转化为相应的matlab语句最终的matlab程序如下 % Script file: stats_1.m % % Purpose: % To calculate mean and the standard deviation of % an input data set containing an arbitrary number % of input values. % % Record of revisions: % Date Programmer Description of change % ==== ========== ===================== % 12/05/97 S. J. Chapman Original code % % Define variables: % n -- The number of input samples % std_dev -- The standard deviation of the input samples % sum_x -- The sum of the input values % sum_x2 -- The sum of the squares of the input values % x -- An input data value % xbar -- The average of the input samples % Initialize sums. n = 0; sum_x = 0; sum_x2 = 0; % Read in first value x = input('Enter first value: '); % While Loop to read input values. while x >= 0 % Accumulate sums. n = n + 1; sum_x = sum_x + x; sum_x2 = sum_x2 + x^2; % Read in next value x = input('Enter next value: '); end % Calculate the mean and standard deviation x_bar = sum_x / n; std_dev = sqrt( (n * sum_x2 - sum_x^2) / (n * (n-1)) ); % Tell user. fprintf('The mean of this data set is: %f\n', x_bar); fprintf('The standard deviation is: %f\n', std_dev); fprintf('The number of data points is: %f\n', n); 5.检测程序为检测这个程序,我们将手工算出一组简单数据的平均数和标准差,然后与程序产生的结果进行比对。如果我们用三个输入值:3,4和5,那么它的平均数和标准差分别为 我们把这些值输入程序后,产生的结果为 >> stats_1 Enter first value: 3 Enter next value: 4 Enter next value: 5 Enter next value: -1 The mean of this data set is: 4.000000 The standard deviation is: 1.000000 The number of data points is: 3.000000 这个结果说明了程序的正确性。在这个例子中,我们并没有完全遵循设计过程。这个失误导致这个软件有一个致命的缺陷。你能指出来它吗? 我们的错误就在于我们没有检测程序所有可能的输入类型。请重看一遍程序。如果我们不输入数或者只输入一个数,那么上面的公式就会出现除以0的情况。这种除0错误将会在导致在命令窗口内出现divide­by­zero的警告,导致输出值为无穷大(NaN)。我们需要修改这个程序来解决这个问题,告诉用户这个问题是什么,并在适当的时侯停止。这个程序的修定版本为stats_2。在运行运算之前,我们必须检查是否有足够多的输入值。如果没有,程序将打印出错误提示信息,并且跳出。你自己检测一下这个版本的程序。 % Script file: stats_2.m % % Purpose: % To calculate mean and the standard deviation of % an input data set containing an arbitrary number % of input values. % % Record of revisions: % Date Programmer Description of change % ==== ========== ===================== % 12/05/97 S. J. Chapman Original code % 1. 12/06/97 S. J. Chapman Correct divide-by-0 error if % 0 or 1 input values given. % % Define variables: % n -- The number of input samples % std_dev -- The standard deviation of the input samples % sum_x -- The sum of the input values % sum_x2 -- The sum of the squares of the input values % x -- An input data value % xbar -- The average of the input samples % Initialize sums. n = 0; sum_x = 0; sum_x2 = 0; % Read in first value x = input('Enter first value: '); % While Loop to read input values. while x >= 0 % Accumulate sums. n = n + 1; sum_x = sum_x + x; sum_x2 = sum_x2 + x^2; % Read in next value x = input('Enter next value: '); end % Check to see if we have enough input data. if n < 2 % Insufficient information disp('At least 2 values must be entered!'); else % There is enough information, so % calculate the mean and standard deviation x_bar = sum_x / n; std_dev = sqrt( (n * sum_x2 - sum_x^2) / (n * (n-1)) ); % Tell user. fprintf('The mean of this data set is: %f\n', x_bar); fprintf('The standard deviation is: %f\n', std_dev); fprintf('The number of data points is: %f\n', n); end 注意平均数和标准差可以通过MATLAB的内建函数mean和std计算得到,输入数据存储在一个向量内,并把向量作为函数的参数。在本章章末的练习中,将会要求你用标准的matlab函数创建一个新的版本程序。 4.2 for循环 for循环结构是另一种循环结构,它以指定的数目重复地执行特定的语句块。For循环的形式如下 for index = expr Statement 1 ... Body Statement n end 其中index是循环变量(就是我们所熟知的循环指数),exp是循环控制表达式。变量index读取的是数组expr的行数,然后程序执行循环体(loopbody),所以expr有多少列,循环体就循环多少次。expr经常用捷径表达式的]方式,即first:incr:last。 在for和end之前的语句我们称之为循环体。在for循环运转的过程中,它将被重复的执行。For循环结构函数如下: 1.在for循环开始之时,matlab产生了控制表达式 2.第一次进入循环,程序把表达式的第一列赋值于循环变量index,然后执行循环体内的语句。 3.在循环体的语句被执行后,程序把表达式的下一列赋值于循环变量index,程序将再一次执行循环体语句。 4.只要在控制表达式中还有剩余的列,步骤3将会一遍一遍地重复执行。我们要举大量的例子来说明for循环的操作。 第一,考虑下面的例子 for ii = 1:10 Statement 1 ... Statement n end 在这种情况下,控制表达式产生了一个1ⅹ10数组,所以语句1到n将会被重复执行10次。循环系数ii在第一次执行的时侯是1,第二次执行的时侯为2,依次类推,当最后一次执行时,循环指数为10。在第十次执行循环体之后,再也没有新的列赋值给控制表达式,程序将会执行end语句后面的第一句。注意在循环体在最后一次执行后,循环系数将会一直为10。 第二,考虑下面的例子。 for ii = 1:2:10 Statement 1 ... Statement n end 在这种情况下,控制表达式产生了一个1ⅹ5数组,所以语句1到n将会执行5次。循环指数ii在第一次执行时为1,第二次执行时为3,依此类推,最后一次执行时为9。在第五次执行循环体之后,再也没有新的列赋值给控制表达式,程序将会执行end语句后面的第一句。注意在循环体在最后一次执行后,循环系数将会一直为9。 第三,考虑下面的例子。 for ii = [5 9 7] Statement 1 ... Statementn end 在这里,控制表达式是一个直接写出的1ⅹ3的数组,所以语句1到n将会执行3次,循环指数ii在第一次执行时为1,第二次执行时为3,第三次执行时为7。循环指数在循环结束之后一直为7。 最后,考虑下面的例子。 for ii = [1 2 3; 4 5 6] Statement 1 ... Statement n end 在这里,控制表达式是一个直接写出的2ⅹ3的数组,所以语句1到n将会执行3次,循环指数ii在第一次执行时为行向量 ,第二次执行时为 ,第三次执行时为 。这个例子说明循环指数可以为向量。 对应于for循环的伪代码为: for index = expression Statement 1 ... Statement n end 例4.2 阶乘(factorial)函数 为了说明for循环操作,我们将用for循环来计算阶乘函数。阶乘函数的定义如下: N!=1 N=0 N!=N * (N-1) * (N-2) * ... * 3 * 2 * 1 N>0 计算N的阶乘的matlab代码为 n_factorial = 1 for ii = 1 : n n_factorial = n_factorial * ii; end 假设我们要计算5的阶乘。如果n为5,for循环控制表达式将会产生行向量[1 2 3 4 5]。这种循环将会执行5次,ii值按先后顺序依次为1,2,3,4,5。n_factorial最终的计算结果为1ⅹ2ⅹ3ⅹ4ⅹ5=120。 例4.3 计算the day of year the day of year是指这一年已经逝去的天数(包括当天)。在平年中,它的取值范围为1到365,在闰年中,它的取值范围1到366。编写一个matlab程序,输入年,月,日,输入为对应的the of year。 答案: 为了确定the day of year,程序需要计算先前月份的天数之后,然后再计算当月已经过去了多少天,在求和的过程中将会用到for循环。因为每一个月的天数不尽相同,所以我们要确定每一个月的正确天数。我们用switch结构来确定它。 在闰年时,在二月后的某一天的the day of year将会比平年时大1。因为在闰年的二月份多出一个2月29号。所以为了正确地计算出the day of year,我们必须确定那一年是闰年。在公历中,闰年是这样规定的 1.能被400整除的年为闰年 2.能被100整除但不能被400整除的年不为闰年 3.能被4整除但不能被100整除年为闰年 4.其余的年份不为闰年 我们将用到mod(求余)函数来确定一个数是否能被另一个数整除。如果函数的返回值为0,则说一个数能被另一个数整除,否则,则不然。 下面是一个用于计算the day of year的程序。注意程序如何计算出前面月份总共的天数,如何应用switch结构确定每一月的天数。 % Script file: doy.m % % Purpose: % This program calculates the day of year corresponding % to a specified date. It illustrates the use switch % and for constructs. % % Record of revisions: % Date Programmer Description of change % ==== ========== ===================== % 12/07/98 S. J. Chapman Original code % % Define variables: % day --Day (dd) % day_of_year --Day of year % ii --Loop index % leap_day --Extra day for leap year % month --Month (mm) % year --Year(yyyy) % Get day, month, and year to convert disp('This program calculates the day of year given the '); disp('current date.'); month = input('Enter current month (1-12):'); day = input('Enter current day(1-31):'); year = input('Enter current year(yyyy): '); % Check for leap year, and add extra day if necessary if mod(year,400) == 0 leap_day = 1; % Years divisible by 400 are leap years elseif mod(year,100) == 0 leap_day = 0; % Other centuries are not leap years elseif mod(year,4) == 0 leap_day = 1; % Otherwise every 4th year is a leap year else leap_day = 0; % Other years are not leap years end % Calculate day of year by adding current day to the % days in previous months. day_of_year = day; for ii = 1:month - 1 % Add days in months from January to last month switch (ii) case {1,3,5,7,8,10,12}, day_of_year = day_of_year + 31; case {4,6,9,11}, day_of_year = day_of_year + 30; case 2, day_of_year = day_of_year + 28 + leap_day; end end % Tell user fprintf('The date %2d/%2d/%4d is day of year %d.\n', ... month, day, year, day_of_year); 我们用下面已知的结果来检测这个程序。 1.1999年不是闰年。它的1月1号对应的day of year是1,12月31号必定对应的是365。 2.2000年是一个闰年。它的1月1号对应的day of year是1,12月31号必定对应的是366。 3.2001年不是闰年。它的1月1号对应的day of year是30。这个程序5次运行后的结果分别为 >> doy This program calculates the day of year given the current date. Enter current month (1-12):1 Enter current day(1-31):1 Enter current year(yyyy): 1999 The date 1/ 1/1999 is day of year 1. >> doy This program calculates the day of year given the current date. Enter current month (1-12):12 Enter current day(1-31):31 Enter current year(yyyy): 1999 The date 12/31/1999 is day of year 365. >> doy This program calculates the day of year given the current date. Enter current month (1-12):1 Enter current day(1-31):1 Enter current year(yyyy): 2000 The date 1/ 1/2000 is day of year 1. >> doy This program calculates the day of year given the current date. Enter current month (1-12):12 Enter current day(1-31):31 Enter current year(yyyy): 2000 The date 12/31/2000 is day of year 366. >> doy This program calculates the day of year given the current date. Enter current month (1-12):3 Enter current day(1-31):1 Enter current year(yyyy): 2001 The date 3/ 1/2001 is day of year 60. 通过5次不同情况的检测,这个程序给出了正确的结果。 例4.4 统计分析 执行如下算法: 输入一系列的测量数,计算它们的平均数和标准差。这些数可以是正数,负数或0。 答案: 这个程序必须能够读取大量数据,并能够计算出这些测量值的平均数和标准差。这些测量值可以是正数,负数或0。 因为我们再也不能用一个数来表示数据中止的标识了,我们要求用户给出输入值的个数,然后用for循环读取所有数值。 下面的就是这个修定版本的程序。它允许各种输入值,请你自己验证下面5个输入值的平均数和标准差:3,­1,0,1,­2。 % Script file: stats_3.m % % Purpose: % To calculate mean and the standard deviation of % an input data set, where each input value can be % positive, negative, or zero. % % Record of revisions: % Date Programmer Description of change % ==== ========== ==================== % 12/08/97 S. J. Chapman Original code % % Define variables: % ii Loop index % n The number of input samples % std_dev The standard deviation of the input samples % sum_x The sum of the input values % sum_x2 The sum of the squares of the input values % x An input data value % xbar The average of the input samples % Initialize sums. sum_x = 0; sum_x2 = 0; % Get the number of points to input. n = input('Enter number of points: '); % Check to see if we have enough input data. if n < 2 % Insufficient data disp ('At least 2 values must be entered.'); else % we will have enough data, so let's get it. % Loop to read input values. for ii = 1:n % Read in next value x = input('Enter value: '); % Accumulate sums. sum_x = sum_x + x; sum_x2 = sum_x2 + x^2; end % Now calculate statistics. x_bar = sum_x / n; std_dev = sqrt((n * sum_x2 - sum_x^2) / (n * (n - 1))); % Tell user. fprintf('The mean of this data set is: %f\n', x_bar); fprintf('The standard deviation is: %f\n', std_dev); fprintf('The number of data points is: %f\n', n); end 4.2.1 运算的细节 既然我们已经看了许多for循环的例子。在用for循环时,我们必须检查许多重要的细节。 1.没有必要缩进for循环的循环体。即使所有语句都左对齐,matlab程序也会识别出这个循环。但缩进循环体能增强代码的可读性,所以建议大家缩进循环体。 好的编程习惯 对于for循环体总是要缩进两个或更多空格,以增强程序的可读性。 2.在for循环中,我们不能随意修改循环指数。循环指数常被用作计算器, 如果修改了它们将会导致一些奇怪而难以发现的错误。下面的一个例子将初始化一个函数的数组。但是语句“ii=5”的突然出现,导致只有a(5)得到了初始化,它得到了本应赋给a(1),a(2)等等的值。 for ii = 1:10 ... ii = 5 ; %Error! ... a(ii) = <calculation> end 好的编程习惯 在循环体中绝不修改循环指数的值。 3.我们在第二章已经学过,用赋值的方法可以扩展一个已知的数组。例如,语句 arr = 1:4; 定义了一个数组[1 2 3 4]。如果执行语句 arr(8) = 6; 将会产生一个八元素数组[1 2 3 4 0 0 0 6]。不幸的是,每一次扩展数组,都要经过以下步骤:第一步,创建一个新数组。第二步,把旧数组的元素复制到新数组当中。第三步,把扩展的元素写入新数组。第四步,删除旧数组。对于大数组来说这些步骤是相当耗时的。 当一个for循环中存储了一个预先未定义的数组,在第一次循环执行的时侯,循环结构迫使matlab重复执行以上步骤。从另一方面说,如果在循环开始之前数组预先分配了数组的大小,那么复制就不需要了,执行代码的速度也将加快。下面代码片段向大家展示了在循环开始之前如何预先分配数组。 好的编程习惯 在循环执行开始之前,总是要预先分配一个数组,这样能大大增加循环运行的速度。 4.用for循环和向量计算是非常常见的。例如,下面的代码片段用for循环计算1到100之间的所有整数的平方,平方根,立方根。 for ii = 1:100 square(ii) = ii ^2; square_root(ii) = ii ^ (1/2); cube_root(ii) = ii ^ (1/3); end 下面一个代码片段是用向量计算上面的问题。 ii = 1:100; square = ii .^2; square_root = ii .^ (1/2); cube_root(ii) = ii .^ (1/3); 尽管两种算法得到了相同的结果,但两者并不同等价。因为for循环算法比向量算法慢15倍还多。这是由于matlab通过每一次循环时,每行都要翻译执行一次。也相当于matlab翻译执行了300行代码。相反,如果用向量算法,matlab只需要翻译执行4行代码。所以用向量语句它的执行速度非常快。 向量算法的缺点是需要很大的内存,因为一些间接的数组需要创建。这经常是一小点损失,所以要比for循环算法好的多。 在matlab中,用向量算法代替循环的算法的过程称之为向量化(vectorization)。向量化能够改进许多的matlab程序。 好的编程习惯 那种既可以用向量可以解决的问题,也可以用循环解决的问题,最好用向量解决,这是因为向量执行的速度快。 例4.5 比较向量算法和循环为了比较循环和向量算法执行若无事所用的时间,用两种方法编程并测试三个运算所花的时间。 1.用for循环计算1到10000的之间每一个整数的平方,而事先不初始化平方数组。 2.用for循环计算1到10000的之间每一个整数的平方,而事先初始化平方数组。 3.用向量算法计算计算1到10000的之间每一个整数的平方。 答案: 这个程序必须用上面提供的三种方示计算出1到10000之间的每一个整数的平方,并测试每一个种算法的时间。测试时间要用到matlab函数tic和toc。tic函数复位内建计时器,而toc函数则从最后一次调用tic以秒开始计时。 因为在许多的计算机中它的时间钟是相当粗略的,所以有必要多运行几次以获得相应的平均数。 下面就是用三种方法编出的matlab程序。 % Script file: timings.m % % Purpose: % This program calculates the time required to %
展开阅读全文

开通  VIP会员、SVIP会员  优惠大
下载10份以上建议开通VIP会员
下载20份以上建议开通SVIP会员


开通VIP      成为共赢上传

当前位置:首页 > 教育专区 > 其他

移动网页_全站_页脚广告1

关于我们      便捷服务       自信AI       AI导航        抽奖活动

©2010-2026 宁波自信网络信息技术有限公司  版权所有

客服电话:0574-28810668  投诉电话:18658249818

gongan.png浙公网安备33021202000488号   

icp.png浙ICP备2021020529号-1  |  浙B2-20240490  

关注我们 :微信公众号    抖音    微博    LOFTER 

客服