循环(loop)
是一种
matlab 结构,它允许我们多次执行一系列的语句。循环结构有两种基本形式
:while
循环和
for 循环。两者之间的最大不同在于代码的重复是如何控制的。在while 循环中,代码的重复的次数是不能确定的,只要满足用户定义的条件,重复就进行下去。相对地,在
for 循环中,代码的重复次数是确定的,在循环开始之前,我们就知道代码重复的次数了。
1 while 循环
只要满足一定的条件,While 循环是一个重复次数不能确定的语句块。它的基本形如下
如果 expression
的值非零
(true)
,程序将执行代码块
(code block)
,然后返回到
while 语句执行。如果
expression
的值仍然非零,那么程序将会再次执行代码。直到
expression 的值变为
0
,这个重复过程结束。当程序执行到
while
语句且
expression
的值为
0 之后,程序将会执行
end
后面的第一个语句。
我们将用 whlie
循环编写一个统计分析的程序。
例
1
统计分析在科学工程计算中,跟大量的数据打交道是非常平常的事,这些数据中的每一个数据都是对我们关心的一些特殊值的度量。本课程的第一次测验的成绩就是一个简单的例子。每一个成绩都对某一个学生在本课程中学到多少东西的度量。
许多的时侯,我们并不关心某一个单个数据。我们可以通过总结得到几个重要的数据,以此告诉我们数据的总体情况。例如,一组数据的平均数
(
数学期望
)和标准差。平均数的定义如下
:
标准差的定义如下:
标准差则体现随机变量取值与其期望值的偏差。标准差的值较大,则表明该随机变量的取值与其期望值的偏差较大,反之,则表明此偏差较小。如果所有的输入数据都可以在一个数组中得到,这些数据的平均数就可以通过公式
(4.2)
直接计算出来,或应用
matlab 的内建函数
std
。本例的目的是要通过公式
4.1
,
4.2 计算平均数和标准差,向大家介绍 while循环的应用。我们要执行的算法是读取一个组数据,计算它们的平均数和标准差,最后输出结果。
答案
:
程序必须能读取一系列的测量值,并能够计算出这些测量值的数学期望和标准差。在进行计算之前,我们有
while
循环来读取这些测量值。
当所有的测量值输入完毕,我们必须通过一定的方法来告诉程序没有其它的数据输入了。在这里,我们假设所有测量值均为非负数,我们用一个负数来表示数据输入完毕。当一个负数输入时,程序将停止读取输入值,并开始计算这些数据的数学期望和方差。
1.陈述问题因为我们假设所有的输入数据为非负数,则合适地问题陈述为
:计算一组测量数的平均数和方差,假设所有测量值为非负数
;假设我们事先不知道有多少个测量数。一个负数的输入值将代表测量值输入的结束。
2.定义输入值和输出值这个程序的输入是未知数目的非负数。输出为这些非负数的平均数和标准差。顺便还要打印出输入数据的数据,以便于检测程序的正确性。
3.设计算法,这个程序可分为以下三大步
:
累积输入数据,
计算平均值和标准差
写出平均值、标准差
每一大步的为读取输入值。为达此目的,我们必须提示用户输入合适的值。当数据输入完毕,我们将计算出数据的个数,它们的和与平方和。这些步骤的伪代码如下所示
将n,sum_x和sum_x2初始化为0
提示用户输入第一个数字
读入第一个x
while x >=0 (当x大于等于0时)
n←n+1 (n加1)
sum_x←sum_x + x (sum_x加上x)
sum_x2←sum_x2 + x^2 (sum_x2加上x的平方)
提示用户输入下一个数字
读入下一个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)))
最后我们写出输出结果
写出平均值x_bar
写出标准差std_dev
写出输入数据点的数量n
4.将伪代码转化为相应的 matlab 语句最终的 matlab 程序如下
% 脚本文件: stats_1.m
%
% 目的:
% 计算包含任意数量输入值的输入数据集的平均值和标准差。
%
% 定义变量:
% n——输入样本数
% std_dev——输入样本的标准差
% sum_x——输入值之和
% sum_x2——输入值平方的和
% x——一个输入数据值
% xbar——所有输入数据的平均值
% 初始化求和
n = 0;
sum_x = 0;
sum_x2 = 0;
% 读入第一个值
x = input('Enter first value: ');
% while循环来读取输入的值。
while x >= 0
% 累计求和。
n = n + 1;
sum_x = sum_x + x;
sum_x2 = sum_x2 + x ^ 2;
% 读入下一个值
x = input('Enter next value: ');
end
% 计算均值和标准差。
x_bar = sum_x / n;
std_dev = sqrt((n * sum_x2 - sum_x ^ 2)/(n*(n-1)));
% 输出结果
fprintf('This data set的平均值为: %f\n', x_bar);
fprintf('标准差:%f\n', std_dev);
fprintf('数据点数:%f\n', n);
5.检测程序为检测这个程序,我们将手工算出一组简单数据的平均数和标准差,然后与程序产生的结果进行比对。如果我们用三个输入值:3,4 和 5,那么它的平均数和标准差分别为
这个结果说明了程序的正确性。在这个例子中,我们并没有完全遵循设计过程。这个失误导致这个软件有一个致命的缺陷。你能指出来它吗?
我们的错误就在于我们没有检测程序所有可能的输入类型。请重看一遍程序。如果我们不输入数或者只输入一个数,那么上面的公式就会出现除以
0
的情况。这种除
0 错误将会在导致在命令窗口内出现
divide-by-zero
的警告,导致输出值为无穷大(NaN)。我们需要修改这个程序来解决这个问题,告诉用户这个问题是什么,并在适当的时侯停止。这个程序的修定版本为
stats_2。在运行运算之前,我们必须检查是否有足够多的输入值。如果没有,程序将打印出错误提示信息,并且跳出。你自己检测一下这个版本的程序。
注意平均数和标准差可以通过 MATLAB
的内建函数
mean
和
std 计算得到,输入数据存储在一个向量内,并把向量作为函数的参数。
% 脚本文件: stats_2.m
%
% 目的:
% 计算包含任意数量输入值的输入数据集的平均数和标准偏差。
%
% 修改记录:
% 日期 程序员 修改描述
% ==== ========== =============================
% 12/05/97 S. J. Chapman 原始代码
% 1. 12/06/97 S. J. Chapman 如果输入值为0或1,修正除以0的错误。
%
% 定义变量:
% n——输入样本数
% std_dev——输入样本的标准差
% sum_x——输入值之和
% sum_x2——输入值平方的和
% x——一个输入数据值
% xbar——所有输入数据的平均值
% 初始化求和。
n = 0; sum_x = 0; sum_x2 = 0;
% 读入第一个值。
x = input('输入第一个数: ');
% while循环来读取输入的值。
while x >= 0
% 累计求和。
n = n + 1;
sum_x = sum_x + x;
sum_x2 = sum_x2 + x^2;
% 读入下一个值。
x = input('输入下一个数: ');
end
% 检查是否有足够的输入数据。
if n < 2 % 不足的信息
disp('至少必须输入两个数!');
else % 输入信息充足,所以
% 计算平均值和标准偏差。
x_bar = sum_x / n;
std_dev = sqrt( (n * sum_x2 - sum_x^2) / (n * (n-1)) );
% 告诉用户。
fprintf('这组数据的平均数是: %f\n', x_bar);
fprintf('标准偏差是:%f\n', std_dev);
fprintf('数据点数为:%f\n', n);
end