Download as pdf or txt
Download as pdf or txt
You are on page 1of 156



主要内容

综 述……(3)
Matlab 用法简介……(5)
绪论……(5)
第一节 Matlab 的安装及使用……(5)
第二节 向量与矩阵运算……(9)
第三节 矩阵的基本运算……(12)
第四节 Matlab 中的图形……(18)
第五节 Matlab 编程……(28)
第六节 Matlab 符号运算……(35)
综合练习……(39)


综 述

数学软件是许多数学工作者经常提到的话题之一,人们将它用于进行科学计
算和数学实验.目前既有专门介绍数学软件的多种书籍,更有若干专门介绍数学
实验的教材.这些书籍或教材的一个共同的特点就在于它们都非常的专业化,一
般读者看起来十分吃力.还有一点就是用于数学实验的数学软件五花八门,读者
往往花费许多时间仍然不得要领.能否有一本相对集中的教材将两者结合起来
呢?应该说是有一定难度的.本教材的目的之一就是作这方面的尝试.本教材的
软件篇和附录篇主要介绍数学软件,而在实验篇则主要介绍数学实验.

众所周知,到目前为止,数学软件大概有如下几类:
(1) 公共的基础软件:BASIC,FORTRAN,Tuobo C,Tuobo Pascal 等;
(2) 矩阵实验室系统:Matlab 等;
(3) 计算机代数系统:Mathematica,Maple 等;
(4) 交互式数学系统:MathCAD,Calcwin 等.
在教材的软件篇里介绍的 Matlab 6.5 软件以及在附录篇里介绍的 Maple v4
等软件有许多共性.在一定意义下,它们是一致的.比如:
(1) 都可以完成数学专业领域中数值运算和解析(符号)运算.数值运算的含
义不言而喻;符号运算的意义是:用户只要在计算机上输入相关的公式、
符号和等式等,就能很容易地算出代数、积分、三角以及很多科技领域
中复杂表达式的值;
(2) 显示数学表格和图形,使用户通过对图形结果的分析加深对有关问题的
理解.
当然不能因此而否定它们各自的重要性.事实上,它们各有千秋,各有各的
侧重点.比如:Mathematica 的数值运算和解析(符号)运算可以非常地精确;
MathCAD 7.0 专业版是可视化数学运算工具,用户输入的公式看上去就和黑板上
或在参考书上所见到的一模一样;Matlab 主要用于数值计算,计算速度十分快捷;
Maple 与 Mathematica 十分类似,可能在符号运算方面更有力一些.
由于时间及水平所限,本教材的编写不很全面,以后将进一步加以改进.要


说明的是:附录篇中 Maple 部分的内容由陈志杰教授提供;上海交通大学的彭勃
老师也提供了若干素材.在此一并表示感谢.

* * * * * *

在本教材第二版(即 Matlab 版)的编写过程中,得到了 2005 年度华东师范


大学大学生科研基金——《数学实验案例分析与 Matlab 的实现》项目的支持,来
自 2003 级的郑圣洁、陈继国、刘娜、章华彦等四位同学为本教材进行了若干程序
的设计、实现与调试.另外,在本教材第一版(即 Mathematica 版)的编写过程
中,也曾经得到 2000 年度华东师范大学大学生科研基金——《数学实验的设计与
实现》项目的支持,该科研小组的 1998 级的陈怡、张齐、吴栋、岳文权、张力蔚
等五位同学为本教材提供了若干数学实验的案例.另外有 1998 级的范黎斌、2000
级的赵喆同学也分别提供了一个数学实验案例,赵喆同学还在一些程序的完善方
面提出了良好的建议并提供了积极的帮助,在此一并对他们的工作表示感谢.
考虑到在数学实验中如何使用数学软件的问题,本教材在每个实验的开始列
出了相关的 Matlab 函数,并给出了简要的说明,这可能与软件篇中的内容有少量
重复,但对于理解和实现实验中的程序是非常有益的,特此说明.
通过教学,我们已经积累了若干教学素材,包括介绍 Matlab 的 16 个 ppt 文
件,讲解各个数学实验的 10 个 ppt 文件,以及部分练习题的参考解答等.读者可
通过有关网站获取,或联系有关作者获得.相信这些教学资料对您的学习或教学
会有一定的帮助作用.

作者联系方法:
万福永:fywan@math.ecnu.edu.cn
戴浩晖:hhdai@math.ecnu.edu.cn
潘建瑜:jypan@math.ecnu.edu.cn

相关资料下载网址:
http://math.ecnu.edu.cn/download/sxsyecnu.zip (注意:for Mathematica 版)
http://math.ecnu.edu.cn/download/sxsyecnu2.zip (注意:for Matlab 版)

2006 年 6 月


Matlab 用法简介

绪 论
Matlab 是“Matrix Laboratory”的缩写,意为“矩阵实验室”,是当今美国很流行的科
学计算软件.信息技术、计算机技术发展到今天,科学计算在各个领域得到了广泛的应用.在
许多诸如控制论、时间序列分析、系统仿真、图像信号处理等方面产生了大量的矩阵及其
相应的计算问题.自己去编写大量的繁复的计算程序,不仅会消耗大量的时间和精力,减
缓工作进程,而且往往质量不高.美国 Mathwork 软件公司推出的 Matlab 软件就是为了给
人们提供一个方便的数值计算平台而设计的.
Matlab 是一个交互式的系统,它的基本运算单元是不需指定维数的矩阵,按照 IEEE 的
数值计算标准(能正确处理无穷数 Inf(Infinity)、无定义数 NaN(not-a-number)及其运算)进
行计算.系统提供了大量的矩阵及其它运算函数,可以方便地进行一些很复杂的计算,而
且运算效率极高.Matlab 命令和数学中的符号、公式非常接近,可读性强,容易掌握,还
可利用它所提供的编程语言进行编程完成特定的工作.除基本部分外,Matlab 还根据各专
门领域中的特殊需要提供了许多可选的工具箱,如应用于自动控制领域的 Control System 工
具箱和神经网络中 Neural Network 工具箱等.

第一节 Matlab 的安装及使用

§1.1 Matlab 的安装


Matlab 有各种版本,早期有 Matlab 1.0 for 386 的 DOS 版本,后来逐步发展.这里介绍
的版本是 Matlab 6.x for Windows.因为它使用方便,界面美观,我们选择它作为主要讲解
版本.Matlab 还有许多附加的部分,最常见的部分称为 Simulink,是一个用作系统仿真的
软件包,它可以让您定义各种部件,定义各自对某种信号的反应方式及与其它部件的连接
方式.最后选择输入信号,系统会仿真运行整个模拟系统,并给出统计数据.Simulink 有时
是作为 Matlab 的一部分提供的,称为 Matlab with Simulink 版本.Matlab 还有许多工具箱,
它们是根据各个特殊领域的需要,用 Matlab 自身的语言编写的程序集,使用起来非常方
便.您可以视工作性质和需要购买相应的工具箱.常见的工具箱有:
Signal Process 信号处理 System Identification 系统辨识
Optimization 优化 Neural Network 神经网络
Control System 自动控制 Spline 样条
Symbolic Math 符号代数 Image Process 图像处理
Nonlinear Control 非线性控制 Statistics 统计

§1.2 Matlab 基本用法


从 Windows 中双击 Matlab 图标,会出现 Matlab 命令窗口(Command Window),在一
段提示信息后,出现系统提示符“>>”.Matlab 是一个交互系统,您可以在提示符后键入
各种命令,通过上下箭头可以调出以前打入的命令,用滚动条可以查看以前的命令及其输
出信息.
如果对一条命令的用法有疑问的话,可以用 Help 菜单中的相应选项查询有关信息,也
可以用 help 命令在命令行上查询,您可以试一下 help、help help 和 help eig(求特征值的函


数)命令.
下面我们先从输入简单的矩阵开始掌握 Matlab 的功能.

§1.2.1 输入简单的矩阵
输入一个小矩阵的最简单方法是用直接排列的形式.矩阵用方括号括起,元素之间用空
格或逗号分隔,矩阵行与行之间用分号分开.例如输入:
A=[1 2 3 ; 4 5 6 ; 7 8 0]
系统会回答
A=
1 2 3
4 5 6
7 8 0
表示系统已经接收并处理了命令,在当前工作区内建立了矩阵 A.
大的矩阵可以分行输入,用回车键代替分号,如:
A=[ 1 2 3
4 5 6
7 8 0]
结果和上式一样,也是
A=
1 2 3
4 5 6
7 8 0

§1.2.2 矩阵元素
Matlab 的矩阵元素可以是任何数值表达式.如:
x=[ -1.3 sqrt(3) (1+2+3)*4/5]
结果:
x=
-1.3000 1.7321 4.8000
在括号中加注下标,可取出单独的矩阵元素.如:
x(5)=abs(x(1))
结果
x=
-1.3000 1.7321 4.8000 0 1.3000
注:结果中自动产生了向量的第 5 个元素,中间未定义的元素自动初始为零.
大的矩阵可把小的矩阵作为其元素来完成,如:
A=[A; [10 11 12]]
结果
A=
1 2 3
4 5 6
7 8 0
10 11 12
小矩阵可用“:”从大矩阵中抽取出来,如:
A=A(1:3,:);
即从 A 中取前三行和所有的列,重新组成原来的 A. (详细介绍参见第二节的相关内容)

§1.2.3 语句和变量
Matlab 的表述语句、变量的类型说明由 Matlab 系统解释和判断.Matlab 语句通常形
式为:
变量=表达式
或者使用其简单形式为:


表达式
表达式由操作符或其它特殊字符、函数和变量名组成.表达式的结果为一个矩阵,显示
在屏幕上,同时保存在变量中以留用.如果变量名和“=”省略,则具有 ans 名(意思指回答)
的变量将自动建立.例如:
键入 1900/81
结果为:
ans =
23.4568
需注意的问题有以下几点:
 语句结束键入回车键,若语句的最后一个字符是分号,即“;”,则表明不输出当前
命令的结果.
 如果表达式很长,一行放不下,可以键入“…”(三个点,但前面必须有个空格,
目的是避免将形如“数 2 …”理解为“数 2.”与“..”的连接,从而导致错误),然
后回车.
 变量和函数名由字母加数字组成,但最多不能超过 63 个字符,否则系统只承认前
63 个字符.
 Matlab 变量字母区分大小写,如 A 和 a 不是同一个变量,函数名一般使用小写字
母,如 inv(A)不能写成 INV(A),否则系统认为未定义函数.

§1.2.4 who 和系统预定义变量


输入 who 命令可检查工作空间中建立的变量,键入:
who
系统输出为:
Your variables are:
A ans x
这里表明三个变量已由前面的例子产生了.
但列表中列出的并不是系统全部的变量,系统还有以下内部变量:
eps、pi、Inf、NaN
变量 eps 在决定诸如矩阵的奇异性时,可作为一个容许差,容许差的初值为 1.0 到 1.0
以后计算机所能表示的下一个最大浮点数,IEEE 在各种计算机、工作站和个人计算机上使
用这个算法.用户可将此值置为任何其它值(包括 0 值).Matlab 的内部函数 pinc 和 rank 以
eps 为缺省的容许差.
变量 pi 是,它是用 imag(log(-1))建立的.
Inf 表示无穷大.如果您想计算 1/0
S=1/0
结果会是
Warning:Divide by zero
S=Inf
具有 IEEE 规则的机器,被零除后,并不引出出错条件或终止程序的运行,而产生一个
警告信息和一个特殊值在计算方程中列出来.
变量 NaN 表示它是个不定值.由 Inf/Inf 或 0/0 运算产生.
要了解当前变量的信息请键入 whos,屏幕将显示:
Name Size Bytes Class
A 4x3 96 double array
S 1x1 8 double array
ans 1x1 8 double array
x 1x5 40 double array
Grand total is 19 elements using 152 bytes
从 size 及 bytes 项目可以看出,每一个矩阵实元素需 8 个字节的内存.4×3 的矩阵使用
96 个字节,全部变量的使用内存总数为 152 个字节.自由空间的大小决定了系统变量的多
少,如计算机上有虚拟内存的话,其可定义的变量个数会大大增加.


§1.2.5 数和算术表达式
Matlab 中数的表示方法和一般的编程语言没有区别.如:
3 -99 0.0001
9.63972 1.6021E-20 6.02252e23
在计算中使用 IEEE 浮点算法其舍入误差是 eps.浮点数表示范围是 10-308~10308.
数学运算符有:
+ 加
- 减
* 乘
/ 右除
\ 左除
^ 幂
这里 1/4 和 4\1 有相同的值都等于 0.25(注意比较:1\4=4).只有在矩阵的除法时左除
和右除才有区别.

§1.2.6 复数与矩阵
在 Matlab 中输入复数首先应该建立复数单位:
i=sqrt(-1)
及 j=sqrt(-1)
之后复数可由下面语句给出:
Z=3+4i (注意: 在 4 与 i 之间不要留有任何空间!)
输入复数矩阵有两个方便的方法,如:
A=[1 2; 3 4] + i*[5 6; 7 8]
和 A=[1+5i 2+6i; 3+7i 4+8i]
两式具有相等的结果.但当复数作为矩阵的元素输入时,不要留有任何空间,如 1+5i,
如在“+”号左右留有空格,就会被认为是两个分开的数.
不过实际使用复数时并没有这么麻烦,系统有一个名为 startup.m 的 Matlab 命令文件,
建立复数单位的语句也放在其中.当 Matlab 启动时,此文件自动执行,i 和 j 将自动建立.

§1.2.7 输出格式
任何 Matlab 语句执行结果都可在屏幕上显示,同时赋给指定的变量,没有指定变量时
赋给 ans.数字显示格式可由 format 命令来控制(Windows 系统下的 Matlab 系统的数字显
示格式可以由 Option 菜单中的 Numerical Format 菜单改变).format 仅影响矩阵的显示,不
影响矩阵的计算与存贮.(Matlab 以双精度执行所有的运算)
首先,如果矩阵元素是整数则矩阵显示就没有小数,如 x=[-1 0 1],结果为:
x=
-1 0 1
如果矩阵元素不是整数则输出形式有:(用命令:format 格式进行切换)
格式 中文解释 说明
format 短格式 Default. Same as SHORT
(缺省格式)
format short 短格式 Scaled fixed point format with 5 digits
(缺省格式) (只显示五位十进制数)
format long 长格式 Scaled fixed point format with 15 digits
format short e 短格式 e 方式 Floating point format with 5 digits
format long e 长格式 e 方式 Floating point format with 15 digits
format short g 短格式 g 方式 Best of fixed or floating point format with 5 digits
format long g 长格式 g 方式 Best of fixed or floating point format with 15 digits
format hex 16 进制格式 Hexadecimal format
format + +格式 The symbols +, - and blank are printed


for positive, negative and zero elements.
Imaginary parts are ignored
format bank 银行格式 Fixed format for dollars and cents
format rat 有理数格式 Approximation by ratio of small integers
format compact 压缩格式 Suppress extra line-feeds
format loose 自由格式 Puts the extra line-feeds back in
例如:
x=[4/3 1.2345e-6]
在不同的输出格式下的结果为:
短格式 1.3333 0.0000
短格式 e 方式 1.3333e+000 1.234e-006
长格式 1.333333333333333 0.000001234500000
长格式 e 方式 1.333333333333333e-000 1.23450000000000e-006
有理数格式 4/3 1/810045
16 进制格式 3ff5555555555555 3eb4b6231abfd271
+格式 + +
对于短格式,如果矩阵的最大元素比数 999999999 大,或者比数 0.0001 小,则在打印
时,将加入一个普通的长度因数.如 y=1.e20*x,意为 x 被 1020 乘,结果为:
y=
1.0e+020*
1.3333 0.0000
“+”格式是显示大矩阵的一种紧凑方法,“+”,“-”和空格显示正数、负数和零元素.
最后 format compact 命令压缩显示的矩阵,以允许更多的信息显示在屏幕上.

§1.2.8 Help 求助命令和联机帮助


Help 求助命令很有用,它对 Matlab 大部分命令提供了联机求助信息.您可以从 Help
菜单中选择相应的菜单,打开求助信息窗口查询某条命令,也可以直接用 help 命令.
键入 help
得到 help 列表文件,键入“help 指定项目”,如:
键入 help eig
则提供特征值函数的使用信息.
键入 help [
显示如何使用方括号等.
键入 help help
显示如何利用 help 本身的功能.
还有,键入 lookfor <关键字>:可以从 m 文件的 help 中查找有关的关键字.

§1.2.9 退出和存入工作空间
退出 Matlab 可键入 quit 或 exit 或选择相应的菜单.中止 Matlab 运行会引起工作空间
中变量的丢失,因此在退出前,应键入 save 命令,保存工作空间中的变量以便以后使用.
键入 save
则将所有变量作为文件存入磁盘 Matlab.mat 中,下次 Matlab 启动时,
键入 load
将变量从 Matlab.mat 中重新调出.
save 和 load 后边可以跟文件名或指定的变量名,如仅有 save 时,则只能存入 Matlab.mat
中.如 save temp 命令,则将当前系统中的变量存入 temp.mat 中去,命令格式为:
save temp x 仅仅存入 x 变量.
save temp X Y Z 则存入 X、Y、Z 变量.
load temp 可重新从 temp.mat 文件中提出变量,load 也可读 ASCII 数据文件.详细语法
见联机帮助.


第二节 向量与矩阵运算
Matlab 能处理数、向量和矩阵.但一个数事实上是一个 1×1 的矩阵,1 个 n 维向量也
不过是一个 1×n 或 n×1 的矩阵.从这个角度上来讲,Matlab 处理的所有的数据都是矩
阵.Matlab 的矩阵处理能力是非常灵活、强大的.以下我们将从矩阵的产生、基本运算、
矩阵函数等几个方面来说明.

§2.1 向量及矩阵的生成
除了我们在上节介绍的直接列出矩阵元素的输入方法,矩阵还可以通过几种不同的方式
输入到 Matlab 中.

§2.1.1 通过语句和函数产生
1. 向量的产生
除了直接列出向量元素(即所谓的“穷举法”)外,最常用的用来产生相同增量的向量
的方法是利用“:”算符(即所谓的“描述法”).在 Matlab 中,它是一个很重要的字符.如:
z=1:5
z=
1 2 3 4 5
即产生一个 1~5 的单位增量是 1 的行向量,此为默认情况.
用“:”号也可以产生单位增量不等于 1 的行向量,语法是把增量放在起始量和结尾量
的中间.如:
x=0:pi/4:pi
即产生一个由 0~pi 的行向量,单位增量是 pi/4=3.1416/4=0.7854.
x=
0 0.7854 1.5708 2.3562 3.1416
也可以产生单位增量为负数的行向量.如:
y=6:-1:1
y=
6 5 4 3 2 1
2. 矩阵的产生
Matlab 提供了一批产生矩阵的函数:
zeros 产生一个零矩阵 diag 产生一个对角矩阵
ones 生成全 1 矩阵 tril 取一个矩阵的下三角
eye 生成单位矩阵 triu 取一个矩阵的上三角
magic 生成魔术方阵 pascal 生成 PASCAL 矩阵
例如:
ones(3)
ans =
1 1 1
1 1 1
1 1 1
eye(3)
ans =
1 0 0
0 1 0
0 0 1
除了以上产生标准矩阵的函数外,Matlab 还提供了产生随机(向量)矩阵的函数 rand
和 randn,及产生均匀级数的函数 linspace、产生对数级数的函数 logspace 和产生网格的函数
meshgrid 等等.详细使用请查阅随机文档.
“ : ”冒号可以用来产生简易的表格,为了产生纵向表格形式,首先用冒号“ : ”产
生行向量,再进行转置,计算函数值的列,然后形成有二列的矩阵.例如命令:

10
x=(0.0:0.2:3.0)';
y=exp(-x).*sin(x);
[x y]
产生结果为:
ans =
0 0
0.2000 0.1627
0.4000 0.2610
0.6000 0.3099
0.8000 0.3223
1.0000 0.3096
1.2000 0.2807
1.4000 0.2430
1.6000 0.2018
1.8000 0.1610
2.0000 0.1231
2.2000 0.0896
2.4000 0.0613
2.6000 0.0383
2.8000 0.0204
3.0000 0.0070

§2.1.2 通过后缀为.m 的命令文件产生


如有文件 data.m,其中包括正文:
A=[ 1 2 3
456
7 8 0]
则用 data 命令执行 data.m,可以产生名为 A 的矩阵.

§2.2 矩阵操作
在 Matlab 中可以对矩阵进行任意操作,包括改变它的形式,取出子矩阵,扩充矩阵,
旋转矩阵等.其中最重要的操作符为“:”, 它的作用是取出选定的行与列.
例如:
A(:,:) 代表 A 的所有元素;试比较 A(:), 将 A 按列的方向拉成长长的 1 列(向量);
A(:,J) 代表 A 的第 J 列;
A(J:K) 代表 A(J), A(J+1), …, A(K),如同 A(:)的第 J 到第 K 个元素;
A(:,J:K) 代表 A(:,J), A(:,J+1), …, A(:,K),如此类推.
对矩阵可以进行各种各样的旋转、变形、扩充:
Matlab 中有内部函数 fliplr ( Flip matrix in the left/right direction),它对矩阵进行左右旋转.
例 x= 1 2 3 fliplr(x)为 3 2 1
4 5 6 6 5 4
同样有 flipud:
x= 1 4 flipud(x)为 3 6
2 5 2 5
3 6 1 4
矩阵的转置用符号“ ' ”表示:
如 A=[1 2 3; 4 5 6 ; 7 8 0]
那么:计算 B=A'
B=
1 4 7
2 5 8
3 6 0

11
符号“ ' ”为矩阵的转置,如果 Z 为复矩阵,则 Z'为它的复数共轭转置,非共轭转置
使用 Z.' 或 conj(Z')求得.
reshape 改变矩阵的形状,这是什么意思呢?可举一个例子来说明.
A=[A;[10 11 12]]
A=
1 2 3
4 5 6
7 8 0
10 11 12
则 reshape(A,2,6)
ans =
1 7 2 8 3 0
4 10 5 11 6 12
可见,reshape 是将矩阵元素以列为单位进行重组,原来 4×3 的矩阵变为了 2×6 的矩
阵.那么以下的语句也不难理解了,它将矩阵 A 按列打开(size 函数返回矩阵 A 的行数与
列数) .
reshape(A,1,size(A,1)*size(A,2)),它等价于 A(:)' .
还有函数 rot90,它可以将矩阵进行各种 90 度的旋转;tril 及 triu 取出矩阵的下三角及上
三角阵等.详细的用法可以在需要使用时查阅手册.

第三节 矩阵的基本运算

§3.1 加和减
如矩阵 A 和 B 的维数相同,则 A+B 与 A-B 表示矩阵 A 与 B 的和与差.如果矩阵 A 和
B 的维数不匹配,Matlab 会给出相应的错误提示信息.如:
A= B=
1 2 3 1 4 7
4 5 6 2 5 8
7 8 0 3 6 0
C =A+B 返回:
C=
2 6 10
6 10 14
10 14 0
如果运算对象是个标量(即 1×1 矩阵),可和其它矩阵进行加减运算.例如:
x= -1 y=x-1= -2
0 -1
2 1

§3.2 矩阵乘法
Matlab 中的矩阵乘法有通常意义上的矩阵乘法,也有 Kronecker 乘法,以下分别介绍.

§3.2.1 矩阵的普通乘法
矩阵乘法用“ * ”符号表示,当 A 矩阵列数与 B 矩阵的行数相等时,二者可以进行乘
法运算,否则是错误的.计算方法和线性代数中所介绍的完全相同.
如:A=[1 2 ; 3 4]; B=[5 6 ; 7 8]; C=A*B,
结果为

12
 1 2   5 6   1  5  2  7 1  6  2  8   19 22 
C=   ×   =   =  
 3 4   7 8   3  5  4  7 3  6  4  8   43 50 
即 Matlab 返回:
C=
19 22
43 50
如果 A 或 B 是标量,则 A*B 返回标量 A(或 B)乘上矩阵 B(或 A)的每一个元素所
得的矩阵.

§3.2.2 矩阵的 Kronecker 乘法


对 n×m 阶矩阵 A 和 p×q 阶矩阵 B,A 和 B 的 Kronecher 乘法运算可定义为:
 a11 B a12 B ... a1m B 
 
 a21 B a22 B ... a2 m B 
C  A B  
    
 
 a B a B ... a B 
 n1 n2 nm 

由上面的式子可以看出, Kronecker 乘积 A  B 表示矩阵 A 的所有元素与 B 之间的乘积


组合而成的较大的矩阵,B  A 则完全类似.A  B 和 B  A 均为 np×mq 矩阵,但一般情
况下 A  B  B  A.和普通矩阵的乘法不同,Kronecker 乘法并不要求两个被乘矩阵满足任
何维数匹配方面的要求.Kronecker 乘法的 Matlab 命令为 C=kron(A,B),例如给定两个矩阵
A 和 B:
 1 2  1 3 2
A=   B=  
 3 4  2 4 6
则由以下命令可以求出 A 和 B 的 Kronecker 乘积 C:
A=[1 2; 3 4]; B=[1 3 2; 2 4 6]; C=kron(A,B)
C=
1 3 2 2 6 4
2 4 6 4 8 12
3 9 6 4 12 8
6 12 18 8 16 24
作为比较,可以计算 B 和 A 的 Kronecker 乘积 D,可以看出 C、D 是不同的:
A=[1 2; 3 4]; B=[1 3 2; 2 4 6]; D=kron(B,A)
D=
1 2 3 6 2 4
3 4 9 12 6 8
2 4 4 8 6 12
6 8 12 16 18 24

§3.3 矩阵除法
在 Matlab 中有两种矩阵除法符号:“\”即左除和“/”即右除.如果 A 矩阵是非奇
异方阵,则 A\B 是 A 的逆矩阵乘 B,即 inv(A)*B;而 B/A 是 B 乘 A 的逆矩阵,即 B*inv(A).具
体计算时可不用逆矩阵而直接计算.
通常:
x=A\B 就是 A*x=B 的解;
x=B/A 就是 x*A=B 的解.
当 B 与 A 矩阵行数相等可进行左除.如果 A 是方阵,用高斯消元法分解因数.解方程:
A*x(:, j)=B(:, j),式中的(:, j)表示 B 矩阵的第 j 列,返回的结果 x 具有与 B 矩阵相同的阶数,
如果 A 是奇异矩阵将给出警告信息.
如果 A 矩阵不是方阵,可由以列为基准的 Householder 正交分解法分解,这种分解法可

13
以解决在最小二乘法中的欠定方程或超定方程,结果是 m×n 的 x 矩阵.m 是 A 矩阵的列
数,n 是 B 矩阵的列数.每个矩阵的列向量最多有 k 个非零元素,k 是 A 的有效秩.
右除 B/A 可由 B/A=(A'\B')'左除来实现.

§3.4 矩阵乘方
A^P 意思是 A 的 P 次方.如果 A 是一个方阵,P 是一个大于 1 的整数,则 A^P 表示 A
的 P 次幂,即 A 自乘 P 次.如果 P 不是整数,计算涉及到特征值和特征向量的问题,如已
经求得:[V,D]=eig(A),则:
A^P=V*D.^P/V(注:这里的.^表示数组乘方,或点乘方,参见后面的有关介绍)
如果 B 是方阵, a 是标量,a^B 就是一个按特征值与特征向量的升幂排列的 B 次方程
阵. 如果 a 和 B 都是矩阵,则 a^B 是错误的.

§3.5 矩阵的超越函数
在 Matlab 中解释 exp(A)和 sqrt(A)时曾涉及到级数运算,此运算定义在 A 的单个元素
上. Matlab 可以计算矩阵的超越函数,如矩阵指数、矩阵对数等.
一个超越函数可以作为矩阵函数来解释,例如将“m”加在函数名的后边而成 expm(A)
和 sqrtm(A),当 Matlab 运行时,有下列三种函数定义:
expm 矩阵指数
logm 矩阵对数
sqrtm 矩阵开方
所列各项可以加在多种 m 文件中或使用 funm.请见应用库中 sqrtm.m,1ogm.m,funm.m
文件和命令手册.

§3.6 数组运算
数组运算由线性代数的矩阵运算符“*”、“/”、“\”、“^”前加一点来表示,即为“.*”、
“./”、“.\”、“.^”.注意没有“.+”、“.-”运算.

§3.6.1 数组的加和减
对于数组的加和减运算与矩阵运算相同,所以“+”、“-”既可被矩阵接受又可被数组接
受.

§3.6.2 数组的乘和除
数组的乘用符号.*表示,如果 A 与 B 矩阵具有相同阶数,则 A.*B 表示 A 和 B 单个元素
之间的对应相乘.例如 x=[1 2 3]; y=[ 4 5 6];
计算 z=x.*y
结果 z=4 10 18
数组的左除(.\)与数组的右除(./),由读者自行举例加以体会.

§3.6.3 数组乘方
数组乘方用符号.^表示.
例如:键入:
x=[ 1 2 3]
y=[ 4 5 6]
则 z=x.^y=[1^4 2^5 3^6]=[1 32 729]
(1) 如指数是个标量,例如 x.^2,x 同上,则:
z=x.^2=[1^2 2^2 3^2]=[ 1 4 9]
(2) 如底是标量,例如 2 .^[x y] ,x、y 同上,则:
z=2 .^[x y]=[2^1 2^2 2^3 2^4 2^5 2^6]=[2 4 8 16 32 64]

14
从此例可以看出 Matlab 算法的微妙特性,虽然看上去与其它乘方没什么不同,但在 2
和“.”之间的空格很重要,如果不这样做,解释程序会把“.”看成是 2 的小数点. Matlab
看到符号“^”时,就会当做矩阵的幂来运算,这种情况就会出错,因为指数矩阵不是方阵.

§3.7 矩阵函数
Matlab 的数学能力大部分是从它的矩阵函数派生出来的,其中一部分装入 Matlab 本身
处理中,它从外部的 Matlab 建立的 M 文件库中得到,还有一些由个别的用户为其自己的
特殊的用途加进去的.其它功能函数在求助程序或命令手册中都可找到.手册中备有为
Matlab 提供数学基础的 LINPACK 和 EISPACK 软件包,提供了下面四种情况的分解函数或
变换函数:
(1)三角分解;(2)正交变换;(3) 特征值变换;(4)奇异值分解.

§3.7.1 三角分解
最基本的分解为“LU”分解,矩阵分解为两个基本三角矩阵形成的方阵,三角矩阵有
上三角矩阵和下三角矩阵.计算算法用高斯变量消去法.
从 lu 函数中可以得到分解出的上三角与下三角矩阵,函数 inv 得到矩阵的逆矩阵,det
得到矩阵的行列式.解线性方程组的结果由方阵的“\”和“/”矩阵除法来得到.
例如:
A=[ 1 2 3
4 5 6
7 8 0]
LU 分解,用 Matlab 的多重赋值语句
[L,U]=lu(A)
得出
L=
0.1429 1.0000 0
0.5714 0.5000 1.0000
1.0000 0 0
U=
7.0000 8.0000 0
0 0.8571 3.0000
0 0 4.5000
注:L 是下三角矩阵的置换,U 是上三角矩阵的正交变换,分解作如下运算,检测计算
结果只需计算 L*U 即可.
求逆由下式给出: x=inv(A)
x=
-1.777 0.8889 -0.1111
8
1.5556 -0.777 0.2222
8
-0.1111 0.2222 -0.1111
从 LU 分解得到的行列式的值是精确的,d=det(U)*det(L)的值可由下式给出:
d=det(A)
d=
27
直接由三角分解计算行列式:d=det(L)*det(U)
d=
27.0000
为什么两种 d 的显示格式不一样呢? 当 Matlab 做 det(A)运算时,所有 A 的元素都是整
数,所以结果为整数.但是用 LU 分解计算 d 时,L、U 的元素是实数,所以 Matlab 产生
的 d 也是实数.

15
例如:线性联立方程取 b=[ 1
3
5]
解 Ax=b 方程,用 Matlab 矩阵除得到
x=A\b
结果 x=
0.3333
0.3333
0.0000
由于 A=L*U,所以 x 也可以有以下两个式子计算:y=L\b,x=U\y.得到相同的 x 值,
中间值 y 为:
y=
5.0000
0.2857
0.0000
Matlab 中与此相关的函数还有 rcond、chol 和 rref.其基本算法与 LU 分解密切相关.chol
函数对正定矩阵进行 Cholesky 分解,产生一个上三角矩阵,以使 R'*R=X.rref 用具有部分
主元的高斯-约当消去法产生矩阵 A 的化简梯形形式.虽然计算量很少,但它是很有趣的
理论线性代数.为了教学的要求,也包括在 Matlab 中.

§3.7.2 正交变换
“QR”分解用于矩阵的正交-三角分解.它将矩阵分解为实正交矩阵或复酉矩阵与上
三角矩阵的积,对方阵和长方阵都很有用.
例如 A=[ 1 2 3
4 5 6
7 8 9
10 11 12]
是一个降秩矩阵,中间列是其它二列的平均,我们对它进行 QR 分解:
[Q,R]=qr(A)
Q=
-0.077 -0.833 0.5444 0.0605
6 1
-0.310 -0.451 -0.770 0.3251
5 2 9
-0.543 -0.069 -0.091 -0.831
3 4 3 7
-0.776 0.3124 0.3178 0.4461
2
R=
-12.884 -14.591 -16.299
1 6 2
0 -1.0413 -2.0826
0 0 0.0000
0 0 0
可以验证 Q*R 就是原来的 A 矩阵.由 R 的下三角都给出 0,并且 R(3,3)=0.0000,说明
矩阵 R 与原来矩阵 A 都不是满秩的.
下面尝试利用 QR 分解来求超定和降秩的线性方程组的解.
例如:
b=[ 1
3
5

16
7]
讨论线性方程组 Ax=b,我们可以知道方程组是超定的,采用最小二乘法的最好结果是
计算 x=A\b.
结果为:
Warning: Rank deficient, rank = 2 tol = 1.4594e-014
x=
0.5000
0
0.1667
我们得到了缺秩的警告.用 QR 分解法计算此方程组分二个步骤:
y=Q'*b
x=R\y
求出的 y 值为
y=
-9.1586
-0.3471
0.0000
0.0000
x 的结果为
Warning: Rank deficient, rank = 2 tol = 1.4594e-014
x=
0.5000
0
0.1667
用 A*x 来验证计算结果,我们会发现在允许的误差范围内结果等于 b.这告诉我们虽然
联立方程 Ax=b 是超定和降秩的,但两种求解方法的结果是一致的.显然 x 向量的解有无穷
多个,而“QR”分解仅仅找出了其中之一.

§3.7.3 奇异值分解
在 Matlab 中三重赋值语句
[U,S,V]=svd(A)
在奇异值分解中产生三个因数:
A=U*S*V '
U 矩阵和 V 矩阵是正交矩阵,S 矩阵是对角矩阵,svd(A)函数恰好返回 S 的对角元素,
而且就是 A 的奇异值(其定义为:矩阵 A'*A 的特征值的算术平方根).注意到 A 矩阵可以
不是方的矩阵.
奇异值分解可被其它几种函数使用,包括广义逆矩阵 pinv(A)、秩 rank(A)、欧几里德矩
阵范数 norm(A,2)和条件数 cond(A).

§3.7.4 特征值分解
如果 A 是 n×n 矩阵,若满足 Ax=x,则称为 A 的特征值,x 为相应的特征向量.
函数 eig(A)返回特征值列向量,如果 A 是实对称的,特征值为实数.特征值也可能为复
数,例如:
A=[ 0 1
-1 0]
eig(A)
产生结果
ans =
0 + 1.0000i
0 - 1.0000i
如果还要求求出特征向量,则可以用 eig(A)函数的第二个返回值得到:
[x,D]=eig(A)

17
D 的对角元素是特征值.x 的列是相应的特征向量,以使 A*x=x*D.
计算特征值的中间结果有两种形式:
Hessenberg 形式为 hess(A),Schur 形式为 schur(A).
schur 形式用来计算矩阵的超越函数,诸如 sqrtm(A)和 logm(A).
如果 A 和 B 是方阵,函数 eig(A,B)返回一个包含一般特征值的向量来解方程
Ax=Bx
双赋值获得特征向量
[X,D]=eig(A,B)
产生特征值为对角矩阵 D.满秩矩阵 X 的列相应于特征向量,使 A*X=B*X*D,中间结
果由 qz(A,B)提供.

§3.7.5 秩
Matlab 计算矩阵 A 的秩的函数为 rank(A),与秩的计算相关的函数还有:rref(A)、orth(A)、
null(A)和广义逆矩阵 pinv(A)等.
利用 rref(A),A 的秩为非 0 行的个数.rref 方法是几个定秩算法中最快的一个,但结果
上并不可靠和完善.pinv(A)是基于奇异值的算法.该算法消耗时间多,但比较可靠.其它
函数的详细用法可利用 Help 求助.

第四节 Matlab 中的图形

§4.1 二维作图
绘图命令 plot 绘制 x-y 坐标图;loglog 命令绘制对数坐标图;semilogx 和 semilogy 命令
绘制半对数坐标图;polor 命令绘制极坐标图.

§4.1.1 基本形式
如果 y 是一个向量,那么 plot(y)绘制一个 y 中元素的线性图.假设我们希望画出
y=[0., 0.48, 0.84, 1., 0.91, 6.14 ]
则用命令:plot(y)
它相当于命令:plot(x, y),其中 x=[1,2,…,n]或 x=[1;2;…;n],即向量 y 的下标编号, n 为
向量 y 的长度
Matlab 会产生一个图形窗口,显示如下图形,请注意:坐标 x 和 y 是由计算机自动绘
出的.
7

0
1 2 3 4 5 6

图 4.1.1.1 plot([0.,0.48,0.84,1.,0.91,6.14])

上面的图形没有加上 x 轴和 y 轴的标注,也没有标题.用 xlabel,ylabel,title 命令可以


加上.

18
如果 x,y 是同样长度的向量,plot(x,y)命令可画出相应的 x 元素与 y 元素的 x-y 坐标
图.例:
x=0:0.05:4*pi; y=sin(x); plot(x,y)
grid on, title(' y=sin( x ) 曲线图' )
xlabel(' x = 0 : 0.05 : 4Pi ')
结果见下图.
y=sin( x ) 曲线图
1

0.8

0.6

0.4

0.2

-0.2

-0.4

-0.6

-0.8

-1
0 2 4 6 8 10 12 14

x = 0 : 0.05 : 4Pi

图 4.1.1.2 y=sin(x)的图形

title 图形标题
xlabel x 坐标轴标注
ylabel y 坐标轴标注
text 标注数据点
grid 给图形加上网格
hold 保持图形窗口的图形
表 4.1.1.1 Matlab 图形命令

§4.1.2 多重线
在一个单线图上,绘制多重线有三种办法.
第一种方法是利用 plot 的多变量方式绘制:
plot(x1,y1,x2,y2,...,xn,yn)
x1,y1,x2,y2,...,xn,yn 是成对的向量,每一对 x, y 在图上产生如上方式的单线.多变量方
式绘图是允许不同长度的向量显示在同一图形上.
第二种方法也是利用 plot 绘制,但加上 hold on/off 命令的配合:
plot(x1,y1)
hold on
plot(x2,y2)
hold off
第三种方法还是利用 plot 绘制,但代入矩阵:
如果 plot 用于两个变量 plot(x,y),并且 x,y 是矩阵,则有以下情况:
(1)如果 y 是矩阵,x 是向量,plot(x,y)用不同的画线形式绘出 y 的行或列及相应的 x
向量,y 的行或列的方向与 x 向量元素的值选择是相同的.
(2)如果 x 是矩阵,y 是向量,则除了 x 向量的线族及相应的 y 向量外,以上的规则
也适用.
(3)如果 x,y 是同样大小的矩阵,plot(x,y)绘制 x 的列及 y 相应的列.
还有其它一些情况,请参见 Matlab 的帮助系统.

§4.1.3 线型和颜色的控制
如果不指定划线方式和颜色,Matlab 会自动为您选择点的表示方式及颜色.您也可以
用不同的符号指定不同的曲线绘制方式.例如:
plot(x,y,'*') 用'*'作为点绘制的图形.

19
plot(x1,y1,':',x2,y2,'+') 用':'画第一条线,用'+'画第二条线.
线型、点标记和颜色的取值有以下几种:
线型 点标记 颜色
- 实线 . 点 y 黄
: 虚线 o 小圆圈 m 棕色
-. 点划线 x 叉子符 c 青色
-- 间断线 + 加号 r 红色
* 星号 g 绿色
s 方格 b 蓝色
d 菱形 w 白色
^ 朝上三角 k 黑色
v 朝下三角
> 朝右三角
< 朝左三角
p 五角星
h 六角星
表 4.1.3.1 线型和颜色控制符
如果你的计算机系统不支持彩色显示,Matlab 将把颜色符号解释为线型符号,用不同
的线型表示不同的颜色.颜色与线型也可以一起给出,即同时指定曲线的颜色和线型.
例如: t=-3.14:0.2:3.14;
x=sin(t); y=cos(t);
plot(t,x, '+r',t,y, '-b')
1

0.5

-0.5

-1
-4 -2 0 2 4

图 4.1.3.1 不同线型、颜色的 sin,cos 图形

§4.1.4 对数图、极坐标图及条形图

loglog、semilogx、semilogy 和 polar 的用法和 plot 相似.这些命令允许数据在不同的 graph


paper 上绘制,例如不同的坐标系统.先介绍的 fplot 是扩展来的可用于符号作图的函数.

 fplot(fname,lims) 绘制 fname 指定的函数的图形.


 polar( theta, rho) 使用相角 theta 为极坐标形式绘图,相应半径为 rho,其次可使用
grid 命令画出极坐标网格.
 loglog 用 log10-log10 标度绘图.
 semilogx 用半对数坐标绘图,x 轴是 log10,y 是线性的.
 semilogy 用半对数坐标绘图,y 轴是 log10,x 是线性的.
 bar(x) 显示 x 向量元素的条形图,bar 不接受多变量.
 hist 绘制统计频率直方图.
 histfit(data,nbins) 绘制统计直方图与其正态分布拟合曲线.

fplot 函数的绘制区域为 lims=[xmin,xmax],也可以用 lims=[xmin,xmax,ymin,ymax]指定 y


轴的区域.函数表达式可以是一个函数名,如 sin,tan 等;也可以是带上参数 x 的函数表达

20
式,如 sin(x),diric(x,10);也可以是一个用方括号括起的函数组,如[sin, cos].
例 1:fplot('sin',[0 4*pi])
例 2:fplot('sin(1 ./ x)', [0.01 0.1])
例 3:fplot('abs(exp(-j*x*(0:9))*ones(10,1))',[0 2*pi],'-o')
例 4:fplot('[sin(x), cos(x) , tan(x)]',[-2*pi 2*pi -2*pi 2*pi]) %%(图 4.1.4.1)

6 30

4
20
2

0 10

-2
0
-4

-6 -10
-6 -4 -2 0 2 4 6 -4 -2 0 2
10 10 10 10

图 4.1.4.1 sin,cos,tan 函数图形 图 4.1.4.2 半对数图

下面介绍的是其它几个作图函数的应用.
例 5:半对数坐标绘图
t=0.001:0.002:20;
y=5 + log(t) + t;
semilogx(t,y, 'b')
hold on
semilogx(t,t+5, 'r') %% (图 4.1.4.2)

例 6:极坐标绘图
t=0:0.01:2*pi;
polar(t,sin(6*t)) %% (图 4.1.4.3)

图 4.1.4.3 极坐标绘图 图 4.1.4.4 正态分布的统计直方图与其正态分布拟合曲线

例 7:正态分布图
我们可以用命令 normrnd 生成符合正态分布的随机数.
normrnd(u,v,m,n)
其中,u 表示生成随机数的期望,v 代表随机数的方差.
运行:
a=normrnd(10,2,10000,1);
histfit(a) %% (图 4.1.4.4)
我们可以得到正态分布的统计直方图与其正态分布拟合曲线.

例 8:比较正态分布(图 4.1.4.5(1))与平均分布(图 4.1.4.5(2))的分布图:

21
yn=randn(30000,1); %% 正态分布
x=min(yn) : 0.2 : max(yn);
subplot(121)
hist(yn, x)
yu=rand(30000,1); %% 平均分布
subplot(122)
hist(yu, 25)
2 5 0 0 1 4 0 0

1 2 0 0
2 0 0 0

1 0 0 0

1 5 0 0
8 0 0

6 0 0
1 0 0 0

4 0 0

5 0 0
2 0 0

0 0
-5 0 5 0 0 .5 1

4.1.4.5(1) 4.1.4.5(2)

图 4.1.4.5 正态分布与平均分布的分布图

§4.1.5 子图
在绘图过程中,经常要把几个图形在同一个图形窗口中表现出来,而不是简单地叠加
(例如上面的例 8) .这就用到函数 subplot.其调用格式如下:
subplot(m,n,p)
subplot 函数把一个图形窗口分割成 m×n 个子区域,用户可以通过参数 p 调用个各子绘
图区域进行操作.子绘图区域的编号为按行从左至右编号.

例 9:绘制子图
x=0:0.1*pi:2*pi;
subplot(2,2,1)
plot(x,sin(x),'-*');
title('sin(x)');
subplot(2,2,2)
plot(x,cos(x),'--o');
title('cos(x)');
subplot(2,2,3)
plot(x,sin(2*x),'-.*');
title('sin(2x)');
subplot(2,2,4);
plot(x,cos(3*x),':d')
title('cos(3x)')
得到图形如下:

22
sin(x) cos(x)
1 1

0.5 0.5

0 0

-0.5 -0.5

-1 -1
0 2 4 6 8 0 2 4 6 8

sin(2x) cos(3x)
1 1

0.5 0.5

0 0

-0.5 -0.5

-1 -1
0 2 4 6 8 0 2 4 6 8

图 4.1.5.1 子图

§4.1.6 填充图
利用二维绘图函数 patch,我们可绘制填充图.绘制填充图的另一个函数为 fill.
下面的例子绘出了函数 humps(一个 Matlab 演示函数)在指定区域内的函数图形.
例 10:用函数 patch 绘制填充图
fplot('humps',[0,2],'b')
hold on
patch([0.5 0.5:0.02:1 1],[0 humps(0.5:0.02:1) 0],'r');
hold off
title('A region under an interesting function.')
grid

图 4.1.6.1 填充图

我们还可以用函数 fill 来绘制类似的填充图.


例 11:用函数 fill 绘制填充图

23
x=0:pi/60:2*pi;
y=sin(x);
x1=0:pi/60:1;
y1=sin(x1);
plot(x,y,'r');
hold on
fill([x1 1],[y1 0],'g')

图 4.1.6.2 填充图

§4.2 三维作图

§4.2.1 mesh(Z)语句
mesh(Z)语句可以给出矩阵 Z 元素的三维消隐图,网络表面由 Z 坐标点定义,与前面叙
述的 x-y 平面的线格相同,图形由邻近的点连接而成.它可用来显示用其它方式难以输出的
包含大量数据的大型矩阵,也可用来绘制 Z 变量函数.
显示两变量的函数 Z=f(x,y),第一步需产生特定的行和列的 x-y 矩阵.然后计算函数在
各网格点上的值.最后用 mesh 函数输出.
下面我们绘制 sin(r)/r 函数的图形.建立图形用以下方法:
x=-8:.5:8;
y=x';
x=ones(size(y))*x;
y=y*ones(size(y))';
R=sqrt(x.^2+y.^2)+eps;
z=sin(R)./R;
mesh(z) %% 试运行 mesh(x,y,z),看看与 mesh(z)有什么不同之处?
各语句的意义是:首先建立行向量 x,列向量 y;然后按向量的长度建立 1-矩阵;用向
量乘以产生的 1-矩阵,生成网格矩阵,它们的值对应于 x-y 坐标平面;接下来计算各网格
点的半径;最后计算函数值矩阵 Z.用 mesh 函数即可以得到图形.

24
图 4.2.1 三维消隐图
第一条语句 x 的赋值为定义域,在其上估计函数;第三条语句建立一个重复行的 x 矩阵,
第四条语句产生 y 的响应,第五条语句产生矩阵 R(其元素为各网格点到原点的距离).用
mesh 方法结果如上.
另外,上述命令系列中的前 4 行可用以下一条命令替代:
[x, y]=meshgrid(-8:0.5:8)

§4.2.2 与 mesh 相关的几个函数


(1) meshc 与函数 mesh 的调用方式相同,只是该函数在 mesh 的基础上又增加了绘制相
应等高线的功能.下面来看一个 meshc 的例子:
[x,y]=meshgrid([-4:.5:4]);
z=sqrt(x.^2+y.^2);
meshc(z) %% 试运行 meshc(x,y,z),看看与 meshc(z)有什么不同之处?
我们可以得到图形:

图 4.2.2.1 meshc 图

地面上的圆圈就是上面图形的等高线.
(2) 函数 meshz 与 mesh 的调用方式也相同,不同的是该函数在 mesh 函数的作用之上增
加了屏蔽作用,即增加了边界面屏蔽.例如:
[x,y]=meshgrid([-4:.5:4]);
z=sqrt(x.^2+y.^2);
meshz(z) %% 试运行 meshz(x,y,z),看看与 meshz(z)有什么不同之处?
我们得到图形:

25
图 4.2.2.2 meshz 图

§4.2.3 其它的几个三维绘图函数
(1) 在 Matlab 中有一个专门绘制圆球体的函数 sphere,其调用格式如下:
[x,y,z]=sphere(n)
此函数生成三个(n+1)×(n+1)阶的矩阵,再利用函数 surf(x,y,z)可生成单位球面.
[x,y,z]=sphere 此形式使用了默认值 n=20
sphere(n) 只绘制球面图,不返回值.
运行下面程序:
sphere(30);
axis square;
我们得到球体图形:

图 4.2.3.1 球面图

若只输入 sphere 画图,则是默认了 n=20 的情况.

(2) surf 函数也是 Matlab 中常用的三维绘图函数.其调用格式如下:


surf(x,y,z,c)
输入参数的设置与 mesh 相同,不同的是 mesh 函数绘制的是一网格图,而 surf 绘制的
是着色的三维表面.Matlab 语言对表面进行着色的方法是,在得到相应网格后,对每一网

26
格依据该网格所代表的节点的色值(由变量 c 控制),来定义这一网格的颜色.若不输入 c,
则默认为 c=z.
我们看下面的例子:
%绘制地球表面的气温分布示意图.
[a,b,c]=sphere(40);
t=abs(c); %求绝对值
surf(a,b,c,t);
axis equal
colormap('hot')
我们可以得到图形如下:

图 4.2.3.2 等温线示意图

§4.2.4 图形的控制与修饰
(1) 坐标轴的控制函数 axis,调用格式如下:
axis([xmin,xmax,ymin,ymax,zmin,zmax])
用此命令可以控制坐标轴的范围.
与 axis 相关的几条常用命令还有:
axis auto 自动模式,使得图形的坐标范围满足图中一切图元素
axis equal 严格控制各坐标的分度使其相等
axis square 使绘图区为正方形
axis on 恢复对坐标轴的一切设置
axis off 取消对坐标轴的一切设置
axis manual 以当前的坐标限制图形的绘制

(2)grid on 在图形中绘制坐标网格.
grid off 取消坐标网格.

(3)xlabel, ylabel, zlabel 分别为 x 轴, y 轴, z 轴添加标注.title 为图形添加标题.


以上函数的调用格式大同小异,我们以 xlabel 为例进行介绍:
xlabel('标注文本','属性 1','属性值 1','属性 2','属性值 2',…)
这里的属性是标注文本的属性,包括字体大小、字体名、字体粗细等.

27
例如:
[x, y]=meshgrid(-4:.2:4);
R=sqrt(x.^2+y.^2);
z=-cos(R);
mesh(x,y,z)
xlabel('x\in[-4,4]','fontweight','bold');
ylabel('y\in[-4,4]','fontweight','bold');
zlabel('z=-cos(sqrt(x^2+y^2))','fontweight','bold');
title('旋转曲面','fontsize',15,'fontweight','bold','fontname','隶书');

图 4.2.4.1 添加标注

以上各种绘图方法的详细用法,请看联机信息.

§4.3 统计回归图
对平面上 n 个点: ( x1 , y1 ), ( x2 , y2 ), , ( xn , yn ),
在平面直线族{ y  a  bx | a, b 为实数}中寻求一条直线 y  a 0  b0 x ,使得散点到与散
点相对应的在直线上的点之间的纵坐标的误差的平方和最小,用微积分的方法可得:
x y  x y
i i i i
n  xi y i  ( x i )( y i ) n n n
b0  2 2
 2
n  x  (  xi )
i   xi   xi2
  
 n  n
 

a0 
y i
 b0
x i
 y  b0 x
n n

所求得的这条直线: y  a 0  b0 x 称为回归直线.
例:已知如下点列,求其回归直线,并计算最小误差平方和.
x 0.1 0.11 .12 .13 .14 .15 .16 .17 .18 .2 .21 .23
y 42 43.5 45 45.5 45 47.5 49 53 50 55 55 60
参考的程序如下:
x=[0.1 0.11 .12 .13 .14 .15 .16 .17 .18 .2 .21 .23];

28
y=[42 43.5 45 45.5 45 47.5 49 53 50 55 55 60];
n=length(x);
xb=mean(x);
yb=mean(y);
x2b=sum(x.^2)/n;
xyb=x*y'/n;
b=(xb*yb-xyb)/(xb^2-x2b);
a=yb-b*xb;
y1=a+b.*x;
plot(x,y,'*',x,y1);
serror=sum((y-y1).^2)

图 4.3.1 回归直线

第五节 Matlab 编程

§5.1 关系运算

§5.1.1 比较运算
比较两个同阶矩阵有下面六种相关操作符:
相关操作符
< 小于
<= 小于等于
> 大于
>= 大于等于
== 等于
~= 不等于
表 5.1.1.1 相关操作符
比较两个元素的大小,结果是“1”表明为真,结果是“0”表明为假.
例如 2+2~=4
结果是“0” ,表明为假.
例如一个 6 阶魔术方阵,矩阵元素计算满足各种条件:

29
A=magic(6)
ans =
35 1 6 26 19 24
3 32 7 21 23 25
31 9 2 22 27 20
8 28 33 17 10 15
30 5 34 12 14 16
4 36 29 13 18 11
阶数为 n 的魔术方阵,即 n×n 矩阵,是由 1~n2 的整数组成(n=6).仔细观察这个矩阵,
我们会发现任何行和、任何列和都相等.另外,每个 3×3 子行列式的对角线元素和,都可
被 3 整除.为了显示这一特性,键入:
p=(rem(A,3)==0)
p=
0 0 1 0 0 1
1 0 0 1 0 0
0 1 0 0 1 0
0 0 1 0 0 1
1 0 0 1 0 0
0 1 0 0 1 0
为了再仔细地观察这个模式,可以用 format+格式画出矩阵的压缩格式.此格式用“+”
代表正元素, “-”代表负元素,空格代表 0.
format +
p=
+ +
+ +
+ +
+ +
+ +
+ +
find 函数在关系运算中很有用,它可以在 0-1 矩阵中找非零元素的下标.
若 y 是一个向量,例如:y=[1 3 2 4 3.5 2.9],则 find(y<3.0),将指出 y 的
分量在哪些位置上小于 3.0.
ans = 1 3 6
即:向量 y 的第 1、3、6 位置上的元素小于 3.0.
当输入 x==NaN 时结果为 NaN,因为按照 IEEE 算法规定任何具有 NaN 的操作,结果
都是 NaN.调试 NaN 很有用,例如测试 x,输入 isnan(x)函数,如果 x 元素是不定值则得 1,
否则得 0.isfinite(x)更有用,如-<x<时则得 1.

§5.1.2 逻辑运算
& 与
| 或
~ 非
表 5.1.2.1 逻辑运算符

“&”和“|”操作符可比较两个标量或两个同阶矩阵.对于矩阵来说必须符合规则,
如果 A 和 B 都是 0-1 矩阵,则 A&B 或 A|B 也都是 0-1 矩阵,这个 0-1 矩阵的元素是 A 和 B
对应元素之间逻辑运算的结果,逻辑操作符认定任何非零元素都为真,给出“1”,任何零
元素都为假,给出“0” .
非(或逻辑非)是一元操作符,即~A:当 A 是非零时结果为“0”;当 A 为“0”时,结果
为“1” .因此下列两种表示:
p | (~p) 结果为 1.
p & (~p) 结果为 0.

30
any 和 all 函数在连接操作时很有用,设 x 是 0-1 向量,如果 x 中任意有一元素非零时,
any(x)返回“1” ,否则返回“0”;all(x)函数当 x 的所有元素非零时,返回“1”,否则也返回
“0” .这些函数在 if 语句中经常被用到.如:
if all(A<5)
do something
end

§5.2 控制流
Matlab 与其它计算机语言一样,也有控制流语句.控制流语句可使原本简单地在命令
行中运行的一系列命令或函数,组合成为一个整体——程序,从而提高工作效率.

§5.2.1 for 循环
Matlab 与其它计算机语言一样有 do 或 for 循环,完成一个语句或一组语句在一定时间
内反复运行的功能.例如:
for i = 1:n , x( i )=0, end
x 的第一个元素赋 0 值,如果 n<1,结构上合法,但内部语句不运行,如果 x 不存在或
比 n 元素小,额外的空间将会自动分配.
多重循环写成锯齿形是为了增加可读性.例如:
m=9;n=9;
for i = 1:m
for j=1:n
A( i, j ) = 1/( i + j - 1);
end
end
A
程序的说明:
(1)事实上,上述程序给出了 Hilbert 矩阵的构造过程,可参见函数 hilb(n).
(2)语句内部使用分号,表示计算过程不输出中间结果.
(3)循环后的 A 命令表示显示矩阵 A 的结果.
(4)每个 for 语句必须以 end 语句结束,否则是错误的.
for 循环的通用形式为:
for v=expression
statements
end
其中 expression 表达式是一个矩阵,因为 Matlab 中都是矩阵,矩阵的列被一个接一个
的赋值到变量 v,然后 statements 语句运行.
通常 expression 是一些 m:n 或 m:k:n 仅有一行的矩阵,并且它的列是个简单的标量.但
如注意到 expression 可以为矩阵,即 v 可以为向量,对某些问题的处理将大大简化.

§5.2.2 while 循环
Matlab 中的 while 循环语句为一个语句或一组语句在一个逻辑条件的控制下重复未知
的次数.
它的一般形式为:
while expression
statements
end
当 expression 的所有运算为非零值时,statements 语句组将被执行.如果判断条件是向量
或矩阵的话,可能需要 all 或 any 函数作为判断条件.
例如计算 expm(A),在 A 并不是太大时,直接计算 expm(A)是可行的.
expm(A)=I+A+A^2/2!+A^3/3!+… 注意:这里的 I 表示单位矩阵.
程序为:

31
E = 0*A; F = E + eye(size(E)); N = 1;
while norm(F,1) > 0,
F = A*F/N;
E = E + F;
N = N + 1;
end

§5.2.3 if 和 break 语句
下面介绍 if 语句的二个例子.
(1) 一个计算如何被分成三个部分,用符号校验:
if n<0
A=negative(n)
elseif mod(n,2)==0
A=even(n)
else
A=odd(n)
end
其中的三个函数 negative(n)、even(n)、odd(n)是自编的输出函数.参见下面的函数文件.

(2) 这个例子涉及数论中一个很有趣的问题,取任何的正整数,如果是偶数,用 2 除;
如果是奇数,用 3 乘,并加上 1,反复这个过程,直到你的整数成为 1.这个极有趣不可解
的问题是:有使这个过程不中止的整数吗?
%classic "3n+1"problem from number theory
while 1
n=input('Enter n, negative quits: ');
if n<=0 break,end
while n>1
if rem(n,2) == 0 %% 是连续的 2 个等号
n=n/2
else
n=3*n+1
end;
end
end
这个过程能永远进行吗?
程序的说明:
(1)本程序用到了 if 语句与 while 语句,过程比较复杂;
(2)使用 input 函数,可使程序在执行过程中,从键盘输入一个数(矩阵);
(3)break 语句提供了程序跳出死循环的途径.

§5.3 M 文件、命令文件及函数文件

§5.3.1 M 文件
Matlab 通常使用命令驱动方式,当单行命令输入时,Matlab 立即处理并显示结果,同
时将运行说明或命令存入文件.
Matlab 语句的磁盘文件称作 M 文件,因为这些文件名的未尾是.M 形式,例如一个文件
名为 bessel.m,提供 bessel 函数语句.
一个 M 文件包含一系列的 Matlab 语句,一个 M 文件可以循环地调用它自己.
M 文件有两种类型:
第一类型的 M 文件称为命令文件,它是一系列命令、语句的简单组合.
第二类型的 M 文件称为函数文件,它提供了 Matlab 的外部函数.用户为解决一个特定

32
问题而编写的大量的外部函数可放在 Matlab 工具箱中,这样的一组外部函数形成一个专用
的软件包.
这两种形式的 M 文件,无论是命令文件,还是函数文件,都是普通的 ASCII 文本文件,
可选择编辑或字处理文件来建立.

§5.3.2 命令文件
当一个命令文件被调用时,Matlab 运行文件中出现的命令而不是交互地等待键盘输入,
命令文件的语句在工作空间中运算全局数据,对于进行分析解决问题及做设计中所需的一
长串繁杂的命令和解释是很有用的.
例如:一个自编的命令文件 fibo.m,用于计算 Fibonnaci 数列
% An M-file to calculate Fibonnaci numbers
f=[1, 1 ]; i = 1;
while f(i)+f(i+1)<1000
f(i+2)=f(i)+f(i+1);
i=i+1;
end
plot(f)
在 Matlab 命令窗口中键入 fibo 命令,并回车执行,将计算出所有小于 1000 的 Fibonnaci
数,并绘出图形.
要注意的是:文件执行后,f 和 i 变量仍然留在工作空间.

§5.3.3 函数文件
如果 M 文件的第一行包含 function,这个文件就是函数文件,它与命令文件不同,所定
义变量和运算都在文件内部,而不在工作空间.函数被调用完毕后,所定义变量和运算将
全部释放.函数文件对扩展 Matlab 函数非常有用.
例如:一个自编的函数文件 mean.m,用于求向量的(或矩阵按列的)平均值
function y=mean(x)
% MEAN Average or mean value,For Vectors,
% MEAN (x) returns the mean value
% For matrix MEAN (x) is a row vector
% containing the mean value of each column
[m,n]=size(x);
if m==1
m=n;
end
y=sum(x)/m;
磁盘文件中定义的新函数称为 mean 函数,它与 Matlab 函数一样使用,例如 z 为从 1
到 99 的实数向量:
z=1:99;
计算均值:mean(z)
ans=
50
mean.m 程序的说明:
(1)第一行的内容:函数名,输入变量,输出变量,没有这行这个文件就是命令文件,
而不是函数文件.
(2)%:表明%右边的行是说明性的内容注释.前一小部分行来确定 M 文件的注释,
并在键入 help mean 后显示出来.显示内容为连续的若干个%右边的文字.
(3)变量 m,n 和 y 是 mean 的局部变量,在 mean 运行结束后,它们将不在工作空间 z
中存在.如果在调用函数之前有同名变量,先前存在的变量及其当前值将不会改变.

再例如:一个计算标准差的函数文件 stat.m
function [mean,stdev]=stat(x)

33
[m,n]=size(x);
if m==1
m=n
end
mean=sum(x)/m;
stdev=sqrt(sum(x.^2)/m-mean.^2);
stat 表明返回多输出变量是可能的.

又如:使用多输入变量计算矩阵秩函数
function r=rank(x,tol)
% rank of a matrix
s=svd(x);
if(nargin==1)
tol=max(size(x))*s(1)*eps;
end
r=sum(s>tol);
这个变量说明利用永久变量 nargin 确定输入变量的个数,变量 nargout 虽然这里没有使
用,但它包含有输出变量的个数.
一些有用的说明:
当 M 函数文件第一次在 Matlab 运行时,它被编译并放入内存,以后使用时不用重新编
译即可得到.
what 命令:显示磁盘当前目录中的 M 文件,
dir 命令:列出所有文件.
一般而言,输入一个名字到 Matlab,例如键入 whoopie 命令,Matlab 用以下步骤解释:
(1) 看 whoopie 是否为变量.
(2) 检验 whoopie 是否为在线函数.
(3) 检验 whoopie 文件的当前目录.
(4) 将 whoopie 看成 Matlab 的 PATH 中的一个文件,在 Matlab PATH 目录中搜索.
如果 whoopie 存在,Matlab 首先将其作为变量而不是作为函数.

§5.4 字符串、输入及输出

§5.4.1 echo、input、pause、keyboard
一般来说,当一个 M 文件运行时,文件的命令不在屏幕上显示,而 echo 命令则使 M 文
件运行时,命令在屏幕上显示,这对于调试、演示相当有用.
input 功能:输入 Input('How many apples')给用户一个提示串,等待,然后显示用户通过
键盘输入的大量表达式.可以用 input 命令建立驱动 M 文件的菜单.
与 input 功能相同,但功能更强的 keyboard 命令将计算机作为一个命令文件来调用,放
入 M 文件中,此特性对调试或正在运行期间修改变量很有用.
pause 命令:使用户暂停运行一个程序,当再按任一键时恢复执行,pause(n)等待 n 秒钟
后再继续执行.

§5.4.2 串和宏串
字符串用单个引号输入到 Matlab 中,例如:
s='Hello'
结果显示为:
s=
Hello
字符存在向量中,每个元素就是一个字符,如:
size(s)
ans =

34
1 5
表明 S 为一个 1×5 的矩阵,有五个元素.字符以 ASCII 值存入,abs 函数或 double 函
数将显示以下值(即 Hello 的 ASCII 值)
abs(s)
ans =
72 101 108 108 111
getstr 函数,使向量作为字符显示,而不显示 ASCII 值.
disp 可在变量中显示字符.sprintf, num2str 和 int2str 可以将数字转换成串.
字符变量通过括号连成大串.例如:
s='hello';
s=[s,' world']
s=
hello world
eval 是与字符变量—起工作的函数,执行简单字符宏调用.eval( t )执行包含在 t 内的字
符.如果 t 是任何 Matlab 表达式或语句的源字符,则字符串被解释执行.例如:
t='eye(2)', eval(t)
结果为:
ans=
1 0
0 1
又例如,给矩阵元素赋值
t='1/(i+j-1)';
for i=1:n
for j=1:n
a( i, j)=eval(t);
end
end
这儿有一个例子,介绍如何一起使用 eval 与 load 命令,装入十个具有顺序文件名的文
件中的数据:
fname='mydata';
for i = 1:10
eval([ 'load ', fname, int2str( i )])
end

§5.4.3 外部程序
Matlab 与外部独立程序的通讯方式可以是多种多样的,下面介绍其中的一个办法:
(1) Matlab 中将变量存入磁盘
(2) 运行外部程序(读数据文件,进行处理),将结果写到磁盘上
(3) 将处理后的文件装回到工作空间中
例如:用外部程序 gareqn 找 garfield 方程的结果:
function y=garfield(a,b,q,r)
save gardata a,b,q,r
! gareqn
load gardata
使用 FORTRAN 或其它语言写 gareqn 程序,使其可以读 gardata.mat,进行处理,将结果
存入文件中.
这个程序可将计算机的“连接码”提供给 Matlab,在许多系统中它将新的目标码连接
到程序中比物理联接要方便得多.

§5.4.4 输入输出数据
可使用各种方法将其它程序和外部世界的数据送入 Matlab,同样可把 Matlab 数据输送
到外部世界,使你的程序以 Matlab 使用的文件形式直接计算数据.

35
最好的方法取决于多少数据,数据是否可读,什么形式等:
(1) 清晰的元素表输入:
如果你有少量数据,比如说小于 10~15 个元素,使用方括号[]输入.
(2) 使用文本编辑建立命令文件,将数据列为清晰的元素表输入.如果数据不是可读形
式,又不得不以一种方法键入,可以重复运行 M 文件,重复修改数据.
(3) 如果数据以 ASCII 形式存贮,并有固定长度,行尾有回车符,各数间有空格的文件
称为 flat file(ASCII 的 flat file 可由普通文本编辑来编辑),flat file 通过 load 命令直接读进
Matlab,结果存入名为文件名的变量中去.
(4) 将数据文件译成 Matlab 文件形式,使用 load 命令,translate 程序由 Matlab 中的应
用程序库支持,translate 程序将 ASCII 文件、二进制文件、FORTRAN 非格式文件和 DIF 文
件转换为 Matlab 使用的特定的 MAT 文件,当磁盘文件中存有大量数据时,这个方法输入
最好.
Matlab 数据输出到外部世界的方法:
(1) 小矩阵时:使用 diary 命令建立日志文件,在文件中列出变量,用文本编辑处理日
志文件,日志的输出包括运行中的 Matlab 命令.
(2) 使用 save 命令存入变量,退出 Matlab,用 translate 程序将 MAT 文件转换成任一种
其它文件形式.

第六节 Matlab 符号运算

Matlab 本身并没有符号计算功能,1993 年通过购买 Maple 的使用权后,开始具备符号


运算的功能.符号运算的类型很多,几乎涉及数学的所有分支.

§6.1 Matlab 符号运算的工作流程

§6.1.1 工作过程

§6.1.2 核心工具
sym 函数 VS syms 语句
sym 函数:构造符号变量和表达式: a=sym('a')
(Construct symbolic numbers, variables and objects)
syms 语句:构造符号对象的简捷方式(Short-cut for constructing symbolic objects)

§6.1.3 符号变量确定原则
(1)除了 i 和 j 之外,字母位置最接近 x 的字母;若距离相等,则取 ASCII 码大的;
(2)若没有除了 i 与 j 以外的字母,则视 x 为默认的符号变量;
(3)可利用函数 findsym(string,N)来询问在众多符号中,哪 N 个为符号变量.例如:键
入 findsym(3*a*b+y^2,1),即可得到答案 y.更多的例子见下表:

符号表达式 默认符号变量
a*x^2+b*x+c x
1/(4+cos(t)) t

36
4*x/y x
2*a+b b
2*i x

§6.2 Matlab 的六大常见符号运算

§6.2.1 因式分解
syms x
f=x^6+1;
s=factor(f)
结果为:
s=(x^2+1)*(x^4-x^2+1)

§6.2.2 计算极限
求极限:
ln( x  h)  ln( x)
(1) L  lim ,
h0 h

x n
(2) M  lim (1  )
n  n
syms h n x
L=limit('(log(x+h)-log(x))/h',h,0) %%单引号可省略掉
M=limit('(1-x/n)^n',n,inf)
结果为:
L =1/x
M =exp(-x)

§6.2.3 计算导数
dy dy d2 y
y  sin ax , 求 A  ,B  ,C 
dx da d x2 .
syms a x; y=sin(a*x);
A=diff(y,x)
B=diff(y,a)
C=diff(y,x,2)
结果为:
A = cos(a*x)*a
B = cos(a*x)*x
C = -sin(a*x)*a^2

§6.2.4 计算不定积分、定积分、反常积分
x2  1
I 
( x2  2 x  2 ) 2
dx

/2 cos x
J
0
 sin x  cos x
dx


2
K 0 e  x dx

syms x
f=(x^2+1)/(x^2-2*x+2)^2;

37
g=cos(x)/(sin(x)+cos(x));
h=exp(-x^2);
I=int(f)
J=int(g,0,pi/2)
K=int(h,0,inf)
结果为:
I =1/4*(2*x-6)/(x^2-2*x+2)+3/2*atan(x-1)
J =1/4*pi
K =1/2*pi^(1/2)

§6.2.5 符号求和

1
求级数 n
n 1
2
的和 S, 以及前十项的部分和 S1.

syms n
S=symsum(1/n^2, 1, inf)
S1=symsum(1/n^2,1,10)
结果为:
S =1/6*pi^2
S1 =1968329/1270080

x
重要说明:当求函数项级数 n n 1
2
的和 S2 时,可用命令:

syms n x
S2=symsum(x/n^2, n, 1, inf)
S2 =1/6*x*pi^2

两点说明:
(1)注意观察 S2 与 S1 的细微区别!
(2)当通项公式的 Matlab 表达式较长时,表达式要加上单引号.后面的练习中会遇到
此问题.

§6.2.6 解代数方程和常微分方程
利用符号表达式解代数方程所需要的函数为 solve(f),即解符号方程式 f.
例如:求一元二次方程 a*x^2+b*x+c=0 的根.
f=sym('a*x^2+b*x+c') 或 f='a*x^2+b*x+c'
solve(f)
ans=
[1/2/a*(-b+(b^2-4*c*a)^(1/2))]
[1/2/a*(-b-(b^2-4*c*a)^(1/2))]
solve(f, a)
ans=
-(b*x+c)/x^2

利用符号表达式可求解微分方程的解析解,所需要的函数为 dsolve(f),使用格式:
dsolve('equation1', ' equation2', …)
其中:equation 为方程或条件.写方程或条件时,用 Dy 表示 y 关于自变量的一阶导数,
用 D2y 表示 y 关于自变量的二阶导数,依此类推.
1. 求微分方程 y '  x 的通解.
syms x y %定义 x,y 为符号
dsolve('Dy=x', 'x')
ans =

38
1/2*x^2+C1
试比较:
若写成:
syms x y %定义 x,y 为符号
dsolve('Dy=x')
结果将是什么?是否正确?为什么?

 y"  x  y '
2. 求微分方程  的特解.
 y (0)  1, y ' (0)  0
syms x y
dsolve('D2y=x+Dy', 'y(0)=1', 'Dy(0)=0', 'x')
ans =
-1/2*x^2+exp(x)-x
试比较:
若写成:
syms x y
dsolve('D2y=x+Dy', 'y(0)=1', 'Dy(0)=0')

结果将是什么?是否正确?为什么?

 x'  y  x
3. 求微分方程组  的通解.
 y'  2 x
syms x y
[x,y]=dsolve('Dx=y+x, Dy=2*x')
x=
1/3*C1*exp(-t)+2/3*C1*exp(2*t)+1/3*C2*exp(2*t)-1/3*C2*exp(-t)
y=
2/3*C1*exp(2*t)-2/3*C1*exp(-t)+2/3*C2*exp(-t)+1/3*C2*exp(2*t)

试比较:
若写成:
(1) dsolve('Dx=y+x, Dy=2*x')
结果将是:
ans =
x: [1x1 sym]
y: [1x1 sym]
试解释此结果的含义.

若写成:
(2) [x,y]=dsolve('Dx=y+x, Dy=2x')
结果将是:
x=
exp(t)*C1+C2*exp(t)-C2-2-2*t
y=
C2+2*t
是否正确?为什么?

39
综合练习
1.按顺序进行如下的操作:
(1)产生一个 5 阶魔术方阵 A;并计算 A'与 A-1(即 inv(A));
(2)求 A 的特征值;
(3)计算 A 的各列的总和与平均值;
(4)计算 A 的各行的总和与平均值;
(5)若 b=[1 2 3 4 5] ',求方程组 Ax=b 的解;
(6)验证你的结论的正确性.
2.产生行向量 S =[1.0, 1.2, 1.4, …, 20],并计算 S * S' 与 S' * S,你有何“发现”?
1 2  5 5
3.设 A=  ;B=   ;求 C=A * B – B * A,你有何“发现”?
3 4  0 5
1 2  5 0
4.若设矩阵 A=   ;B=   ;求 C=A * B – B * A,你又有何“发现”?
3 4  0 5
5.如何建立如下的矩阵(命令方式和程序方式)?

 2004 0  0   0 10  10 
   
 0 2004  0   10 0  10 
(1)  ; (2) ;
         
   
 0  
 0 2004 1010  10 10  0 1010

 2004 1  1   10 10  10 


   
 1 2004  1  10 10  10 
(3)  ; (4) 
          
 
 1 1  2004 1010  10 10 
 10 1010
 
1 1 1 
 2 3  11 
 10 0  0   
 1 20  0  1 1  1 
(5)   (6)  3 4 12 
      
       
 1 1  100  1 1 1 
  
 11 12 20 
 2004 20 0 0 0 
 0
 2004 30 0 0 
(7)  0 0 2004 40 0 
 
 0 0 0 2004 50 
 0 0 0 0 2004 

3
6.绘制下列曲线的图形(散点图与折线图): y  x3  x2  x  1 , x [ 1 , 2 ]
7.绘制下列曲面的图形: z 2  x 2  2 y 2 (提示:曲面由两部分构成)
8.在同一个图形上作下列两个函数的图象:
2 2
(1) y  sin ( x), x  [0,2 ] ; (2) y  cos ( x), x  [0,2 ]

40
9.假如你有一组实测数据,例如:
x=[53 56 60 67.5 75 90 110];
y=[109 120.5 130 141.1 157.5 180 185];
求其回归直线,画回归直线图形并计算最小误差平方和.
10.假如你有一组实测数据,例如:
x=[75 86 95 108 112 116 135 151 155 160 163 167 171 178 185];
y=[10 12 15 17 20 22 35 41 48 50 51 54 59 66 75];
求其回归直线,画回归直线图形并计算最小误差平方和.
11.随机产生 500 个 0 到 100 的整数 FS 作为学生的考试分数.
(1) 画出 FS 的简单直方图;
(2) 画出每个分数段(0~10、10~20、…,90~100)的统计频数直方图;
12.求下列各结果:
(1)用 Matlab 因式分解: x100  1 .
1
(1  x) x  e
(2)用 Matlab 求极限: L  lim .
x 0 x

(3)用 Matlab 求积分: 0 sin x 2 dx .

x 2 n1
(4)用 Matlab 求幂级数:  ( 1 ) n1 的和函数(化简结果).
n 1 4n2 1
13.非线性回归尝试
下表是到 1994 年的游泳世界纪录,试估计时间 y 与距离 x 的关系.
距离 x(米) 50 100 200 400 800 1500
时间 y(秒) 21.81 48.42 106.69 225 466.60 863.48

说明:用线性回归方法将得到: y  11.0089  0.5961x ,但当 x  18 时, y  0.2794 ,


这是非常荒唐的结果!显然,一个基本要求是当 x  0 时 y  0 .试尝试使用非线性回归模
b
型: y  ax .

14. (三维)符号作图尝试
命令 作用 解释
ezplot3 3-D parametric curve plotter 3D 参数曲线图形
ezcontour use contour plotter 等高线图
ezcontourf filled contour plotter 填充等高线图
ezmesh 3-D mesh plotter 3D mesh 曲面图形
ezmeshc combination mesh/contour plotter mesh 曲面/等高线图
ezsurf 3-D colored surface plotter 3D surf 曲面图形
ezsurfc combination surf/contour plotter surf 曲面/等高线图

请尝试以下的命令:
ezplot3('sin(t)', ' cos(t)', 't', [0,6*pi])
ezcontour('x*exp(-x^2 - y^2)')
ezcontourf('x*exp(-x^2 - y^2)')
ezmesh('(s-sin(s))*cos(t)','(1-cos(s))*sin(t)','s',[-2*pi,2*pi])
ezmeshc('(s-sin(s))*cos(t)','(1-cos(s))*sin(t)','s',[-2*pi,2*pi])
ezsurf('x*exp(-x^2 - y^2)')
ezsurfc('x*exp(-x^2 - y^2)')

41



主要内容

综 述……(43)
实验一 特殊函数与图形……(45)
实验二 定积分的近似计算……(53)
实验三 求代数方程的近似根(解) ……(61)
实验四 求微分方程的解……(72)
实验五 数据的统计分析……(81)
实验六 古典密码与破译……(95)
实验七 数字填图问题……(106)
实验八 概率与频率……(119)
实验九 网站排名问题……(126)
实验十 遗传算法与优化问题……(141)

42
综 述

在最近的几十年中,数学科学取得了飞速的发展,新的数学分支层出不穷,
而且各分支之间,数学与其它科学之间相互交叉,相互渗透,呈现高度统一的新
趋势,大量新兴的数学方法在科学研究和生产管理各种领域中被成功地应用,现
代数学已不再仅仅是其它科学的基础,而是直接发挥着第一生产力的作用. 目前
在工农业生产方面,正大量运用的高技术从本质上说就是数学技术,这一点已被
越来越多的人们所认识.因此,能否自觉地运用数学观念、数学知识和定量思维
方法已成为衡量一个民族文化素质的标志.

面临数学地位的巨大变化,科学工作者和工程技术人员对数学知识的需求大
大增加了,以往传统的数学课程已远远不能满足需要.新型的人才不仅需要有传
统意义上的逻辑思维能力和几何直观能力,而且要求具有更强的数学建模能力和
使用新的计算工具即计算机的能力,数学实验课正是基于这种需要而设立的,它
是面向 2l 世纪数学教学内容和课程体系改革的成功举措.

数学实验课和传统的数学课程的一个重要区别是,传统的课程注重知识的传
授和逻辑推理能力的培养,而数学实验课则侧重于将实际问题转化为数学问题,
即数学建模能力的培养.首要的是培养学生用量的观念去观察和把握现象的能力,
培养学生综合运用数学知识分析和解决实际问题的意识,即数学素质.

另一个区别是传统数学课程的运算能力培养,主要指的是寻求解析解的能力,
包括许许多多的变换和技巧,而这些训练势必使课程内容臃肿不堪,增加学生负
担.数学实验课则更侧重于创新意识和科学计算能力的培养,也就是运用现代的
计算机技术和软件包来取代那些繁杂的推演和复杂的运算技巧.由于软件包技术
的高速发展,不仅能完成复杂的数值计算,也能进行符号演算以及机器证明等工
作,因此,数学实验课是加强实践性的一个重要环节.

数学实验课的内容取自各种应用领域,可以是工业、农业、技术、经济管理、
军事等的实际问题,也可以是科学研究中的基础问题. 本教材将主要介绍如何通
过建模方法将实际问题转化为数学问题,介绍解决问题的方法,包括解析的方法
和数值的方法,并且介绍各种常用的数学软件. 通过在计算机上做实验,使学生
掌握用数值模拟的方法解决实际问题的全过程.

数学实验课采用讲授和上机相结合的方式,建议分三步进行:

第一步:由教师讲解实验中问题的具体背景,相关的建模方法和数值计算的
方法。包括条件的化简,因素的分离和选择变量,以及建立变量之间关系的数学
方法,并对所建立的数学模型求解的理论和实现计算的计算机指令等.

43
第二步:由学生分组在课外进行讨论,建立模型,做好解答的准备.

第三步:上机操作,用数学软件求出解析解和数值解,重点在数值解,最后
写出实验报告.

教材的实验篇主要介绍是 10 个数学实验, 所涉及的内容跨越了数学和统计学


上众多不同的领域.我们选择它们的目的,一方面是展示数学科学领域的宽阔,
同时也把在后续课程中将会再次遇到的若干重要的数学思想作简单介绍,并给出
应用方式的演示.实验的次序不限.无论做一两个实验,还是做更多的实验,它
都会是一个有益的学习经历.

实验的目标是希望你从自己的一些数学发现中获得乐趣.与此同时你当然会
学到一些特定的思想和技巧.但与获得数学摸索上更多的经历相比,那些是第二
位的.显然,数学与其它科学分支的差别就在于,实验上的发现有被严格证明的
可能性,从而不再有任何可怀疑之处.你现有的数学知识可能不足以构造出一个
证明过程,但通过系统清晰地给出对实验结论的阐述,可以为后续课程中学习构
造证明方法打下更好的基础.

44
实验一 特殊函数与图形

一、问题背景与实验目的
著名的 Riemann 函数大家都很熟悉了,但是关于它的图像你是否清楚呢?除
了最上面那几点,其他都很难画吧?你想不想看看下面那些“挤在一起”的点是
怎样分布的呢?还有几何中的马鞍面、单叶双曲面等是怎样由直线生成的,是不
是也想目睹一下呢?这些,都离不开绘图.
实际上绘图一直是数学中的一种重要手段,借助图形,往往可以化繁为简,
使抽象的对象得到明白直观的体现.比如函数的基本性质,一个图形常可以使之
一目了然,非常有效.它虽不能代替严格的分析与证明,但在问题的研究过程中,
可以帮助研究人员节约相当一部分精力.此外,它还可以使计算、证明、建模等
的结果得到更明白易懂的表现,有时,这比科学论证更有说服力.
同时,数学的教学与学习过程也离不开绘图.借助直观的图形,常可以使初
学者更容易接受新知识.如数学分析中有不少函数,其解析式着实让人望而生畏,
即使对其性质作了详尽的分析,还是感到难明就里;但如果能看到它的图形,再
配合理论分析,则问题可以迎刃而解.又如在几何的学习中,会遇到大量的曲线
与曲面,也离不开图形的配合.
传统的手工作图,往往费力耗时,效果也不尽理想.计算机恰恰弥补了这个
不足,使你可以方便地指定各种视角、比例、明暗,从各个角度进行观察.
本实验通过对函数的图形表示和几个曲面(线)图形的介绍,一方面展示它
们的特点,另一方面,也将就 Matlab 软件的作图功能作一个简单介绍.大家将
会看到,Matlab 的作图功能非常强大.

二、相关函数(命令)及简介
1.平面作图函数:plot,其基本调用形式:
plot(x,y,s)
以 x 作为横坐标,y 作为纵坐标.s 是图形显示属性的设置选项.例如:
x=-pi:pi/10:pi;
y=sin(x);
plot(x,y,'--rh','linewidth',2,'markeredgecolor','b','markerfacecolor','g')

图1

45
在使用函数 plot 时,应当注意到当两个输入量同为向量时,向量 x 与 y 必须
维数相同,而且必须同是行向量或者同是列向量.
绘图时,可以制定标记的颜色和大小,也可以用图形属性制定其他线条特征,
这些属性包括:
linewidth 指定线条的粗细.
markeredgecolor 指定标记的边缘色
markerfacecolor 指定标记表面的颜色.
markersize 指定标记的大小.
若在一个坐标系中画几个函数,则 plot 的调用格式如下:
plot(x1,y1,s1,x2,y2,s2,……)
2.空间曲线作图函数:plot3,它与 plot 相比,只是多了一个维数而已.其调用
格式如下:
plot3(x,y,z,s).例如:
x=0:pi/30:20*pi;
y=sin(x);z=cos(x);
plot3(x,y,z)
得到三维螺旋线:

图2

3.空间曲面作图函数:
(1)mesh 函数.绘制彩色网格面图形.调用格式:
mesh(z),mesh(x,y,z)和 mesh(x,y,z,c).
其中,mesh(x,y,z,c)画出颜色由 c 指定的三维网格图.若 x、y 均为向量,则
length(x)=n,length(y)=m,[m,n]=size(z).
(2)surf 在矩形区域内显示三维带阴影曲面图.调用格式与 mesh 类似.
(3)ezmesh 用符号函数作三维曲面网格图.
调用格式:
ezmesh(x,y,z)
其中 x = x(s,t), y = y(s,t),z = z(s,t).画图区域默认为: -2*pi < s < 2*pi 且-2*pi < t
< 2*pi.
或者用格式:
ezmesh(x,y,z,[smin,smax,tmin,tmax])
(4)ezsurf 用符号函数作三维曲面图.调用格式与 ezmesh 类似.
(5)sphere 画球体命令.

46
4.meshgrid,调用格式:
[x,y]=meshgrid(m,n),
这里的 m,n 为给定的向量,可以定义网格划分区域和划分方法.矩阵 x 和矩阵
y 是网格划分后的数据矩阵.
5.图像的修饰与其他函数:
(1)axis equal 控制各个坐标轴的分度,使其相等;
(2)colormap 设置绘图颜色.
调用格式:
colormap([r g b])
其中 r,g,b 都是 0-1 之间的数.
或者用格式:
colormap(s)
s 为颜色映像.下面举几个常用的例子:
颜色映像 相应的颜色系 颜色映像 相应的颜色系
autumn 红黄色系 hsv 色调饱和色系
gray 线性灰色系 hot 黑红黄白色系
cool 青和洋红色系 pink 柔和色系
(3)grid 网格函数 grid on 添加网格.grid off 取消网格.
(4)find 找出符合条件的元素在数组中的位置.调用格式:
y=find(条件)
例如:输入:
a=[4 5 78 121 4 665 225 4 1];
b=find(a>7)
输出:b =3 4 6 7

三、实验内容
数学分析中,特别是积分部分,我们接触了不少有趣的函数,由于其中有的
不是一一对应的,用上面的方法无法画出它们的图像,这时就只能用参数了.
此外还有些图形只能用参数来画,比如空间曲线,在计算机上不接受“两个
曲面的交线”这种表示,所以也只能用参数来实现.
用参数方式作图的关键在于找出合适的参数表示,尤其是不能有奇点,最好
也不要用到开方.所以要找的参数最好是有几何意义的.当然这也不可一概而论,
需要多积累经验.
1.利用函数 plot 在一个坐标系中画以下几个函数图像,要求采用不同颜色、
不同线形、不同的符号标记.函数为:x  sin(t ), y  cos(t ), z  sin(2t ), t  (0, 2 ) .

程序如下:
t=0:pi/20:2*pi;
x=sin(t);
y=cos(t);
z=sin(2*t);
plot(t, x, '--k*', t, y, '-rs', t, z, ':bo')
图像如下:

47
图3

2.绘制类似田螺线的一条三维螺线(方程自己设计).
程序如下:
t=0:.1:30;
x=2*(cos(t)+t.*sin(t));
y=2*(sin(t)-t.*cos(t));
z=1.5*t;
plot3(x,y,-z) %取 –z 主要是为了画图看起来更清楚
axis equal
图像如下:

图4

sin x 2  y 2
3.利用函数 z  ,绘制一个墨西哥帽子的图形.
x2  y2
程序如下:
[a,b]=meshgrid(-8:.5:8); %先生成一个网格
c=sqrt(a.^2+b.^2)+eps;
z=sin(c)./c;
mesh(a,b,z)
axis square

48
图像如下:

图5

思考:这里的 eps 是什么?其作用是什么?


x2 y2
4.利用 surf 绘制马鞍面图形(函数为: z   ).
9 4
程序如下:
[x,y]=meshgrid(-25:1:25,-25:1:25);
z=x.^2/9-y.^2/4;
surf(x,y,z)
title('马鞍面')
grid off
图像如下:

图6

5.分别用 ezmesh 和 ezsurf 各绘制一个圆环面,尝试将两个圆环面放在一个图形

49
界面内,观察它们有什么不同之处.
提示:圆环面的方程为: ( x 2  y 2  R ) 2  z 2  r 2 , R  6, r  2 ,而圆
环面的参数方程为:
 x  ( R  r cos u ) cos v

 y  ( R  r cos u ) sin v u  [0,2 ], v  [0,2 ]
 z  r sin u ,

程序参见附录 1.
图像如下:

图7
6.绘制黎曼函数图形,加深对黎曼函数的理解.
说明:黎曼函数的定义为
1 p p
 , 当p、q为正整数, 为既约分数,x   (0,1)
y  q q q
0, 当x  0,
1及无理点, x  [0,
1]

程序参见附录 2.
图像如下:

图8

50
四、自己动手
1.作出下图所示的三维图形:

图9
提示:图形为圆环面和球面的组合.

2.作出下图所示的墨西哥帽子及其剪裁图形:

图 10

3.画出球面、椭球面、双叶双曲面、单叶双曲面.
4.若要求田螺线的一条轴截面的曲边是一条抛物线: y  0 时 x 2  5 z .试重新设
计田螺线的参数方程,并画出该田螺线.

51
5.作出下图所示的马鞍面(颜色为灰色,并有一个标题:“马鞍面”):

图 11
6.绘制图 8 所示的黎曼函数图形,要求分母的最大值 n 的数值由键盘输入(提
示:使用 input 语句).

五、附录
附录 1:(fulu1.m)
程序如下:
subplot(1,2,1)
ezmesh('(6+2*cos(u))*cos(v)','(6+2*cos(u))*sin(v)','2*sin(u)',[0,2*pi,0,2*pi])
axis equal
subplot(1,2,2)
ezsurf('(6+2*cos(u))*cos(v)','(6+2*cos(u))*sin(v)','2*sin(u)',[0,2*pi,0,2*pi])
axis equal

附录 2:(fulu2.m)
程序如下:
n=100;x=[];y=[];k=1;
for i=2:n
for j=1:i-1
if gcd(i,j)==1 %用函数 gcd(m,n)可求 m 和 n 的最大公约数
x(k)=j/i;
y(k)=1/i;
k=k+1;
end
end
end
plot(x,y,'.b');
axis([0,1,0,1])

52
实验二 定积分的近似计算

一、问题背景与实验目的
利用牛顿—莱布尼兹公式虽然可以精确地计算定积分的值,但它仅适用于被
积函数的原函数能用初等函数表达出来的情形.如果这点办不到或者不容易办
到,这就有必要考虑近似计算的方法.在定积分的很多应用问题中,被积函数甚
至没有解析表达式,可能只是一条实验记录曲线,或者是一组离散的采样值,这
时只能应用近似方法去计算相应的定积分.
本实验将主要研究定积分的三种近似计算算法:矩形法、梯形法、抛物线
法.对于定积分的近似数值计算,Matlab 有专门函数可用.

二、相关函数(命令)及简介
1.sum(a):求数组 a 的和.
2.format long:长格式,即屏幕显示 15 位有效数字.
(注:由于本实验要比较近似解法和精确求解间的误差,需要更高的精度).
3.double():若输入的是字符则转化为相应的 ASCII 码;若输入的是整型数值则
转化为相应的实型数值.
4.quad():抛物线法求数值积分.
格式: quad(fun,a,b) ,注意此处的 fun 是函数,并且为数值形式的,所以使
用*、/、^等运算时要在其前加上小数点,即 .*、./、.^等.
例:Q = quad('1./(x.^3-2*x-5)',0,2);
5.trapz():梯形法求数值积分.
格式:trapz(x,y)
其中 x 为带有步长的积分区间;y 为数值形式的运算(相当于上面介绍的函
数 fun)

例:计算  sin( x)dx
0

x=0:pi/100:pi;y=sin(x);
trapz(x,y)
6.dblquad():抛物线法求二重数值积分.
格式:dblquad(fun,xmin,xmax,ymin,ymax),fun 可以用 inline 定义,也可以通
过某个函数文件的句柄传递.
例 1:Q1 = dblquad(inline('y*sin(x)'), pi, 2*pi, 0, pi)
顺便计算下面的 Q2,通过计算,比较 Q1 与 Q2 结果(或加上手工验算),
找出积分变量 x、y 的上下限的函数代入方法.
Q2 = dblquad(inline('y*sin(x)'), 0, pi, pi, 2*pi)
例 2:Q3 = dblquad(@integrnd, pi, 2*pi, 0, pi)
这时必须存在一个函数文件 integrnd.m:

53
function z = integrnd(x, y)
z = y*sin(x);
7.fprintf(文件地址,格式,写入的变量):把数据写入指定文件.
例:x = 0:.1:1;
y = [x; exp(x)];
fid = fopen('exp.txt','w'); %打开文件
fprintf(fid,'%6.2f %12.8f\n',y); %写入
fclose(fid) %关闭文件
8.syms 变量 1 变量 2 …:定义变量为符号.
9.sym('表达式'):将表达式定义为符号.
解释:Matlab 中的符号运算事实上是借用了 Maple 的软件包,所以当在 Matlab
中要对符号进行运算时,必须先把要用到的变量定义为符号.
10.int(f,v,a,b):求 f 关于 v 积分,积分区间由 a 到 b.
11.subs(f,'x',a):将 a 的值赋给符号表达式 f 中的 x,并计算出值.若简单
地使用 subs(f),则将 f 的所有符号变量用可能的数值代入,并计算出值.

三、实验内容
1. 矩形法
根据定积分的定义,每一个积分和都可以看作是定积分的一个近似值,即
b n

 f ( x )dx   f ( i )xi
a
i 1

在几何意义上,这是用一系列小矩形面积近似小曲边梯形的结果,所以把这
个近似计算方法称为矩形法.不过,只有当积分区间被分割得很细时,矩形法才
有一定的精确度.
1 dx
针对不同  i 的取法,计算结果会有不同,我们以  为例(取 n  100 ),
0 1  x2

(1) 左点法:对等分区间
ba
x0  a  x1    xi  a  i    xn  b ,
n
在区间 [ xi 1 , xi ] 上取左端点,即取  i  x i 1 ,

n
1 dx

 0 1  x2 i1 f ( i )xi  0.78789399673078,

1 dx 
理论值  2
 ,此时计算的相对误差
0 1 x 4
0.78789399673078   4
  0.003178
 4

(2)右点法:同(1)中划分区间,在区间 [ xi 1 , xi ] 上取右端点,即取  i  x i ,

54
n
1 dx
 0 1  x2 

i 1
f ( i )xi  0.78289399673078,

1 dx 
理论值  2
 ,此时计算的相对误差
0 1 x 4
0.78289399673078   4
  0.003188
 4
xi 1  xi
(3)中点法:同(1)中划分区间,在区间 [ xi 1 , xi ] 上取中点,即取  i  ,
2
n
1 dx
 0 1  x2 

i 1
f ( i )xi  0.78540024673078,

1 dx 
理论值  2
 ,此时计算的相对误差
0 1 x 4
0.78540024673078   4
  2.653  106
 4

如果在分割的每个小区间上采用一次或二次多项式来近似代替被积函数,那
么可以期望得到比矩形法效果好得多的近似计算公式.下面介绍的梯形法和抛物
线法就是这一指导思想的产物.

2. 梯形法
等分区间
ba ba
x0  a  x1    xi  a  i    x n  b , x 
n n
相应函数值为
y 0 , y1 ,  , y n ( y i  f ( xi ), i  0,1, , n ).

曲线 y  f (x ) 上相应的点为

P0 , P1 , , Pn ( Pi  ( xi , y i ), i  0,1, , n )

将曲线的每一段弧 Pi 1 Pi 用过点 Pi 1 , Pi 的弦 Pi 1 Pi (线性函数)来代替,这使得

每个 [ xi 1 , xi ] 上的曲边梯形成为真正的梯形,其面积为

y i 1  y i
 x , i  1,2, , n .
2
于是各个小梯形面积之和就是曲边梯形面积的近似值,

55
n
b yi 1  yi x n
 a
f ( x )dx  
i 1 2
 x   ( yi1  yi ) ,
2 i 1

b b  a y0 y
 f ( x )dx  (  y1    yn 1  n ) ,
a n 2 2
称此式为梯形公式.
1 dx
仍用  的近似计算为例,取 n  100 ,
0 1  x2

1 dx ba y y
 0 1  x 2  n ( 20  y1    yn1  2n )  0.78539399673078,
1 dx 
理论值  2
 ,此时计算的相对误差
0 1 x 4
0.78539399673078   4
  5.305  106
 4
很显然,这个误差要比简单的矩形左点法和右点法的计算误差小得多.

3. 抛物线法
由梯形法求近似值,当 y  f (x ) 为凹曲线时,它就偏小;当 y  f (x ) 为凸曲

线时,它就偏大.若每段改用与它凸性相接近的抛物线来近似时,就可减少上述
缺点,这就是抛物线法.
将积分区间 [a, b] 作 2n 等分,分点依次为
ba ba
x 0  a  x1    xi  a  i    x 2n  b , x  ,
2n 2n
对应函数值为
y 0 , y1 , , y 2 n ( y i  f ( xi ), i  0,1, , 2n ),

曲线上相应点为
P0 , P1 , , P2 n ( Pi  ( xi , y i ), i  0,1, , 2n ).

现 把 区 间 [ x0 , x 2 ] 上 的 曲 线 段 y  f (x ) 用 通 过 三 点 P0 ( x0 , y 0 ) , P1 ( x1 , y1 ) ,

P2 ( x 2 , y 2 ) 的抛物线

y  x 2  x    p1 ( x)

来近似代替,然后求函数 p1 ( x) 从 x0 到 x 2 的定积分:
x2 x2  3 3  2 2
 p1 ( x )dx   ( x 2   x   )dx  ( x 2  x0 )  ( x2  x0 )   ( x2  x0 )
x0 x0 3 2

56
x 2  x0
 [(x02  x0   )  (x 22  x 2   )   ( x 0  x 2 ) 2  2  ( x 0  x 2 )  4 ]
6

x0  x2
由于 x1  ,代入上式整理后得
2

x2 x 2  x0 2
 p1 ( x)dx  [(x02  x 0   )  (x 22  x 2   )  4(x1  x1   )]
x0 6

x 2  x0 ba
 ( y 0  4 y1  y 2 )  ( y 0  4 y1  y 2 )
6 6n
同样也有
ba x4
( y 2  4 y3  y 4 )
 p2 ( x)dx 
x2 6n
……
x2 n ba
 x2 n2 pn ( x)dx  6n ( y 2 n2  4 y 2n 1  y 2 n )
将这 n 个积分相加即得原来所要计算的定积分的近似值:
n n
b x2 i ba
 f ( x )dx    pi ( x)dx   ( y2i  2  4 y2i 1  y2i ) ,
a
i 1
x2 i2
i 1 6n

b ba
 [ y0  y2 n  4( y1  y3   y2 n 1 )  2( y2  y4    y2 n  2 )]
f ( x )dx 
a 6n
这就是抛物线法公式,也称为辛卜生(Simpson)公式.
1 dx
仍用  的近似计算为例,取 n  100 ,
0 1  x2

1 dx ba
 0 1  x 2  6n [ y0  y2n  4( y1  y3   y2n1 )  2( y2  y4    y2n 2 )]
=0.78539816339745,
1 dx 
理论值   ,此时计算的相对误差
0 1  x2 4
0.78539816339745   4
  2.827 10 16
 4

4. 直接应用 Matlab 命令计算结果

dx 1
(1) 数值计算  .
1  x2 0

方法 1:int('1/(1+x^2)','x',0,1) (符号求积分)
方法 2:quad('1./(1+x.^2)',0,1) (抛物线法求数值积分)

57
方法 3:x=0:0.001:1;
y=1./(1+x.^2);
trapz(x,y) (梯形法求数值积分)
2 1
(2)数值计算  dx  x  y 2 dy
0 1

方法 1:int(int('x+y^2','y',-1,1),'x',0,2) (符号求积分)
方法 2:dblquad(inline('x+y^2'),0,2,-1,1) (抛物线法二重数值积分)

四、自己动手
1 dx
1. 实现实验内容中的例子,即分别采用矩形法、梯形法、抛物线法计算  ,
0 1  x2
取 n  258 ,并比较三种方法的精确程度.
2 dx
2. 分别用梯形法与抛物线法,计算  ,取 n  120 .并尝试直接使用函数
1 x

trapz()、quad()进行计算求解,比较结果的差异.
 sin x
3. 试计算定积分  dx .(注意:可以运用 trapz()、quad()或附录程序求解
0 x
吗?为什么?)
1 dx
4. 将  的近似计算结果与 Matlab 中各命令的计算结果相比较,试猜测
0 1  x2

Matlab 中的数值积分命令最可能采用了哪一种近似计算方法?并找出其他例
子支持你的观点.
5. 通过整个实验内容及练习,你能否作出一些理论上的小结,即针对什么类型
的函数(具有某种单调特性或凹凸特性),用某种近似计算方法所得结果更接
近于实际值?
6. 学习 fulu2sum.m 的程序设计方法,尝试用函数 sum 改写附录 1 和附录 3 的
程序,避免 for 循环.

五、附录
附录 1:矩形法(左点法、右点法、中点法)(fulu1.m)
format long
n=100;a=0;b=1;
inum1=0;inum2=0;inum3=0;
syms x fx
fx=1/(1+x^2);
for i=1:n
xj=a+(i-1)*(b-a)/n; %左点
xi=a+i*(b-a)/n; %右点
fxj=subs(fx,'x',xj); %左点值

58
fxi=subs(fx,'x',xi); %右点值
fxij=subs(fx,'x',(xi+xj)/2); %中点值
inum1=inum1+fxj*(b-a)/n;
inum2=inum2+fxi*(b-a)/n;
inum3=inum3+fxij*(b-a)/n;
end
inum1
inum2
inum3
integrate=int(fx,0,1)
integrate=double(integrate)

fprintf('The relative error between inum1 and real-value is about: %d\n\n',...


abs((inum1-integrate)/integrate))

fprintf('The relative error between inum2 and real-value is about: %d\n\n',...


abs((inum2-integrate)/integrate))

fprintf('The relative error between inum3 and real-value is about: %d\n\n',...


abs((inum3-integrate)/integrate))

附录 2:梯形法(fulu2.m)
format long
n=100;a=0;b=1;inum=0;
syms x fx
fx=1/(1+x^2);
for i=1:n
xj=a+(i-1)*(b-a)/n;
xi=a+i*(b-a)/n;
fxj=subs(fx,'x',xj);
fxi=subs(fx,'x',xi);
inum=inum+(fxj+fxi)*(b-a)/(2*n);
end
inum
integrate=int(fx,0,1)
integrate=double(integrate)

fprintf('The relative error between inum and real-value is about: %d\n\n',...


abs((inum-integrate)/integrate))

59
附录 2sum:梯形法(fulu2sum.m),利用求和函数,避免 for 循环
format long
n=100;a=0;b=1;
syms x fx
fx=1/(1+x^2);
i=1:n;
xj=a+(i-1)*(b-a)/n; %所有左点的数组
xi=a+i*(b-a)/n; %所有右点的数组
fxj=subs(fx,'x',xj); %所有左点值
fxi=subs(fx,'x',xi); %所有右点值
f=(fxi+fxj)/2*(b-a)/n; %梯形面积
inum=sum(f) %加和梯形面积求解
integrate=int(fx,0,1)
integrate=double(integrate)

fprintf('The relative error between inum and real-value is about: %d\n\n',...


abs((inum-integrate)/integrate))

附录 3:抛物线法(fulu3.m)
format long
n=100;a=0;b=1;inum=0;
syms x fx
fx=1/(1+x^2);
for i=1:n
xj=a+(i-1)*(b-a)/n; %左点
xi=a+i*(b-a)/n; %右点
xk=(xi+xj)/2; %中点
fxj=subs(fx,'x',xj);
fxi=subs(fx,'x',xi);
fxk=subs(fx,'x',xk);
inum=inum+(fxj+4*fxk+fxi)*(b-a)/(6*n);
end
inum
integrate=int(fx,0,1)
integrate=double(integrate)

fprintf('The relative error between inum and real-value is about: %d\n\n',...


abs((inum-integrate)/integrate))

60
实验三 求代数方程的近似根(解)

一、问题背景和实验目的
求代数方程 f ( x )  0 的根是最常见的数学问题之一(这里称为代数方程,主
要是想和后面的微分方程区别开.为简明起见,在本实验的以下叙述中,把代数
方程简称为方程),当 f (x ) 是一次多项式时,称 f ( x )  0 为线性方程,否则称之
为非线性方程.
当 f ( x )  0 是非线性方程时,由于 f (x ) 的多样性,尚无一般的解析解法可使
用,但如果对任意的精度要求,能求出方程的近似根,则可以认为求根的计算问
题已经解决,至少能满足实际要求.
本实验介绍一些求方程实根的近似值的有效方法,要求在使用这些方法前先
确定求根区间 [a, b] ,或给出某根的近似值 x0 .在实际问题抽象出的数学模型中,
x0 可以根据物理背景确定;也可根据 y  f (x ) 的草图等方法确定,还可用对分法、
迭代法以及牛顿切线法大致确定根的分布情况.
通过本实验希望你能:
1. 了解对分法、迭代法、牛顿切线法求方程近似根的基本过程;
2. 求代数方程(组)的解.

二、 相关函数(命令)及简介
1.abs( ):求绝对值函数.
2.diff(f):对独立变量求微分,f 为符号表达式.
diff(f, 'a'):对变量 a 求微分,f 为符号表达式.
diff(f, 'a', n):对变量 a 求 n 次微分,f 为符号表达式.
例如:
syms x t
diff(sin(x^2)*t^6, 't', 6)
ans=
720*sin(x^2)
3.roots([c(1), c(2), …, c(n+1)]):求解多项式 c1 x n    cn x  cn 1 的所有

根.例如:
求解: x 3  6 x 2  72 x  27  0 .
p = [1 -6 -72 -27];
r = roots(p)
r=
12.1229
-5.7345
-0.3884

4.solve('表达式'):求表达式的解.

61
solve('2*sin(x)=1')
ans =
1/6*pi
5.linsolve(A, b):求线性方程组 A*x=b 的解.
例如:
A= [9 0; -1 8]; b=[1; 2];
linsolve(A, b)
ans=
[ 1/9]
[19/72]
6.fzero(fun, x0):在 x0 附近求 fun 的解.其中 fun 为一个定义的函数,用
“@函数名”方式进行调用.
例如:
fzero(@sin, 3)
ans=
3.1416
7.subs(f, 'x ', a):将 a 的值赋给符号表达式 f 中的 x,并计算出值.
例如:
subs('x^2 ', 'x ', 2)
ans = 4

三、 实验内容
首先,我们介绍几种与求根有关的方法:

1.对分法
对分法思想:将区域不断对分,判断根在某个分段内,再对该段对分,依此
类推,直到满足精度为止.对分法适用于求有根区间内的单实根或奇重实根.
设 f (x ) 在 [a, b] 上连续, f (a)  f (b)  0 ,即 f (a)  0 , f (b)  0 或 f (a)  0 ,

f (b)  0 .则根据连续函数的介值定理,在 (a, b) 内至少存在一点  ,使 f ( )  0 .


下面的方法可以求出该根:
a b
(1) 令 x0  ,计算 f ( x0 ) ;
2
(2) 若 f ( x0 )  0 ,则 x0 是 f ( x )  0 的根,停止计算,输出结果 x  x0 .

若 f ( a )  f ( x0 )  0 ,则令 a1  a , b1  x0 ,若 f ( a )  f ( x0 )  0 ,则令 a1  x0 ,
a1  b1
b1  b ; x1  .
2
ak  bk
……,有 ak 、 bk 以及相应的 xk  .
2
(3) 若 f ( xk )   (  为 预 先 给 定 的 精 度 要 求 ) , 退 出 计 算 , 输 出 结 果

62
ak  bk
xk  ;
2
反之,返回(1),重复(1),(2),(3).
以上方法可得到每次缩小一半的区间序列{[ak , bk ]} ,在 (ak , bk ) 中含有方程的

根.
ak  bk
当区间长 bk  ak 很小时,取其中点 xk  为根的近似值,显然有
2
1 1 1 1
xk    (bk  ak )    (bk 1  ak 1 )    k 1 (b  a )
2 2 2 2
以上公式可用于估计对分次数 k .
1
分析以上过程不难知道,对分法的收敛速度与公比为 的等比级数相同.由
2
于 2  1024 ,可知大约对分 10 次,近似根的精度可提高三位小数.对分法的收
10

敛速度较慢,它常用来试探实根的分布区间,或求根的近似值.

2. 迭代法
1) 迭代法的基本思想:
由方程 f ( x )  0 构造一个等价方程

x   ( x)
从某个近似根 x0 出发,令
xk 1   ( xk ) , k  0,1,2,
可得序列{xk } ,这种方法称为迭代法.
若 {xk } 收敛,即
lim xk  x* ,
k 

只要  ( x ) 连续,有

lim xk 1  lim  ( xk )   (lim xk )


k  k  k 


x*   ( x* )
可知,{xk } 的极限 x* 是 x   ( x ) 的根,也就是 f ( x )  0 的根.
当然,若 xk 发散,迭代法就失败.
以下给出迭代过程 xk 1   ( xk ) 收敛的一些判别方法:
定义:如果根 x* 的某个邻域 x  x*   中,使对任意的 x0 ,迭代过程 xk 1   ( xk ) ,
k  0,1,2, 收敛,则称迭代过程在 x* 附近局部收敛.
定理 1:设 x*   ( x* ) ,在 x* 的某个邻域  内  '( x ) 连续,并且  '( x )  q  1 ,x   ,
则对任何 x0   ,由迭代 xk 1   ( xk ) 决定的序列{xk } 收敛于 x* .
定理 2:条件同定理 1,则
qk
xk  x*  x1  x0
1 q

63
1
xk  x*  xk 1  xk
1 q

定理 3:已知方程 x   ( x ) ,且

(1) 对任意的 x  [a, b] ,有  ( x )  [a, b] .


(2) 对 任 意 的 x  [a, b] , 有  '( x )  q  1 , 则 对 任 意 的 x0  [a, b] , 迭 代

qk
xk 1   ( xk ) 生成的序列{xk } 收敛于 x   ( x ) 的根 x ,且 xk  x  *
x1  x0 . *

1 q
以上给出的收敛定理中的条件要严格验证都较困难,实用时常用以下不严格
的标准:
当根区间 [a, b] 较小,且对某一 x0  [a, b] , ' ( x) 明显小于 1 时,则迭代收敛
(参见附录 3).

2) 迭代法的加速:
a) 松弛法:
若  ( x ) 与 xk 同是 x* 的近似值,则 xk 1  (1  k ) xk  k ( xk ) 是两个近似值的加
权平均,其中  k 称为权重,现通过确定  k 看能否得到加速.

迭代方程是:
x   ( x)
其中 ( x)  (1   ) x   ( x ) ,令 '( x )  1     '( x)  0 ,试确定  :
1 1  '( xk )
当  '( x)  1 时,有   ,即当 k  , 1  k  时,
1   '( x) 1   '( xk ) 1   '( xk )

可 望 获 得 较 好 的 加 速 效 果 , 于 是 有 松 弛 法 : xk 1  (1  k ) xk  k ( xk ) ,

1
k 
1   '( xk )
松弛法的加速效果是明显的 (见附录 4),甚至不收敛的迭代函数经加速后也
能获得收敛.

b) Altken 方法:
松弛法要先计算  '( xk ) ,在使用中有时不方便,为此发展出以下的 Altken 公
式:
x*   ( x* ) , x* 是它的根, x0 是其近似根.
设 x1   ( x0 ) , x2   ( x1 ) ,因为
x*  x2  [ x*  x2 ]  x2  [ ( x* )   ( x1 )]  x2  ' ( )( x*  x1 ) ,
x2  x1  ( x1 )   ( x0 )
用差商  近似代替 ' ( ) ,有
x1  x0 x1  x0

64
x2  x1 *
x*  x2  ( x  x1 ) ,
x1  x0

解出 x* ,得

* ( x2  x1 ) 2
x  x2 
x2  2 x1  x0
由此得出公式
xk(1)   ( xk ) ;
xk(2)   ( xk(1) ) ;

( xk(2)  xk(1) ) 2
xk 1  xk(2)  , k  0,1,2,
xk(2)  2 xk(1)  xk
这就是 Altken 公式,它的加速效果也是十分明显的,它同样可使不收敛的迭代
格式获得收敛(见附录 5).

3. 牛顿(Newton)法(牛顿切线法)
1) 牛顿法的基本思想:
f ( x )  0 是非线性方程,一般较难解决,多采用线性化方法.
f ''( )
f ( x)  f ( x0 )  f '( x0 )( x  x0 )  ( x  x0 ) 2
2!
记: P( x)  f ( x0 )  f '( x0 )( x  x0 )

P( x ) 是一次多项式,用 P( x )  0 作为 f ( x )  0 的近似方程.
P( x)  f ( x0 )  f '( x0 )( x  x0 )  0 的解为
f ( x0 )
x  x0  ( f '( x0 )  0)
f '( x0 )

记为 x1 ,一般地,记

f ( xk )
xk 1  xk  k  0,1,2,
f '( xk )
即为牛顿法公式.
2) 牛顿法的收敛速度:
对牛顿法,迭代形式为:
f ( x)
x  x   ( x)
f' ( x )

[ f' ( x)]2  f ( x) f'' ( x) f ( x) f'' ( x)


' ( x )  1  
[ f' ( x )]2 [ f' ( x )]2

65
注意分子上的 f ( x* )  0 ,所以当 f' ( x* )  0 时,  ( x* )  0 ,牛顿法至少是二阶收
敛的,而在重根附近,牛顿法是线性收敛的.
牛顿法的缺点是:(1)对重根收敛很慢;(2)对初值 x0 要求较严,要求 x0 相当
接近真值 x* .
因此,常用其他方法确定初值 x0 ,再用牛顿法提高精度.

4. 求方程根(解)的其它方法
(1) solve('x^3-3*x+1=0')
(2) roots([1 0 -3 1])
(3) fzero('x^3-3*x+1', -2)
(4) fzero('x^3-3*x+1', 0.5)
(5) fzero('x^3-3*x+1', 1.4)
(6) linsolve([1, 2, 3; 4, 5, 6; 7, 8, 0], [1, 2, 3]')
体会一下,(2) (5) 用了上述 1 3 中的哪一种方法?

以下是本实验中的几个具体的实验,详细的程序清单参见附录.

具体实验 1:对分法
先作图观察方程: x 3  3 x  1  0 的实根的分布区间,再利用对分法在这些区
间上分别求出根的近似值.
输入以下命令,可得 f ( x ) 的图象:

f='x^3-3*x+1';
g='0';
ezplot(f, [-4, 4]);
hold on;
ezplot(g, [-4, 4]); %目的是画出直线 y=0,即 x 轴
grid on;
axis([-4 4 -5 5]);
hold off
请填写下表:
实根的分布区间
该区间上根的近似值
在某区间上求根的近似值的对分法程序参见附录 1.

具体实验 2:普通迭代法
采用迭代过程: xk 1   ( xk ) 求方程 x 3  3 x  1  0 在 0.5 附近的根,精确到第
4 位小数.
x3  1
构造等价方程: x 
3
x 3 1
用迭代公式: xk 1  k , k  0,1,2,
3
用 Matlab 编写的程序参见附录 2.
请利用上述程序填写下表:

66
k

xk

f ( xk )

分析:将附录 2 第 4 行中的 x  0.5 分别改为 x  2 以及 x  1.4 ,问运行的结


果是什么?你能分析得到其中的原因吗?看看下面的“具体实验 3”是想向你表
达一个什么意思.
用 Matlab 编写的程序参见附录 3.
具体实验 3:收敛/发散判断
设方程 x 3  3 x  1  0 的三个根近似地取 x1  0.347 , x2  1.53 和 x3  1.88 ,
这些近似值可以用上面的对分法求得.
xk 3  1
迭代形式一: xk 1 
3
1' ( x )  x 2
1' ( x1 )  0.120 收敛 (很可能收敛,下同)
1' ( x2 )  2.314  1 不收敛 (很可能不收敛,下同)
1' ( x3 )  3.534  1 不收敛
1
迭代形式二: xk 1 
3  xk2

2x
2' ( x ) 
(3  x 2 )2

2' ( x1 )  0.084 收敛
2' ( x2 )  7.044 不收敛
2' ( x3 )  13.167 不收敛
1
迭代形式三: xk 1  (3xk  1) 3

2

3' ( x )  (3x  1) 3

3' ( x1 )  8.410 不收敛


3' ( x2 )  0.426 收敛
3' ( x3 )  0.283 收敛

具体实验 4:迭代法的加速 1——松弛迭代法


x3  1 1
 ( x)  , ' ( x)  x 2 , k 
3 1  xk2

67
迭代公式为
xk3  1
xk 1  (1  k ) xk  k
3
程序参见附录 4.

具体实验 5:迭代法的加速 2——Altken 迭代法


迭代公式为:
3
(1) x3  1 x (1)  1
x k  k , x k( 2 )  k
3 3

( x k( 2 )  x k(1) ) 2
x k 1  x k( 2 )  , k  0,1,2,
x k( 2)  2 x k(1)  x k
程序参见附录 5.

具体实验 6:牛顿法
用牛顿法计算方程 x 3  3 x  1  0 在-2 到 2 之间的三个根.
提示: f ( x)  x 3  3x  1 , f '( x )  3 x 2  3 迭代公式:

2 xk 3  3xk  1
xk 1  x 
k
3 xk2  3
程序参见附录 6 (牛顿法程序).

具体实验 7:其他方法
求下列代数方程(组)的解:
(1) x 5  x  1  0
命令:solve('x^5-x+1=0')
2 x  3 y  0
(2)  2
4 x  3 y  1
命令:[x, y]=solve('2*x+3*y=0', '4*x^2+3*y=1')

1 2 3 4 5 1
2   2
 3 4 5 6  
(3) 求线性方程组 m  x  b 的解,已知 m   3 4 5 6 7 ,b   3
   
4 5 6 7 8  4
5 6 7 8 
0 5
  
命令:
for i=1:5
for j=1:5
m(i, j)=i+j-1;
end

68
end
m(5, 5)=0;
b=[1:5]'
linsolve(m, b)

2 1 0 0 0 0 0 0
1
 2 1 0 0 0 0 0 
0 1 2 1 0 0 0 0
 
0 0 1 2 1 0 0 0
思考:若 m   ,或 m 是类似的但阶数更大的稀疏方
0 0 0 1 2 1 0 0
 
0 0 0 0 1 2 1 0
0 0 0 0 0 1 2 1
 
0 0 0 0 0 0 1 2 
阵,则 m 应如何得到?

四、自己动手
1.对分法可以用来求偶重根附近的近似解吗? 为什么?
2.对照具体实验 2、4、5,你可以得出什么结论?
3.选择适当的迭代过程,分别使用:(1)普通迭代法;(2)与之相应的松
弛迭代法和 Altken 迭代法.求解方程 x 3  3 x  1  0 在 1.4 附近的根,精确到
4 位小数,请注意迭代次数的变化.
4.分别用对分法、普通迭代法、松弛迭代法、Altken 迭代法、牛顿切法线
等 5 种方法,求方程 t  x  sin( x) 的正的近似根,0  t  1 .(建议取 t  0.5 .时
间许可的话,可进一步考虑 t  0.25 的情况.)

五、附录
附录 1:对分法程序(fulu1.m)
syms x fx;
a=0;b=1;
fx=x^3-3*x+1;
x=(a+b)/2;k=0;
ffx=subs(fx, 'x', x);
if ffx==0;
disp(['the root is:', num2str(x)])
else disp('k ak bk f(xk)')
while abs(ffx)>0.0001 & a<b;
disp([num2str(k), ' ', num2str(a), ' ', num2str(b), ' ', num2str(ffx)])
fa=subs(fx, 'x', a);ffx=subs(fx, 'x', x);
if fa*ffx<0
b=x;

69
else
a=x;
end
k=k+1;x=(a+b)/2;
end
disp([num2str(k), ' ', num2str(a), ' ', num2str(b), ' ', num2str(ffx)])
end
注:实验时,可将第 2 行的 a、b 改为其它区间端点进行其它实验.

附录 2:普通迭代法(fulu2.m)
syms x fx gx;
gx=(x^3+1)/3;fx=x^3-3*x+1;
disp('k x f(x)')
x=0.5;k=0;
ffx=subs(fx, 'x', x);
while abs(ffx)>0.0001;
disp([num2str(k), ' ', num2str(x), ' ', num2str(ffx)]);
x=subs(gx, 'x', x);ffx=subs(fx, 'x', x);k=k+1;
end
disp([num2str(k), ' ', num2str(x), ' ', num2str(ffx)])

附录 3:收敛/发散判断(fulu3.m)
syms x g1 g2 g3 dg1 dg2 dg3;
x1=0.347;x2=1.53;x3=-1.88;
g1=(x^3+1)/3;dg1=diff(g1, 'x');
g2=1/(3-x^2);dg2=diff(g2, 'x');
g3=(3*x-1)^(1/3);dg3=diff(g3, 'x');
disp(['1 ', num2str(abs(subs(dg1, 'x', x1))), ' ', ...
num2str(abs(subs(dg1, 'x', x2))), ' ', num2str(abs(subs(dg1, 'x', x3)))])
disp(['2 ', num2str(abs(subs(dg2, 'x', x1))), ' ', ...
num2str(abs(subs(dg2, 'x', x2))), ' ', num2str(abs(subs(dg2, 'x', x3)))])
disp(['3 ', num2str(abs(subs(dg3, 'x', x1))), ' ', ...
num2str(abs(subs(dg3, 'x', x2))), ' ', num2str(abs(subs(dg3, 'x', x3)))])

附录 4:松弛迭代法(fulu4.m)
syms fx gx x dgx;
gx=(x^3+1)/3;fx=x^3-3*x+1;dgx=diff(gx, 'x');
x=0.5;k=0;
ggx=subs(gx, 'x', x);ffx=subs(fx, 'x', x);dgxx=subs(dgx, 'x', x);
disp('k x w')
while abs(ffx)>0.0001;
w=1/(1-dgxx);
disp([num2str(k), ' ', num2str(x), ' ', num2str(w)])
x=(1-w)*x+w*ggx;k=k+1;

70
ggx=subs(gx, 'x', x);ffx=subs(fx, 'x', x);dgxx=subs(dgx, 'x', x);
end
disp([num2str(k), ' ', num2str(x), ' ', num2str(w)])

附录 5: Altken 迭代法(fulu5.m)
syms x fx gx;
gx=(x^3+1)/3;fx=x^3-3*x+1;
disp('k x x1 x2')
x=0.5;k=0;
ffx=subs(fx, 'x', x);
while abs(ffx)>0.0001;
u=subs(gx, 'x', x);v=subs(gx, 'x', u);
disp([num2str(k), ' ', num2str(x), ' ', num2str(u), ' ', num2str(v)])
x=v-(v-u)^2/(v-2*u+x);k=k+1;ffx=subs(fx, 'x', x);
end
disp([num2str(k), ' ', num2str(x), ' ', num2str(u), ' ', num2str(v)])

附录 6:牛顿法(fulu6.m)
syms x fx gx;
fx=x^3-3*x+1;gx=diff(fx, 'x');
x1=-2;x2=0.5;x3=1.4;k=0;
disp('k x1 x2 x3')
fx1=subs(fx, 'x', x1);fx2=subs(fx, 'x', x2);fx3=subs(fx, 'x', x3);
gx1=subs(gx, 'x', x1);gx2=subs(gx, 'x', x2);gx3=subs(gx, 'x', x3);
while abs(fx1)>0.0001|abs(fx2)>0.0001|abs(fx3)>0.0001;
disp([num2str(k), ' ', num2str(x1), ' ', num2str(x2), ' ', num2str(x3)])
x1=x1-fx1/gx1;x2=x2-fx2/gx2;x3=x3-fx3/gx3;k=k+1;
fx1=subs(fx, 'x', x1);fx2=subs(fx, 'x', x2);fx3=subs(fx, 'x', x3);
gx1=subs(gx, 'x', x1);gx2=subs(gx, 'x', x2);gx3=subs(gx, 'x', x3);
end
disp([num2str(k), ' ', num2str(x1), ' ', num2str(x2), ' ', num2str(x3)])

71
实验四 求微分方程的解

一、问题背景与实验目的
实际应用问题通过数学建模所归纳而得到的方程,绝大多数都是微分方程,
真正能得到代数方程的机会很少.另一方面,能够求解的微分方程也是十分有限
的,特别是高阶方程和偏微分方程(组).这就要求我们必须研究微分方程(组)
的解法,既要研究微分方程(组)的解析解法(精确解),更要研究微分方程(组)
的数值解法(近似解).
对微分方程(组)的解析解法(精确解),Matlab 有专门的函数可以用,本实
验将作一定的介绍.
本实验将主要研究微分方程(组)的数值解法(近似解),重点介绍 Euler 折线
法.

二、相关函数(命令)及简介
1.dsolve('equ1','equ2',…):Matlab 求微分方程的解析解.equ1、equ2、…为
方程(或条件).写方程(或条件)时用 Dy 表示 y 关于自变量的一阶导数,用
用 D2y 表示 y 关于自变量的二阶导数,依此类推.
2.simplify(s):对表达式 s 使用 maple 的化简规则进行化简.
例如:
syms x
simplify(sin(x)^2 + cos(x)^2)
ans=1
3.[r,how]=simple(s):由于 Matlab 提供了多种化简规则,simple 命令就是
对表达式 s 用各种规则进行化简,然后用 r 返回最简形式,how 返回形成这种
形式所用的规则.
例如:
syms x
[r,how]=simple(cos(x)^2-sin(x)^2)
r = cos(2*x)
how = combine
4.[T,Y] = solver(odefun,tspan,y0) 求微分方程的数值解.
说明:
(1) 其中的 solver 为命令 ode45、ode23、ode113、ode15s、ode23s、ode23t、
ode23tb 之一.
 dy
  f (t , y )
(2) odefun 是显式常微分方程:  dt
 y (t 0 )  y 0

(3) 在积分区间 tspan= [t 0 , t f ] 上,从 t 0 到 t f ,用初始条件 y 0 求解.

(4) 要 获 得 问 题 在 其 他 指 定 时 间 点 t 0 , t1 , t 2,  上 的 解 , 则 令 tspan=

72
[t 0 , t1 , t 2, , t f ] (要求是单调的).

(5) 因为没有一种算法可以有效地解决所有的 ODE 问题,为此,Matlab 提


供了多种求解器 Solver,对于不同的 ODE 问题,采用不同的 Solver.

求解器 ODE 类型 特点 说明
Solver
ode45 非刚性 单步算法;4、5 阶 Runge-Kutta 大部分场合的首选算

方程;累计截断误差达 (x ) 3

ode23 非刚性 单步算法;2、3 阶 Runge-Kutta 使用于精度较低的情



方程;累计截断误差达 (x ) 3

ode113 非刚性 多步法;Adams 算法;高低精 计算时间比 ode45 短


度均可到 10 3 ~ 10 6
ode23t 适度刚性 采用梯形算法 适度刚性情形
ode15s 刚性 多步法;Gear's 反向数值微分; 若 ode45 失效时,可
精度中等 尝试使用
ode23s 刚性 单步法;2 阶 Rosebrock 算法; 当精度较低时,计算时
低精度 间比 ode15s 短
ode23tb 刚性 梯形算法;低精度 当精度较低时,计算时
间比 ode15s 短

(6) 要特别的是:ode23、ode45 是极其常用的用来求解非刚性的标准形式的


一阶常微分方程(组)的初值问题的解的 Matlab 的常用程序,其中:
ode23 采用龙格-库塔 2 阶算法,用 3 阶公式作误差估计来调节步长,具有
低等的精度.
ode45 则采用龙格-库塔 4 阶算法,用 5 阶公式作误差估计来调节步长,具
有中等的精度.
5.ezplot(x,y,[tmin,tmax]):符号函数的作图命令.x,y 为关于参数 t 的符号
函数,[tmin,tmax] 为 t 的取值范围.
6.inline():建立一个内联函数.格式:inline('expr', 'var1', 'var2',…) ,注意
括号里的表达式要加引号.
例:Q = dblquad(inline('y*sin(x)'), pi, 2*pi, 0, pi)

三、实验内容
1. 几个可以直接用 Matlab 求微分方程精确解的例子:
dy 2
例 1:求解微分方程  2 xy  xe  x ,并加以验证.
dx
求解本问题的 Matlab 程序为:
syms x y %line1
y=dsolve('Dy+2*x*y=x*exp(-x^2)','x') %line2

73
diff(y,x)+2*x*y-x*exp(-x^2) %line3
simplify(diff(y,x)+2*x*y-x*exp(-x^2)) %line4
说明:
(1) 行 line1 是用命令定义 x,y 为符号变量.这里可以不写,但为确保正确性,
建议写上;
(2) 行 line2 是用命令求出的微分方程的解:
1/2*exp(-x^2)*x^2+exp(-x^2)*C1
(3) 行 line3 使用所求得的解.这里是将解代入原微分方程,结果应该为 0,
但这里给出:
-x^3*exp(-x^2)-2*x*exp(-x^2)*C1+2*x*(1/2*exp(-x^2)*x^2+exp(-x^2)*C1)
(4) 行 line4 用 simplify() 函数对上式进行化简,结果为 0, 表明 y  y (x ) 的

确是微分方程的解.
例 2:求微分方程 xy ' y  e x  0 在初始条件 y (1)  2e 下的特解,并画出解函
数的图形.
求解本问题的 Matlab 程序为:
syms x y
y=dsolve('x*Dy+y-exp(x)=0','y(1)=2*exp(1)','x')
ezplot(y)
e  ex
微分方程的特解为:y=1/x*exp(x)+1/x* exp (1) (Matlab 格式),即 y  ,
x
解函数的图形如图 1:
1/x exp(x)+1/x exp(1)

50

40

30

20

10

-10

-20

-30
-6 -4 -2 0 2 4 6
x

图1
 dx
 5x  y  e t
 dt
例 3:求微分方程组  在初始条件 x |t 0  1, y | t 0  0 下的特解,
dy
  x  3y  0
 dt

并画出解函数的图形.

74
求解本问题的 Matlab 程序为:
syms x y t
[x,y]=dsolve('Dx+5*x+y=exp(t)','Dy-x-3*y=0','x(0)=1','y(0)=0','t')
simple(x);
simple(y);
ezplot(x,y,[0,1.3]);axis auto
微分方程的特解(式子特别长)以及解函数的图形均略.
2. 用 ode23、ode45 等求解非刚性的标准形式的一阶常微分方程(组)的初值问
题的数值解(近似解).
 dy 2
  2 y  2 x  2 x
例 4:求解微分方程初值问题  dx 的数值解,求解范围为区
 y (0)  1

间[0, 0.5].
fun=inline('-2*y+2*x^2+2*x','x','y');
[x,y]=ode23(fun,[0,0.5],1);
x';
y';
plot(x,y,'o-')
>> x'
ans =
0.0000 0.0400 0.0900 0.1400 0.1900 0.2400
0.2900 0.3400 0.3900 0.4400 0.4900 0.5000
>> y'
ans =
1.0000 0.9247 0.8434 0.7754 0.7199 0.6764
0.6440 0.6222 0.6105 0.6084 0.6154 0.6179
图形结果为图 2.
1

0.95

0.9

0.85

0.8

0.75

0.7

0.65

0.6
0 0.05 0.1 0.15 0.2 0.25 0.3 0.35 0.4 0.45 0.5

图2

例 5:求解描述振荡器的经典的 Ver der Pol 微分方程

75
d2y dy
2
  (1  y 2 )  y  0, y (0)  1, y ' (0)  0,   7.
dt dt

dx1 dx dx 2
分析:令 x1  y , x 2  , 则 1  x 2 , 2   (1  x1 ) x 2  x1 .
dt dt dt
先编写函数文件 verderpol.m:
function xprime = verderpol(t,x)
global mu;
xprime = [x(2);mu*(1-x(1)^2)*x(2)-x(1)];
再编写命令文件 vdp1.m:
global mu;
mu = 7;
y0=[1;0]
[t,x] = ode45('verderpol',[0,40],y0);
x1=x(:,1);x2=x(:,2);
plot(t,x1)
图形结果为图 3.
2.5

1.5

0.5

-0.5

-1

-1.5

-2

-2.5
0 5 10 15 20 25 30 35 40

图3
3. 用 Euler 折线法求解
前面讲到过,能够求解的微分方程也是十分有限的.下面介绍用 Euler 折线
法求微分方程的数值解(近似解)的方法.
Euler 折线法求解的基本思想是将微分方程初值问题
 dy
  f ( x, y ),
 dx
 y ( x0 )  y 0

y ( x  h)  y ( x ) dy
化成一个代数方程,即差分方程,主要步骤是用差商 替代微商 ,
h dx
于是:

76
 y ( x k  h)  y ( x k )
  f ( x k , y ( x k )),
 h
 y 0  y ( x0 )
记 x k 1  x k  h, y k  y ( x k ) ,从而 y k 1  y ( x k  h) ,则有
 y 0  y ( x0 ),

 x k 1  x k  h, k  0,1,2,  , n  1
 y  y  hf ( x , y ).
 k 1 k k k

例 6:用 Euler 折线法求解微分方程初值问题


 dy 2x
  y 2 ,
 dx y
 y (0)  1

的数值解(步长 h 取 0.4),求解范围为区间[0,2].
解:本问题的差分方程为
 x  0, y  1, h  0.4,
 0 0

 x  x  h,
 k 1 k k  0,1,2, , n  1
 2x
 y k 1  y k  hf ( x k , y k ) (其中:f ( x, y )  y  2 ).
 y
相应的 Matlab 程序见附录 1.
数据结果为:
0 1.0000
0.4000 1.4000
0.8000 2.1233
1.2000 3.1145
1.6000 4.4593
2.0000 6.3074
图形结果见图 4:
7

1
0 0.2 0.4 0.6 0.8 1 1.2 1.4 1.6 1.8 2

图4

77
特别说明:本问题可进一步利用四阶 Runge-Kutta 法求解,读者可将两个结
果在一个图中显示,并和精确值比较,看看哪个更“精确”?(相应的 Matlab 程
序参见附录 2).

四、自己动手

1. 求微分方程 ( x 2  1) y '2 xy  sin x  0 的通解.

2. 求微分方程 y ' '2 y '5 y  e x sin x 的通解.


3. 求微分方程组
 dx
 dt  x  y  0

 dy  x  y  0
 dt

在初始条件 x |t 0  1, y | t 0  0 下的特解,并画出解函数 y  f ( x ) 的图形.

4. 分别用 ode23、ode45 求上述第 3 题中的微分方程初值问题的数值解(近


似解),求解区间为 t  [0,2] .利用画图来比较两种求解器之间的差异.

5. 用 Euler 折线法求解微分方程初值问题
 12 x 2
 y'  y  3 ,
 y
 y ( 0)  1

的数值解(步长 h 取 0.1),求解范围为区间[0,2].
6. 用四阶 Runge-Kutta 法求解微分方程初值问题
 y '  y  e x cos x,

 y ( 0)  1
的数值解(步长 h 取 0.1),求解范围为区间[0,3].
四 阶 Runge-Kutta 法的迭代公式为 (Euler 折线法实为一阶 Runge-Kutta
法):

78

 y 0  y ( x0 ),

 x k 1  x k  h,
 h
 y k 1  y k  ( L1  2 L2  2 L3  L4 )
 6
L1  f ( x k , y k ) k  0,1,2, , n  1
 h h
L2  f ( x k  , y k  L1 )
 2 2
 h h
L3  f ( x k  , y k  L2 )
 2 2
L4  f ( x k  h, y k  hL3 )
相应的 Matlab 程序参见附录 2.试用该方法求解第 5 题中的初值问题.
7. 用 ode45 方法求上述第 6 题的常微分方程初值问题的数值解(近似解),
从而利用画图来比较两者间的差异.

五、附录
附录 1:(fulu1.m)
clear
f=sym('y+2*x/y^2');
a=0;
b=2;
h=0.4;
n=(b-a)/h+1;
x=0;
y=1;
szj=[x,y];
for i=1:n-1
y=y+h*subs(f,{'x','y'},{x,y});
x=x+h;
szj=[szj;x,y];
end
szj
plot(szj(:,1),szj(:,2))

附录 2:(fulu2.m)
clear
f=sym('y-exp(x)*cos(x)');
a=0;
b=3;
h=0.1;
n=(b-a)/h+1;
x=0;
y=1;

79
szj=[x,y];
for i=1:n-1
l1=subs(f,{'x','y'},{x,y});
l2=subs(f,{'x','y'},{x+h/2,y+l1*h/2});
l3=subs(f,{'x','y'},{x+h/2,y+l2*h/2});
l4=subs(f,{'x','y'},{x+h,y+l3*h});
y=y+h*(l1+2*l2+2*l3+l4)/6;
x=x+h;
szj=[szj;x,y];
end
szj
plot(szj(:,1),szj(:,2))

80
实验五 数据的统计分析

一、问题背景与实验目的
在日常生活中我们会在很多事件中收集到一些数据(比如:考试分数、窗口
排队人数、月用电量、灯泡寿命、测量误差、产品质量、月降雨量等数据),这
些数据的产生一般都是随机的.这些随机数据乍看起来并没有什么规律,但通过
数理统计的研究发现:这些随机数还是符合着某种分布规律的,这种规律被称为
统计规律.
本实验旨在通过对概率密度函数曲线的直观认识、对数据分布的形态猜测、
对某些概率分布的密度函数的参数估计(以正态为例)以及进行简单的正态假设
检验,来揭示生活中的随机数据的一些统计规律.

二、相关函数(命令)及简介
1. 概率密度函数 pdf 系列.以 normpdf( )为例,调用格式:
y=normpdf(x, mu,sigma),
计算参数为 mu 和 sigma 的样本数据 x 的正态概率密度函数.参数 sigma 必须为
正.其中:mu 为均值,sigma 为标准差.
2. 参数估计 fit 系列.以 normfit( )为例,调用格式:
[muhat, sigmahat, muci, sigmaci] = normfit(x, alpha),
对样本数据 x 进行参数估计,并计算置信度为 100(1-alpha)%的置信区间.如
alpha=0.01 时,则给出置信度为 99%的置信区间.不写明 alpha,即表示 alpha 取
0.05.
3.load( )函数.调用格式:
S = load('数据文件')
将纯数据文件(文本文件)中的数据导入 Matlab,S 是双精度的数组,其行
数、列数与数据文件相一致.
4. hist(x, m)函数:画样本数据 x 的直方图,m 为直方图的条数,缺省值为 10.
5. tabulate( )函数:绘制频数表.返回 table 矩阵,第一列包含 x 的值,第二列
包含该值出现次数,最后一列包含每个值的百分比.
6.ttest(x,m,alpha) 函数:假设检验函数.此函数对样本数据 x 进行显著性水
平为 alpha 的 t 假设检验,以检验正态分布样本 x(标准差未知)的均值是否为
m.h=1 表示拒绝零假设,h=0 表示不能拒绝零假设.
7.normplot(x)或 weibplot(x) 函数:统计绘图函数,进行正态分布检验.
研究表明:如果数据是来自一个正态分布,则该线为一直线形态;如果它是
来自其他分布,则为曲线形态.

完全类似地可探索以下一系列函数的用法与作用:
8.累积分布函数 cdf 系列,如:normcdf( ).
9.逆累积分布函数 inv 系列,如:norminv( ).
10.随机数发生函数 rnd 系列,如:normrnd( ).
11.均值与方差函数 stat 系列,如:normstat( ).

81
三、实验内容
1. 常见的概率分布的密度函数及其图形
1)常见概率分布的密度函数(20 个,打√的 10 个将在后面作介绍)
序号 中文函数名 英文函数名 英文简写 备注
1 Beta 分布 Beta beta
2 二项分布 Binomial bino √
3 卡方分布 Chisquare chi2 √抽样
4 指数分布 Exponential exp √
5 F 分布 F f √抽样
6 Gamma 分布 Gamma gam
7 几何分布 Geometric geo √
8 超几何分布 Hypergeometric hyge
9 对数正态分布 Lognormal logn
10 负二项式分布 Negative Binomial nbin
11 非中心 F 分布 Noncentral F ncf
12 非中心 t 分布 Noncentral t nct
13 非中心卡方分布 Noncentral Chi-square ncx2
14 正态分布 Normal norm √
15 泊松分布 Poisson poiss √
16 瑞利分布 Rayleigh rayl
17 T 分布 T t √抽样
18 均匀分布 Uniform unif √
19 离散均匀分布 Discrete Uniform unid √
20 Weibull 分布 Weibull weib

2)常见概率分布的密度函数文字说明与图形演示:

(A)常见连续分布的密度函数
(1)正态分布
若连续型随机变量 X 的密度函数为:
( x   )2
1 
2 2
f ( x)  e ,   x  ,  0
 2
则称 X 为服从正态分布的随机变量,记作 X ~ N ( , 2 ) .特别地,称   0,   1
时的正态分布 N (0,1) 为标准正态分布,其概率分布的密度函数参见图 1.一个非
标准正态分布的密度函数参见图 2 中的虚线部分(   1,   2 ).
正态分布是概率论与数理统计中最重要的一个分布,高斯(Gauss)在研究误差
理论时首先用正态分布来刻画误差的分布,所以正态分布又称高斯分布.一个变
量如果是由大量微小的、独立的随机因素的叠加效果,那么这个变量一定是正态
变量.比如测量误差、产品质量、月降雨量等都可用正态分布描述.
x=-8:0.1:8;
y=normpdf(x, 0, 1);
y1=normpdf(x, 1, 2);

82
plot(x, y, x, y1, ':' );
0.4 0.4

0.35 0.35

0.3 0.3

0.25 0.25

0.2 0.2

0.15 0.15

0.1 0.1

0.05 0.05

0 0
-8 -6 -4 -2 0 2 4 6 8 -8 -6 -4 -2 0 2 4 6 8

图 1 标准正态分布 图 2 标准正态与非标准正态

(2)均匀分布(连续)
若随机变量 X 的密度函数为
 1
 , axb
f ( x)   b  a
0, 其他
则称 X 服从区间 [a, b] 上的均匀分布(连续),记作 X ~ U [a, b] ,其概率分布的密
度函数见参见图 3 (a  0, b  2 ) .
均匀分布在实际中经常使用,譬如一个半径为 r 的汽车轮胎,因为轮胎上的
任一点接触地面的可能性是相同的,所以轮胎圆周接触地面的位置 X 是服从
[0, 2 r ] 上的均匀分布,这只要看一看报废轮胎四周磨损程度几乎是相同的就可
明白均匀分布的含义了.
x=-10:0.01:10;r=1;
y=unifpdf(x, 0, 2*pi*r);
plot(x, y);
0.16 0.25

0.14

0.2
0.12

0.1
0.15

0.08

0.1
0.06

0.04
0.05

0.02

0 0
-10 -8 -6 -4 -2 0 2 4 6 8 10 0 5 10 15 20 25 30

图 3 均匀分布(连续) 图4 指数分布

(3)指数分布
若连续型随机变量 X 的密度函数为:

83
 e   x , x  0
f ( x)   其中   0 ,
0, x0

则称 X 为服从参数为  的指数分布的随机变量,记作 X ~ Exp( ) .

在实际应用问题中,等待某特定事物发生所需要的时间往往服从指数分
布.如某些元件的寿命;某人打一个电话持续的时间;随机服务系统中的服务时
间;动物的寿命等都常假定服从指数分布.
指数分布的重要性还在于它是具有无记忆性的连续型随机变量.即:设随机
变量 X 服从参数为  的指数分布,则对任意的实数 s  0, t  0 ,有
P{ X  s  t | X  s}  P{ X  t},
其概率分布的密度函数参见见图 4 (  4) .
x=0:0.1:30;
y=exppdf(x, 4);
plot(x, y)

(B)常见离散分布的密度函数

(4)几何分布
在一个贝努里实验中,每次试验成功的概率为 p ,失败的概率为 q  1  p
(0  p  1) ,设试验进行到第  次才出现成功,则  的分布列为:
P(  k )  pq k 1 , k  1,2,

容易看到 pq k 1
(k  1, 2,) 是几何级数  pq k 1 的一般项,于是人们称它为几何分
k 1

布,其概率分布的密度函数参见图 5 ( p  0.5) .
x=0:30;
y=geopdf(x, 0.5);
plot(x, y)
0.5 0.09

0.45 0.08

0.4
0.07

0.35
0.06

0.3
0.05

0.25

0.04
0.2

0.03
0.15

0.02
0.1

0.05 0.01

0 0
0 5 10 15 20 25 30 0 5 10 15 20 25 30 35 40 45 50

图 5 几何分布 图 6 二项分布

(5)二项分布
如果随机变量 X 的分布列为:

84
n
P( X  k )    p k (1  p ) n k , k  0,1,, n
k 
则这个分布称为二项分布,记为 X ~ b(n, p) .当 n  1 时的二项分布又称为 0-1 分
布,分布律为
X 0 1
P 1 p p

一般的二项分布的密度函数参见图 6 (n  500, p  0.05) .


x=0:50;
y=binopdf(x, 500, 0.05);
plot(x, y);

(6)泊松(Poisson)分布
泊松分布是 1837 年由法国数学家泊松(Poisson S.D.1781-1840)首次提出的,
其概率分布列是:
k
P( X  k )  e   , k  0, 1, 2, ,  0
k!

记为 X ~ P( ) ,其概率分布的密度函数参见图 7 (  25) .


泊松分布是一种常用的离散分布,它与单位时间(或单位面积、单位产品等)
上的计数过程相联系,譬如:单位时间内,电话总机接到用户呼唤次数;1 平方
米内,玻璃上的气泡数;一铸件上的砂眼数;在单位时间内,某种放射性物质分
裂到某区域的质点数等等.
x=0:50;
y=poisspdf(x, 25);
plot(x, y);

注:对比二项分布的概率密度函数图可以发现,当二项分布的 n  p 与泊松分
布  充分接近时,两图拟合程度非常高(图 6 与图 7 中的 n  p  20   ),直观地
验证了泊松定理(泊松分布是二项分布的极限分布),请对比图 6 与图 7.
0.08 1.5

0.07

1
0.06

0.05
0.5

0.04

0
0.03

0.02
-0.5

0.01

0 -1
0 5 10 15 20 25 30 35 40 45 50 0 2 4 6 8 10 12 14 16 18 20

图 7 泊松分布 图 8 均匀分布(离散)

(7)均匀分布(离散)

85
如果随机变量 X 的分布列为:
1
P ( X  k )  , k  1, 2,  , n
n
则这个分布称为离散均匀分布,记为 X ~ U ( [1, 2, , n] ) ,其概率分布的密度函
数参见图 8 (n  20) .
n=20;
x=1:n;
y=unidpdf(x, n);
plot(x, y, 'o-' );

(C)三大抽样分布的密度函数
(8)  2 分布
设随机变量 X 1, X 2,  , X n 相互独立,且同服从正态分布 N (0,1) ,则称随机变
量  n2  X 12  X 22    X n2 服从自由度为 n 的  2 分布,记作  n2 ~  2 (n) ,亦称随
机变量  n2 为  2 变量.其概率分布的密度函数参见图 9 (n  4) 、图 10 (n  10) , 2
分布的密度函数解析式参见本章的附录表格.
x=0:0.1:20; x=0:0.1:20;
y=chi2pdf(x, 4); y=chi2pdf(x, 10);
plot(x, y); plot(x, y)
0.2 0.1

0.18 0.09

0.16 0.08

0.14 0.07

0.12 0.06

0.1 0.05

0.08 0.04

0.06 0.03

0.04 0.02

0.02 0.01

0 0
0 2 4 6 8 10 12 14 16 18 20 0 2 4 6 8 10 12 14 16 18 20

图 9  2 分布 (n  4) 图 10  2 分布 (n  10)

(9) F 分布
设随机变量 X ~  2 (m) , Y ~  2 (n) ,且 X 与 Y 相互独立,则称随机变量
X /m
F
Y /n
服从自由度为 (m, n) 的 F 分布,记作 F ~ F (m, n) ,其概率分布的密度函数参见图
11,即 F (4,10) , F 分布的密度函数解析式参见本章的附录表格.
x=0.01:0.1:8.01;
y=fpdf(x, 4, 10);
plot(x, y)

86
0.7 0.4

0.35
0.6

0.3
0.5

0.25
0.4

0.2

0.3
0.15

0.2
0.1

0.1
0.05

0 0
0 1 2 3 4 5 6 7 8 9 -6 -4 -2 0 2 4 6

图 11 F 分布 图 12 t 分布

(10) t 分布
设随机变量 X ~ N (0,1), Y ~  2 (n) ,且 X 与 Y 相互独立,则称随机变量
X
T
Y /n
服从于自由度为 n 的 t 分布,记作 T ~ t (n) ,其概率分布的密度函数参见图 12,
即 t (4) . t 分布的密度函数解析式参见本章的附录表格.
细心的读者可能已经发现,图 12 的 t 分布图与图 1、图 2 的正态分布十分相
似.可以证明:当 n   时, t 分布趋于标准正态分布 N (0,1) .
x=-6:0.01:6;
y=tpdf(x, 4);
plot(x, y)

2.对给定数据画频数直方图(Histogram)或频数表(Frequency Table)
假定有若干个给定的数据集,它们满足上述 10 种分布之一,我们现在的任
务就是利用画频数直方图等手段,确定它们到底服从哪一类分布.

例 1:某一次书面考试的分数罗列如下,试画频数直方图.
鉴于数据的数量较大(包含有 120 个数据),可以先在一个文本文件中输入,
保存为 data1.txt.
75 69 100 80 70 74 78 59 72 73
63 79 69 81 62 87 80 66 86 75
70 85 85 64 78 65 69 67 78 72
60 50 57 83 77 79 78 74 67 83
71 67 71 74 84 74 83 75 73 74
60 91 65 69 80 63 86 67 73 80
74 68 72 80 95 61 77 85 82 71
80 76 83 69 87 76 72 69 66 86
74 87 59 81 88 75 83 71 77 81
88 67 67 76 71 76 79 79 90 62
80 85 81 75 72 57 94 91 83 78
66 74 79 74 82 79 87 76 81 68

87
x=load('data1.txt');
x=x(:);
hist(x)
结果参见图 13.从图形形态上来看,图 13 较为接近图 2 所示的正态分布.
30 16

14
25

12

20
10

15 8

6
10

5
2

0 0
50 55 60 65 70 75 80 85 90 95 100 50 55 60 65 70 75 80 85 90 95 100

图 13 例 1 的频数直方图 图 14 例 2 的频数直方图

例 2:某一次上机考试的分数罗列如下(data2.txt,包含有 130 个数据),试画频数


直方图.

51 70 95 91 70 83 83 96 66 61
79 79 57 85 95 83 63 71 71 72
91 60 69 100 67 87 72 50 60 63
87 98 71 74 96 55 83 67 92 78
56 62 77 79 84 55 59 61 93 56
82 61 88 97 98 95 73 79 81 87
56 92 53 57 93 89 77 89 56 92
99 86 68 57 91 57 81 65 80 99
79 95 79 86 74 56 70 61 72 81
57 75 98 89 69 61 71 77 72 78
70 73 67 59 62 86 84 93 82 80
90 94 84 89 80 67 97 73 80 94
69 64 51 51 92 62 52 86 67 97

x=load('data2.txt');
x=x(:);
hist(x)

结果参见图 14.图 14 看上去很接近图 8 所示的均匀分布(离散).

例 3:以下给出上海 1998 年来的月降雨量的数据(data3.txt,包含有 98 个数据):


1184.4 1113.4 1203.9 1170.7 975.4 1462.3 947.8
1416.0 709.2 1147.5 935 1016.3 1031.6 1105.7
849.9 1233.4 1008.6 1063.8 1004.9 1086.2 1022.5
1330.9 1439.4 1236.5 1088.1 1288.7 1115.8 1217.5

88
1320.7 1078.1 1203.4 1480.0 1269.9 1049.2 1318.4
1192.0 1016.0 1508.2 1159.6 1021.3 986.1 794.7
1318.3 1171.2 1161.7 791.2 1143.8 1602.0 951.4
1003.2 840.4 1061.4 958.0 1025.2 1265.0 1196.5
1120.7 1659.3 942.7 1123.3 910.2 1398.5 1208.6
1305.5 1242.3 1572.3 1416.9 1256.1 1285.9 984.8
1390.3 1062.2 1287.3 1477.0 1011.9 1217.7 1197.1
1143.0 1018.8 1243.7 909.3 1030.3 1124.4 811.4
820.9 1184.1 1107.5 991.4 901.7 1176.5 1113.5
1272.9 1200.3 1508.7 772.3 813.0 1392.3 1006.2

x=load('data3.txt');
x=x(:);
hist(x)

结果参见图 15.图 15 看上去很接近图 10 所示的  2 分布.

20 12

18

10
16

14
8

12

10 6

4
6

4
2

0 0
700 800 900 1000 1100 1200 1300 1400 1500 1600 1700 1 1.5 2 2.5 3 3.5 4 4.5 5 5.5 6

图 15 例 3 的频数直方图 图 16 例 4 的频数直方图

在重复数据较多的情况下,我们也可以利用 Matlab 自带的函数 tabulate( )产


生频数表,并以频数表的形式来发掘数据分布的规律.
例 4:给出以下数据:(data4.txt,含有 46 个数据)
2 3 6 4 1 5 1 2 3 1 4 2 3 1 3 3 2 3 1 6 4 6 4
6 5 4 3 6 4 3 3 3 3 4 4 5 6 2 1 2 3 4 5 6 5 4
则:
x=load('data4.txt');
x=x(:);
tabulate(x)
hist(x, 6)
Value Count Percent
1 6 13.04%
2 6 13.04%
3 12 26.09%
4 10 21.74%

89
5 5 10.87%
6 7 15.22%
结果参见图 16.图 16 看上去好象没有什么规律可循.

例 5:现累积有 100 次刀具故障记录,当故障出现时该批刀具完成的零件数如下:


(data5.txt)
459 362 624 542 509 584 433 748 815 505
612 452 434 982 640 742 565 706 593 680
926 653 164 487 734 608 428 1153 593 844
527 552 513 781 474 388 824 538 862 659
775 859 755 49 697 515 628 954 771 609
402 960 885 610 292 837 473 677 358 638
699 634 555 570 84 416 606 1062 484 120
447 654 564 339 280 246 687 539 790 581
621 724 531 512 577 496 468 799 544 645
764 558 378 765 666 763 217 715 310 851

x=load('data5.txt');
x=x(:);
hist(x) %%结果参见图 17,很象图 2 所示的正态分布
figure
histfit(x) %%结果参见图 18,加入了较接近的正态分布的密度曲线

25 25

20 20

15 15

10 10

5 5

0 0
0 200 400 600 800 1000 1200 -200 0 200 400 600 800 1000 1200 1400

图 17 例 5 的 hist(x) 图 18 例 5 的 histfit(x)

3. 参数估计
当我们可以基本确定数据集 X 符合某种分布时,下一步我们就该确定这个分
布的参数了.由于正态分布情况发生的比较多,故一般我们首先考虑的分布将是
正态分布.考虑最多的也是正态分布情况.
对于未知参数的估计,可分两种情况:点估计与区间估计.
(1)点估计:构造样本 X 与某个统计量有关的一个函数,作为该统计量的
一个估计,称为点估计.Matlab 统计工具箱中,一般采用最大似然估计法给出参
数的点估计.可以证明:
① 正态分布 N (  ,  2 ) 中,  最大似然估计是 ̂  X ,  2 的最大似然估计是

90
1 n 2
ˆ 2   (X i  X ) ;
n i 1

② 泊松分布 P( ) 的  最大似然估计是   X ;


1
③ 指数分布 Exp( ) 的  最大似然估计是   ,等等.
X
例 6:已知上述例 1 的数据服从正态分布 N (  ,  2 ) ,试求出  和  2 的值.
解: x=load('data1.txt');
x=x(:);
[mu, sigma] = normfit(x)
mu =
75.3417
sigma =
8.8768
因此,  =mu=75.3412,  2 =sigma2=8.87682=78.7982.
(2)区间估计:构造样本 X 与某个统计量有关的两个函数,作为该统计量
的下限估计与上限估计,下限与上限一般能够构成一个区间.这个区间作为该统
计量的估计,称为区间估计.Matlab 统计工具箱中,一般也采用最大似然估计法
给出参数的区间估计.

例 7:已知上述例 1 的数据集 X 服从正态分布 N (  ,  2 ) ,试求出  和  的置信度


为 95%的区间估计.
解: x=load('data1.txt');
x=x(:);
[mu, sigma muci, sigmaci] = normfit(x)
mu =
75.3417
sigma =
8.8768
muci =
73.7371
76.9462
sigmaci =
7.8781
10.1678
因此,73.7371    76.9462,7.8781    10.1678.

例 8:从自动机床加工的同类零件中抽取 16 件,测得长度值为(data6.txt):
12.15 12.12 12.01 12.08 12.09 12.16 12.06 12.13

91
12.07 12.11 12.08 12.01 12.03 12.01 12.03 12.06
已知零件长度服从正态分布 N (  ,  2 ) ,求零件长度的均值  和标准差  的置信度
为 99%的置信区间.
解: x=load('data6.txt');
x=x(:);
[mu, sigma, muci, sigmaci] = normfit(x, 0.01)
mu =
12.0750
sigma =
0.0494
muci =
12.0386
12.1114
sigmaci =
0.0334
0.0892
其中 muci(1)、muci(2)分别是平均值  在 99%置信度下的上下限;而 sigmaci(1)、

sigmaci(2)分别是标准差  在 99%置信度下的上下限.

4.正态假设检验
对总体的分布律或分布参数作某种假设,根据抽取的样本观察值,运用数理
统计的分析方法,检验这种假设是否正确,从而决定接受假设或拒绝假设,这就
是假设检验问题.这里仅以正态假设检验为例,来说明假设检验的基本过程.
正态假设检验的一般过程是:
(1)对比正态分布的概率密度函数图,判断某统计量的分布可能服从正态
分布;
(2)利用统计绘图函数 normplot( )或 weibplot( )进行正态分布检验.
(3)假设检验:利用 Matlab 统计工具箱给出的常用的假设检验方法的函数
ttest(x,m,alpha),进行显著性水平为 alpha 的 t 假设检验,以检验正态分布样本 x
(标准差未知)的均值是否为 m.运行结果中,当 h=1 时,表示拒绝零假设;当
h=0 时,表示不能拒绝零假设.

例 9:试说明例 5 所示的刀具的使用寿命服从正态分布,并且说明在方差未知的
情况下其均值 m 取为 597 是否合理?
解:(1)对比正态分布的概率密度函数图(图 17、图 18)以及对正态分布
的描述(一个变量如果是由大量微小的、独立的随机因素的叠加效果,那么这个
变量一定是正态变量.比如测量误差、产品质量等都可用正态分布描述),可得
初步结论:该批刀具的使用寿命可能服从正态分布.
(2)利用统计绘图函数 normplot(x) 进行分布的正态性检验.由于:
x=load('data5.txt');
x=x(:);
normplot(x)

92
Normal Probability Plot
0.997

0.99
0.98

0.95

0.90

0.75

Probability
0.50

0.25

0.10

0.05

0.02
0.01

0.003
100 200 300 400 500 600 700 800 900 1000 1100
Data

图 19 刀具寿命分布正态性检验
结果如图 19 所示,经观察这 100 个离散点非常靠近倾斜直线段,图形为线
性的,因此可得出结论:该批刀具的使用寿命近似服从正态分布.
(3)利用函数 ttest(x,m,alpha)进行显著性水平为 alpha 的 t 假设检验.由于:
x=load('data5.txt');
x=x(:);
h=ttest(x,597,0.05)
得:h = 0
检验结果:h=0,表示不拒绝零假设,说明所提出的假设“寿命均值为 597”
是合理的.
读者可以验证:当执行 h=ttest(x,555,0.05),将得到 h = 1,表示拒绝零假设.请
读者自行解释此结果的含义.

四、自己动手
1.了解本实验中虽已提及但没有详细介绍的其余 10 种概率分布的密度函数,
如 Beta 分布、Gamma 分布、Weibull 分布等,写出它们的概率分布的密度函数
表达式(本实验的附录中已经列出一部分),并画出相应的图形.
2.写出本实验所列出的 10 种概率累积分布函数表达式,并画出相应的概率
累积分布函数图形.
3.用 tabulate( )函数将例 1、例 2 的分数数据按频数表的方式进行统计,每 5
分为一个分数段(可参见例 4),观察数据分布有什么规律.
4.用 weibplot(x)函数进行例 9 的正态分布检验,比较与例 9 的差别.
5.例 3 给出的上海 1998 年来的月降雨量的数据(data3.txt) 看上去很接近图
10 所示的  2 分布,但  2 分布好象没有直接进行参数估计的函数,试寻求对此
数据进行参数估计的可能方法.
6.向例 3 给出的上海 1998 年来的月降雨量的数据(data3.txt) 中“补充”一
些数据,使其看上去很接近正态分布,并求此时的均值  和标准差  的点估计与
置信度为 97%的区间估计.
7.在第 6 题基础上,说明在方差未知的情况下,其均值  取为 1150 是否合
理?

93
8.ttest( )函数的完整用法是:[h,sig,ci] = ttest(x,m,alpha,tail)
其中 sig 为观察值的概率,当 sig 为小概率时则对零假设提出质疑(这里的
零假设为:H 0 :   m .也可以是其它形式,例如:H 0 :   m 、H 0 :   m 等);
ci 为真正均值μ的 1-alpha 置信区间;不写 tail,表示其取值为 0.
说明:若 h=0,表示在显著性水平 alpha 下,不能拒绝零假设;若 h=1,表示
在显著性水平 alpha 下,可以拒绝零假设.
若 tail=0,表示备择(对立)假设为:H 1 :   m(默认,双边检验);若 tail=1,
表示备择(对立)假设为: H 1 :   m (单边检验);若 tail=-1,表示备择(对
立)假设为: H 1 :   m (单边检验).
试用该函数求解如下问题:某种电子元件的寿命 X(以小时计)服从正态分
布,  、  均未知.现测得 16 只元件的寿命如下:
159 280 101 212 224 379 179 264 222 362 168 250
149 260 485 170
问当取 alpha=0.05 时:(1)是否有理由认为元件的平均寿命不大于 225(小时)?
(2)是否有理由认为元件的平均寿命不大于 295(小时)?
9.查看函数 ttest2( )的用法,并用于处理 Matlab 统计工具中的数据文件
gas.mat.回答问题:一月份油价 price1 与二月份油价 price2 的均值是否相同?

五、附录
附录:Matlab 中的其它部分概率分布函数名及其数学意义列表:
函数名 对应分布 数学意义
batapdf Beta 分布 1
y  f ( x | a, b)  x a 1 (1  x)b1 , 0  x  1
B ( a, b)
chi2pdf 卡方分布 x ( n  2) / 2 e  x / 2
y  f ( x | n)  n / 2 , x0
2 (n / 2)
fpdf F 分布 m  n m2
 
m
 2  m 2 x 2
y  f ( x | m, n)    mn
m n n 
    m  2
 2   2 1   n  x 
   
x0
gampdf Gamma 分布 1 
x
y  f ( x | a, b)  a x a 1e b , x  0
b ( a )
raylpdf 瑞利分布 x  2b 2
x2

y  f ( x | b)  2 e ,   x  
b
tpdf t 分布  n 1  n 1

2   x 2  2

y  f ( x | n)  
1  
n n 
n   
2
  x  
weibpdf Weibull 分布 y  f ( x |  ,  )   ( x) 1 e  ( x ) , x  0

94
实验六 古典密码与破译

一、问题背景和实验目的
保密通讯在军事、政治、经济斗争和竞争中的重要性是不言而喻的.
在斗争或竞争中,一方要将信息传递给己方的接收者,同时又要防止其他人 (特别
是敌方) 知道信息的内容.他采用的一种方式是:将原来的信息(称为 明文) 经过加密,
变成密文之后发送出去,使敌方即使得到密文也读不懂,而合法的接收者收到密文之后
却可以按照预先约定好的方法加以解密,再翻译成明文.而敌方却要千方百计从密文破
译出明文来.一方如何编制密码使之不易被破译,另一方则要找到其弱点加以破译,这
就构成了密码学的主要内容.
从密码学的发展来看,密码可分为古典密码 (即以字符为基本加密单元的密码),以
及现代密码(即以信息块为基本加密单元的密码).这里我们将介绍古典密码的加密和破译
原理.
本实验主要涉及代数,利用模运算意义下的矩阵乘法、求逆矩阵、线性无关、线性空
间与线性变换等概念和运算,学习古典密码体制的加密、解密和破译过程.

二、相关函数(命令)及简介
1.input('一些提示语句'):由键盘输入表达式.
注:a=input(''),对不同的变量类型 a,输入时要注意相应的格式,若 a 为字符则
要加' ',若 a 为矩阵则要加[ ]等.
2.length(a):给出数组 a 的长度.
3.mod(m, n):求 m 被 n 整除后的余数.
4.det(a):求矩阵 a 的行列式.
5.inv(a):求矩阵 a 的逆矩阵.
6.reshape(a, m, n):将矩阵 a 重排成 m*n 的矩阵.
例如:
a=1:10; b=reshape(a, 2, 5)
b= 1 3 5 7 9
2 4 6 8 10
7.double('字符'):将'字符'内的字符转化成 ASCII 码.
8.char(a):将 a 的每个数值转化为字符.
例如:
c=double('love')
c = 108 111 118 101
char(c)
ans = love
9.[m, n]=size(a):求矩阵 a 的维数.
10.gcd(m, n):求 m, n 的最大公约数.
11.fprintf(fid, format, A, ...):以指定格式将数据写入文件,若无参数 fid,则输出到
屏幕.

95
三、实验内容
1.Hill2 密码的两个实际问题:
实际问题(甲):甲方收到与之有秘密通信往来的乙方的一个密文信息,密文内容:
WK VAC PEAOCIXGWIZU ROQWAB ALOHDK C EAFCLWW
CVLEMIM CC
按 照 甲 方 与乙方的约定,他们之 间的密 文 通信采用 Hill2 密码,密钥为二阶矩 阵
1 2
A  且汉语拼音的 26 个字母与 0~25 之间的整数建立一一对应的关系,称之为
0 3
字母的表值,具体的表值见表 1.问这段密文的原文是什么?
表 1 明文字母的表值
A B C D E F G H I J K L M
1 2 3 4 5 6 7 8 9 10 11 12 13
N O P Q R S T U V W X Y Z
14 15 16 17 18 19 20 21 22 23 24 25 0

实际问题(乙):甲方截获了一段密文:
M O FAX J E AB A U C R S X J L U Y H Q AT C Z H W B C S C P
经分析这段密文是用 Hill2 密码编译的,且这段密文的字母 U C R S 依次代表字母 T A C
O,问能否破译这段密文的内容?
2. Hill2 密码的数学模型
一般的加密过程是这样的:
明文  加密器  密文  普通信道  解密器  明文
其中的 “  普通信道  解密器”这个环节容易被敌方截获并加以分析.
在这个过程中,运用的数学手段是矩阵运算,加密过程的具体步骤如下:
1) 根据明文字母的表值,将明文信息用数字表示,设明文信息只需要 26 个拼音大
写字母 A—Z(也可以不止 26 个,如还有小写字母、数字、标点符号等),通信双方给出
这 26 个字母表值(见表 1).
2) 选择一个二阶可逆整数方阵 A ,称为 Hill2 密码的加密矩阵,它是这个加密体制
的“密钥”(是加密的关键,仅通信双方掌握).问题(甲)已给出了这个二阶矩阵.
3) 将明文字母依次逐对分组.Hill2 密码的加密矩阵为二阶矩阵,则明文字母每 2 个
一组(可以推广至 Hilln 密码,则每 n 个明文字母为一组).若最后一组仅有一个字母,
则补充一个没有实际意义的哑字母,这样使每一组都由 2 个明文字母组成.查出每个明
文字母的表值,构成一个二维列向 量  .
4) A 乘以  ,得一新的 2 维列向量   A ,由  的两个分量反查字母表值得到

的两个字母即为密文字母.
以上 4 步即为 Hill2 密码的加密过程.
解密过程,即为上述过程的逆过程.
1 2
例:明文为 HDSDSXX (“华东师大数学系”的拼音缩写), A    ,求这段明文
 0 3 
的 Hill2 密文.
解:将明文相邻文母每 2 个分为一组:

96
HD SD SX XX (1)
最后一个字母 X 为哑字母,无实际意义.查表 1 得到每对字母的表值,并构造 2 维列
向量:
8  19  19   24 
 ,  ,  ,   (2)
 4 4   24   24 
将上述 4 个向量左乘矩阵 A ,得到 4 个 2 维列向量:
16   27   67   72 
 ,  ,  ,   (3)
12  12   72   72 
作模 26 运算(每个元素都加减 26 的整数倍,使其化为 0~25 之间的一个整数)得到:
 16  16   27  1
 12  (mod 26)  12  ,  12  (mod 26)   12  ,
       

 67   15   72   20 
 72  (mod 26)   20  ,  72  (mod 26)   20 
       
反查表 1 得到每对表值对应的字母为:
PL AL OT TT (4)
这就得到了“HDSDSXX” (“华东师大数学系”的拼音缩写) 的密文.
要将这段密文解密,只要将上述加密过程逆转回去,即将密文按同样方式分组,查
它们的表值即得:
16  1  15   20 
 ,  ,  ,   (5)
12  12   20   20 
(5) 是前面的 (3) 经模 26 运算的结果.但如何由 (5) 中的向量求得(2) 中的向量呢?
这是在模运算意义下,如何解方程组:
A   (6)

的问题.一个一般的 n 阶方阵可逆的充要条件为 det( A)  0 .但在模 26 意义下矩阵可

逆与一般的矩阵可逆有所不同.记整数集合 Z m  0,1, 2, , m  1 ,m 为一正整数,模 m

可逆定义如下:
定义 1:对于一个元素属于集合 Z m 的 n 阶方阵 A ,若存在一个元素属于集合 Z m 的

方阵 B ,使得
AB  BA  E (mod m),

称 A 为模 m 可逆, B 为 A 的模 m 逆矩阵,记为 B  A1 (mod m) .

E (mod m) 的意义是,每一个元素减去 m 的整数倍后,可以化成单位矩阵.例如:

97
 27 52 
 26 53  (mod 26)  E
 

定义 2:对 Z m 的一个整数 a ,若存在 Z m 的一个整数 b ,使得 ab  1(mod m) ,称 b 为 a

的模 m 倒数或乘法逆,记作 b  a 1 (mod m) .
可以证明,如果 a 与 m 无公共素数因子,则 a 有唯一的模 m 倒数(素数是指除了 1 与
自身外,不能被其他非零整数整除的正整数),反之亦然.例如, 31  9(mod 26) . 利用这
点,可以证明下述命题:
命题:元素属于 Z m 的方阵 A 模 m 可逆的充要条件是,m 和 det( A) 没有公共素数因子,

即 m 和 det( A) 互素.

显然,所选加密矩阵必须符合该命题的条件.
问题(甲)所选择的明文字母共 26 个,m  26 ,26 的素数因子为 2 和 13,所以 Z 26 上的

a c 
方阵 A 可逆的充要条件为 det( A)(mod m) 不能被 2 和 13 整除.设 A    ,若 A 满
b d 
足命题的条件,不难验证:
 d b 
A1  (ad  bc) 1   (mod 26)
 c a 

其中 (ad  bc )1 是 (ad  bc )(mod 26) 的倒数.显然, (ad  bc )(mod 26) 是 Z 26 中的数.

Z 26 中有模 26 倒数的整数及其倒数可见表 2.

表 2 模 26 倒数表
a 1 3 5 7 9 11 15 17 19 21 23 25
-1
a 1 9 21 15 3 19 7 23 11 5 17 25
表 2 可用下列程序求得:
m=26;
for a=1:m
for i=1:m
if mod(a*i, m)==1
fprintf('The INVERSE (mod %d) of number: %d is: %d\n', m, a, i)
end; end; end

注意:附录 1 给出的 Matlab 程序,可以用于判断一个 2 阶方阵在模 26 意义下是


否可逆,并在可逆的前提下求出其逆矩阵.
读者可结合下列演算的实例加以验证.
利用表 1 可以演算出的 A1 (mod 26) 如下:

98
 3 2 
A1 (mod 26)  31   (mod 26)
0 1 

 3 2 
 9  (mod 26)
0 1 

 27 18 
 (mod 26)
0 9 

1 8
  (mod 26)  B
0 9
于是,可以简单地计算得到:
16   112   1   97 
B *     , B *    ,
12   108   12  108 

 15   175   20  180 
B *     , B *    
 20  180   20  180 
再进行模 26 运算后得到:
 8   19   19   24 
 4  ,  4  ,  24  ,  24 
       
即得到明文:HD SD SX X(X).
用 Matlab 编程进行加密算法的程序参见附录 2.而用 Matlab 编写的相应的解密算
法程序参见附录 3.

表 3 问题 (甲) 的解
序号 分组密文 密文表值 明文表值 分组明文
1 W 23 7 G
K 11 21 U
2 V 22 4 D
A 1 9 I
3 C 3 1 A
P 16 14 N
4 E 5 13 M
A 1 9 I
5 O 15 13 M
C 3 1 A
6 I 9 19 S
X 24 8 H
7 G 7 9 I
W 23 25 Y
8 I 9 9 I
Z 0 0 Z
99
9 U 21 9 I
R 18 6 F
10 O 15 21 U
Q 17 23 W
11 W 23 5 E
A 1 9 I
12 B 2 10 J
A 1 9 I
13 L 12 2 B
O 15 5 E
14 H 8 14 N
D 4 10 J
15 K 11 9 I
C 3 1 A
16 E 5 13 M
A 1 9 I
17 F 6 4 D
C 3 1 A
18 L 12 14 N
W 23 25 Y
19 W 23 21 U
C 3 1 A
20 V 22 14 N
L 12 4 D
21 E 5 5 E
M 13 13 M
22 I 9 9 I
M 13 13 M
23 C 3 1 A
C 3 1 A
于是,实际问题(甲)的解为:
GU DIAN MI MA SHI YI ZI FU WEI JI BEN JIA MI DAN YUAN DE MI MA
即为:“古典密码是以字符为基本加密单元的密码”.
以下来解实际问题 (乙).
实际问题 (乙) 属于破译问题.前面的加密与解密过程类似于在二维向量空间进行线
性变换与其逆变换,每个明文向量是一个 Z m 上的二维向量,乘以加密矩阵后,仍为 Z m 上

的一个二维向量.由于加密矩阵 A 为可逆矩阵,所以,如果知道了两个线性无关的二维

明文向量与其对应的密文向量,就可以求出它的加密矩阵 A 及 A1 .
问题 (乙) 的密文中只出现一些字母,当然它可以是汉语拼音,或英文字母或其他语
言的字母.所以可猜测秘密信息是由 26 个字母组成,设 m  26 .通常由破译部门通过
大量的统计分析与语言分析确定表值.假如,所确定的表值为表 1,已知

100
U   T   R   C 
 C    A, S    O ,
       
注: "  " 前的为密文, "  " 后的为明文.
按照表 1,
U   21  20   T 
 C   1   3   A1  1   1    A 
       

 R  18   3  C 
 S    2   19   A 2   2   15    O 
       

21 18
在模 26 意义下, det( 1 ,  2 )  (mod 26)  345(mod 26)  7 ,它有模 26 倒数,所
3 19

以,1 ,  2 在模 26 意义下线性无关,类似地,也可以验证 det(1 , 2 )  11(mod 26) ,1 ,  2

线性无关.
记 P  ( 1 ,  2 ), C  (1 , 2 ) ,则 P  AC , PT ( A1 )T  C T ,记 PT X  C T ,其中 X  ( A1 )T .

以下在模 26 意义下对 ( PT | C T ) 进行一系列初等行变换将 PT 变成单位矩阵 E ,则相

应的 C T 将变成 X ,即 ( A1 )T .

 1 0  1  1 17 
经过以上的一系列推导,可得 ( A1 )T   , A  0 9 
17 9   
相应的 Matlab 程序参见附录 4.
利用与实际问题(甲)同样的解密方法,可以求得,这段密文的明文是:
| HE | WI LL | VI SI T| A | CO LL EG E | T HI S | A FT ER NO ON |
分析这段文字,如果依竖线所划分成的词汇,则这段密文可理解为如下一段文字:
''He will visit a college this afternoon''.
这样,可以认为破译成功.

四、自己动手
1. 实际问题 (甲) 的修正:按照甲方与乙方的约定,他们之间的密文通信采用 Hill2
1 2
密码,密钥为二阶矩阵 A    且汉语拼音的 26 个字母以及空格(字母 A~Z 的表值
0 4
为 1~26,空格的表值为 0)与 0~26 之间的整数建立一一对应的关系,称之为字母的
表值,试修正表 1、表 2 以及附录中的程序,以给出模 27 意义下矩阵可逆的判别方法
和具体求法.
2. 若将你姓名的拼音作为明文,例如:赵本山 (ZHAO BEN SHAN,含空格),密钥
等参见练习 1,求其在模 27 意义下的 Hill2 密文.
3. 若将你姓名的拼音作为 Hill2 密文,例如:赵本山 (ZHAO BEN SHAN,含空格),

101
密钥等参见练习 1,求其在模 27 意义下的明文.
4. 利用所介绍的 Hill2 密码体制的原理,根据给定的 26 个英文字母的乱序表值(见
表 4),设计与建立 Hill4 密码体制的加密、解密与破译框图并建立必要的计算机程序.设
英文 26 个字母以下面的乱序表与 Z 26 中的整数对应:

表4
A B C D E F G H I J K L M
5 23 2 20 10 15 8 4 18 25 0 16 13
N O P Q R S T U V W X Y Z
7 3 1 19 6 12 24 21 17 14 22 11 9
8 6 9 5
6 9 5 10
(1) 设 A  ,验证矩阵 A 能否作为 Hill4 密码体制的加密矩阵.用框图
5 8 4 9
10 6 11 4
画出你的验算过程,并编写相应的计算机程序.

(2) 设明文为
HILL CRYPTOGRAPHIC SYSTEM IS TRADJITIONAL.
利用上面的表值与加密矩阵给此明文加密,并将得到的密文解密.画出加密与解密过程
的框图并编写相应的计算机程序.
5. 设已知一份密文为 Hill2 密码体系,其中出现频数最高的双字母是 RH 和 NI,
而在明文语言中,出现频数最高的双字母为 TH 和 HE.由这些信息按表 5 给出的表
值能得到什么样的加密矩阵?
A B C D E F G H I J K L M
0 1 2 3 4 5 6 7 8 9 10 11 12
N O P Q R S T U V W X Y Z
13 14 15 16 17 18 19 20 21 22 23 24 25
6. 找出元素属于 Z 26 的所有可能的 Hill2 密码加密矩阵.若截获了如下一段密文

UTCQCVFOYQUVMGMGULFOLEYHDUHOPEASWXTIFBAMWT
且已知它是根据表 1 按 Hill2 密码体制加密的,你能否将其解密?

五、附录
附录 1:判断一个 2 阶方阵是否模 26 意义下可逆;若可逆,求出模 26 意义下的
逆矩阵.
m=26;
aa=input('输入一个 2×2 的矩阵,格式:[a11 a12;a21 a22]: ')
while size(aa)~=[2 2]
aa=input('输入一个 2×2 的矩阵,格式:[a11 a12;a21 a22]: ')
end
a=det(aa);bb=aa;
if gcd(m, a)~=1
disp('该矩阵不可逆')
102
else
for i=1:m
if mod(a*i, m)==1
antaa=i;
end
end
astar=[aa(2,2) -aa(1,2);-aa(2,1) aa(1,1)];
invaa=mod(antaa*astar,m);
disp(['原矩阵是:', mat2str(aa), ',它的逆矩阵(mod', num2str(m), ') 是: ', mat2str(invaa)])
end

注:(1) 实际应用中,当二阶密钥矩阵(可逆)为已知时,就不要每次再输入矩阵了.例
1 2
如:模 26 意义下的二阶密钥矩阵为 A    ,则可直接输入:enmat=[1, 2;0, 3]; 以取
 0 3 
代第 3~7 行.
1 8
(2) 附录 2 中的 demat=[1, 8;0, 9] 即 demat=   实为本程序的结果,读者也可将
 0 9
附录 1 归并到 附录 2、附录 3 中,以使附录 2、附录 3 保持独立.
(3) 注意附录 2、附录 3 中当字符串的长度不是偶数时的处理方法.
(4) 特别注意当 m  27 时,应如何适当地修改附录 2、附录 3,才能完成对空格的正
确处理.
1 2
附录 2:模 26 意义下,密钥(加密)为矩阵 A    时,对任意输入的大写字母
0 3
串的加密程序.
m=26;enmat=[1 2;0 3];demat=[1 8;0 9];ZERO=64;c=[];e1=[];
astr=input('输入要加密的明文文字(全部为大写字母):')
while any(double(astr)>90 | double(astr)<65)
astr=input('输入错误,应该全部为大写字母:')
end
a1=double(astr);lh=length(a1);
if mod(length(a1), 2)==1
a1=[a1, a1(length(a1))];
end
a1=a1-ZERO;
for i=1:length(a1)
if a1(i)==26
a1(i)=0;
end
end
c=reshape(a1, 2, length(a1)/2);
d1=mod(enmat*c, m);
e1=reshape(d1, length(a1), 1);

103
e1=e1';
e1=e1+ZERO;
for i=1:length(e1)
if e1(i)==64
e1(i)=90;
end
end
e1=e1(1:lh);
char(e1)
1 8
附录 3:模 26 意义下,密钥(解密)为矩阵 A    时,对任意输入的大写字
0 9
母串的解密程序.
m=26;enmat=[1 2;0 3];demat=[1 8;0 9];ZERO=64;c=[];e1=[];
astr=input('输入要解密的密文文字(全部为大写字母):')
while any(double(astr)>90 | double(astr)<65)
astr=input('输入错误,应该全部为大写字母:')
end
a1=double(astr);lh=length(a1);
if mod(length(a1), 2)==1
a1=[a1, a1(length(a1))];
end
a1=a1-ZERO;
for i=1:length(a1)
if a1(i)==26
a1(i)=0;
end
end
c=reshape(a1, 2, length(a1)/2);
d1=mod(demat*c, m);
e1=reshape(d1, length(a1), 1);
e1=e1';
e1=e1+ZERO;
for i=1:length(e1)
if e1(i)==64
e1(i)=90;
end
end
e1=e1(1:lh);
char(e1)
附录 4:在模 26 意义下对 ( PT | C T ) 进行一系列初等行变换将 PT 变成单位矩阵 E 过
程的 Matlab 程序.
m=26;zero=64;
p=input('输入要解密的密文文字(全部为大写字母):')

104
while any(double(astr)>90 | double(astr)<65)
p=input('输入要解密的密文文字(全部为大写字母):')
end
p=double(p)-zero;p=reshape(p, 2, 2);
c=input('输入相应的明文文字(全部为大写字母):')
while any(double(astr)>90 | double(astr)<65)
input('输入相应的明文文字(全部为大写字母):')
end
c=double(c)-zero;c=reshape(c, 2, 2);
pc=[p', c'];
if pc(1, 1)==0;
emp=pc(1, :);pc(1, :)=pc(2, :);pc(2, :)=temp;
end
for i=1:(m-1)
if mod(pc(1, 1)*i, m)==1
ant=i;
end
end
pc(1, :)=mod(pc(1, :).*ant, m);
pc(2, :)=mod(pc(2, :)-pc(1, :).*pc(2, 1), m);
for i=1:(m-1)
if mod(pc(2, 2)*i, m)==1
ant=i;
end
end
pc(2, :)=mod(pc(2, :).*ant, m);
pc(1, :)=mod(pc(1, :)-pc(2, :).*pc(1, 2), m);
a=[pc(:, 3), pc(:, 4)];
a=a'

105
实验七 数字填图问题

一、问题背景和实验目的
数字填图问题是数学问题的一种趣味形式.早在 19 世纪后半期,一些数学
家就在报刊中大量使用数字填图游戏和字谜游戏等,目的是使业余爱好者也能通
过简单的形式去认识、理解和琢磨深奥的数学问题,这些问题中甚至包括困惑了
世间智者 350 多年、于 1994 年才刚刚被证明了的“费马大定理”.100 多年来,
数字填图问题对数学界所起的作用是不言而喻的.
大家都知道,数学问题一般都经过严格的逻辑证明才得以解决.而逻辑证明
是指从一些公理出发,经过逻辑推理来证明问题.但随着 20 世纪 40 年代以来计
算机的诞生和发展,计算机改变了整个世界,计算机已在各个领域发挥作用,并
取得了许多重大进展.于是,能否用计算机来证明数学问题便成了大家关心的话
题.
所谓计算机证明是指充分发挥计算机计算速度快和会“推理”的特点,用计
算机程序模拟解题或进行穷举检验,最后得到问题的解.几乎所有的数学家对计
算机证明持保留态度,因为他们相信,只有逻辑证明才是真正可靠的.但“四色
问题”的证明,又使他们感到困惑,因为“四色问题”的证明实际上是一个计算
机证明.
能否用计算机来证明数学问题的争论可能会持续一个相当长的时间,本实验
旨在通过生活中几个常见的数字填图问题的探究,谈谈这类问题的逻辑推理解法
和计算机解法.

二、 相关函数(命令)简介
1.cputime 命令:记录执行本命令时的 Matlab 时钟的时间(秒).
2.tic 命令:开始计时.
3.toc 命令:结束计时.
4.disp(x):输出矩阵 x.x 的各项应为字符,所以在输出时要进行转化.
相关的命令有:
num2str( ):把数值转化为字符;mat2str( ):把矩阵转化为字符.
5.fopen(filename, mode):用 mode 方式打开/建立 filename 文件,以备写入
数据,使用方式:fid = fopen(filename, mode).
6.fclose(fid):关闭上述文件.
例如下列程序是把一个两行的矩阵 y 写入文件 output.dat:
x=0:0.1:1;
y=[x;exp(x)];
fid=fopen(’output.dat’,’wt’);
fprintf(fid,’ x exp(x)\n’);
fprintf(fid,’%6.2f %12.8f\n’,y); %实际得到的是矩阵 y 的转置矩阵
status=fclose(fid);
与 C 语言的文件操作方式相类似.

106
三、 实验内容
让我们先从一个简单的问题出发来谈谈数字填图问题的两种解法.然后通过
几个稍复杂问题的探究,从中展示逻辑推理的严谨以及计算机解法的魅力,启迪
我们去解决更复杂的数学问题.
注:在本实验中,将表达式 abc 理解为 abc ,即 100*a+10*b+c,其余类似,不
另加说明.
(一)、一个简单的问题及其解答
问题一:在图 1 的几个加法等式中,每个□表示一个非零数字,任意两个数字都

不相同,问有多少个解?

图1
【逻辑解法】 为简洁起见,将它的 3 个式子记作: a + b = c,d + e = f,g + h
= i 0,若问题有解,则显然有 i = 1,且(a + b) + (d + e) + (g + h) = c + f + i  10,
故 45 = (a + b + c) + (d + e + f) + (g + h + i) = 2 (c + f) + i  11,即 c + f = 17,故 c
= 8,f = 9 或 c = 9,f = 8.
考虑到 a ~ i 互不相同,当要求 a < b,d < e,g < h 时,有如下 4 组解(见
下表):

注:本问题实际上仅有 2 个解是本质的,即表中的第 2、3 行,第 4、5 行所


代表的解仅是位置不同而已.如不要求 a < b,d < e,g < h,则解的个数是
4C 21C 21C 21 个.
【计算机解法】为验证此结果,可用 Mathematica、Matlab、Turbo C 等软
件进行模拟解题,充分利用计算机运算速度快的特点进行穷举法检验.实践表明
本问题解的情况恰如上所述.用 Matlab 实现的程序清单可参见附录 1,这一算
法比较慢(一个更慢的算法参见附录 1B,试分析其原因),而一个提速的程序清
单可参见附录 2,Turbo C 程序清单可参见附录 3,而 Mathematica 程序清单可参
见附录 4.
【评论】这个问题的逻辑解法十分简单,或许根本不需要计算机解法,但所
用程序有一定的代表性,稍加修改即可解决一系列问题,这点可从下面的问题中
看到.
(二)、几个较复杂的问题及其解答
问题二:在图 2 的 4 个算式中,每个□表示一个非零数字,任意两个数字都不

107
相同,问 (A)、(B)、(C) 和 (D) 这 4 种情形分别有多少个解?

图2
讨论:显然,情形 (C) 无解.情形 (D) 与 情形 (C) 实际上是同一个问题,
因此也无解.
情形 (B) 与 情形 (A) 实际上也是同一个问题.我们先讨论情形 (A) 的解
的个数.

【逻辑解法】为简洁起见,将此竖式记作:abc + def = ghi,即 ,其中 a

~ i 代表 1 ~ 9 这 9 个互不相同的非零数字.据九余数性质可知,两个“加数”
中的六个数字之和被 9 除的余数应等于“和数”中的三个数字之和被 9 除的余
数.又这两个“加数”与“和数”中共九个数字正好是 1,2,  ,9,它们的和
为 45,被 9 除的余数是 0,易见“和数”的三个数字之和被 9 除的余数必为 0,
也即: “和数”是 9 的倍数.注意到题设可知, “和数”的三个数字之和必定为:
g + h + i = 9 或 g + h + i = 18.
<1> 考虑 g + h + i = 9 的情形.
(1) 首先必定有 g > 3,否则 {a,d} 最小为 {1,2},{b,e} 最小为 {4,
5},{c,f} 最小为 {6,7},此时已有 abc + def > 400,与 g  3 矛盾.故 g  4;
另外,g  6 为显然;
(2) 若 g = 4,由 g + h + i = 9,h + i = 5,故 {h,i} 最小为 {1,4} 或 {2,
3};但已有 g = 4,故 {h,i} 为 {2,3},而 {a,d} 最小为 {1,4},从而 g 
5,与 g = 4 矛盾;
(3) 若 g = 5,由 g + h + i = 9,h + i = 4,故 {h,i} 为 {1,3};而 {a,
d} 最小为 {2,4},从而 g  6,与 g = 5 矛盾;
(4) 若 g = 6,由 g + h + i = 9,h + i = 3,故 {h,i} 为 {1,2};而 {a,d}
最小为 {3,4},从而 g  7,与 g = 6 矛盾.
综上所述,g + h + i = 9 的情形下问题无解.
<2> 考虑 g + h + i = 18 的情形.由于 g  4(理由同上),以下按 g = 9,8,
,4 的顺序分类讨论:
(1) g = 9,则 h + i = 9.由于 a ~ i 互不相同,于是 g,h,i 的可能的取值见下
表:

108
对这些竖式有序地交换两个加数的百位数、十位数和个位数,可得到每个类
型的 8(= C 21C 21C 21 ) 个不同竖式 (解),小计有解 12  8 = 96 个.
注意:表中的第 2、5、6、9 列为容易造成失解的地方,要特别留意.
完全类似地有如下一系列过程:
(2) g = 8,则 h + i = 10.仿(1),小计有解 108=80 个,解例见下表:

(3) g = 7,则 h + i = 11.小计有解 58=40 个,解例见下表:

(4) g = 6,则 h + i = 12.小计有解 68=48 个,解例见下表:

(5) g = 5,则 h + i = 13.小计有解 58=40 个,解例见下表:

(6) g = 4,则 h + i = 14.小计有解 48=32 个,解例见下表:

109
结论:本问题的解的个数为:(12 + 10 + 5 + 6 + 5 + 4)  8 = 42  8 = 336.
注:<1>如不考虑两个加数的上下位置关系,则总的解的个数为:42  8/2 =
168.
<2>由于情形 (B) 与 情形 (A) 是同一个问题,故解的个数也为:42  8
= 336.
【计算机解法】为验证此结果,仍用 Matlab、Mathematica、Turbo C 编程
进行模拟解题,充分利用计算机运算速度快的特点进行穷举法检验.实践表明本
问题有且只有 336 个不同竖式(解),而 Matlab 程序清单可参见附录 5,你可
发现它与附录 1 十分相似.
【评论】这个问题的逻辑解法较复杂,而计算机解法则是如此的简单快捷,
运行整个程序不要 1 分钟.实际上非常复杂的“四色问题”的证明也是这样:
对 1482 种有代表性地图的分析,若依靠人工去做,可能要几十年甚至上百年的
时间,而用计算机,只要 1200 小时即告完成.这还是 70 年计算机的计算水平,
若用现在的计算机,计算时间应该不会超过一天!
问题三:在图 3 的加法算式中,每个□表示一个非零数字,任意两个数字都

不相同,问可有多少个解?
【逻辑解法】为简洁起见,将此竖式记作:

a + bc + def = ghi 或 ,其中 a ~ i 代表 1 ~ 9 这 9 个互不相同的非


零数字.
据九余数性质并采用完全类似问题二的讨论可知,“和数”的三个数字之和
必定为:g + h + i = 9 或 g + h + i = 18.同时,g  1,否则 d = 1;另外 g > d,
从而 g = d + 1.
由于 9  g  2,以下按 g = 9,8,7,  ,2 的顺序分类讨论:
(0) g = 9,d = 8.则 h + i = 9.由于 a ~ i 互不相同,于是 g,h,i 的可能
的取值为(见下表):

图3
小计有解 0 个.

110
(1) g = 8,d = 7.则 h + i = 1(不可能,舍去) 或 h+i=10.由于 a ~ i 互不相
同,于是 g,h,i 的可能的取值为(见下表):

对这些竖式有序地交换三个加数的个位数、两个加数的十位数,可得到每个类型
的 12 个不同竖式 (解),小计有解 212=24 个.
完全类似地有如下一系列过程:
(2) g = 7,d = 6.则 h + i = 2(不可能,舍去) 或 h+i=11.仿(1),小计有解
212=24 个.

(3) g = 6,d = 5.则 h + i = 3 或 h + i = 12.有解 112=12 个,解例见下表:

(4) g = 5,d = 4.则 h + i = 4 或 h + i = 13.有解 312=36 个,解例见下表:

(5) g = 4,d = 3.则 h + i = 5 或 h + i = 14.有解 2  12 = 24 个,解例见下


表:

111
(6) g = 3,d = 2.则 h + i = 6 或 h + i = 15.有解 2  12 = 24 个,解例见下
表:

(7) g = 2,d = 1.则 h + i = 7 或 h + i = 16.有解 2  12 = 24 个,解例见下


表:

结论:本问题的解的个数为:(2 + 2 + 1 + 3 + 2 + 2 + 2)  12 = 168.
【计算机解法】让我们再尝试计算机解法.仍用 Matlab、Mathematica、Turbo
C 编程进行穷举法验证,程序清单类似于附录 1~附录 5,不再另附.运行结果
表明本问题的确有且只有 168 个不同竖式(解),要说明的是:该程序在一般的
计算机上运行一次也只需不到 1 分钟.
【评论】也许有人会说,你的问题还仅是一个有穷的问题,象“费马大定理”
这样的无穷问题,你的计算机就无能为力了! 情况或许是这样.但应该注意到:
非常复杂的“四色问题”也是一个无穷问题,但妙就妙在有人能将它们缩小到
1482 种有代表性地图以内,从而成为一个有穷的问题!
至此,对于计算机解题的作用恐怕再不能视而不见了! 下面的两个问题也是
成功地运用计算机解题的的一些典型例子,而至少到目前为止还没有看到它们的
推理解法.
问题四:图 4 的加法等式是:两个真分数之和等于第三个真分数,每个□

表示一个不为 0 的数字,任意两个数字都不相同.比如: 1  5  7 ,试找


32 96 84

出所有可能的解.

112
图4
【计算机解法】本问题利用计算机程序已找到解答,共有 10 个解.解答请
参见:《数学教学》(华东师范大学)1994 年第 5 期.
【评论】程序如何编? 看起来问题似乎很简单,只要将附录 1~附录 5 稍加
修改即可.例如可利用附录 6 的 Matlab 程序进行计算.但实际情况让我们大
吃一惊:用 Matlab 程序居然只有 6 个解!还有 4 个解到哪里去了?用 Turbo
C 程序编写出的类似的程序居然只有 7(或 9)个解!还有 3(或 1)个解到哪
里去了?还有人用 Turbo C 程序编写出的类似的程序,却居然得到了 11 个
“解”!这个多出的 1 个“解”是哪里来的?
类似的问题还会发生在本实验的“四、自己动手”的第 6 题中,用不同的
语言编写出的类似程序,其运行结果居然差距很大,你能明白其中的道理吗?根
据观察,可能是浮点问题,也可能是整数的上界问题,或别的什么原因.具体什
么原因,留作思考题.
问题五:图 5 的加法等式是:两个假分数之和等于第三个假分数,每个□

表示一个不为 0 的数字,任意两个数字都不相同.试找出所有可能的解.

图5
【计算机解法】本问题利用计算机程序也已找到解答,共有 41 个解.同样
只要将附录 1 ~ 5 的程序稍加修改即可.
(三)、小结
数字填图问题是一种活泼的、变形的数学问题,逻辑推理是这类问题的一般
解法.但也有若干数字填图问题要找到这样的逻辑推理解法是非常地困难,而采
用计算机解法则轻而易举.问题一和问题二就是这样的例子.至于问题四和问题
五则只能给出计算机解法.尽管数学家们很难接受计算机解法,因为他们担心计
算机会出错(尽管这种出错的概率几乎为零!),更重要的是他们坚信逻辑证明是
解答这类问题的根本方法.但上述事实证明计算机解法也是十分有效的.另一个
公认的例子是“四色问题”,它的证明实际上就是一个计算机证明.关于这个问
题的争论可能会有一个相当长的时间.不管将来的结论如何,但计算机证明 (解
题) 毕竟代表将来数学问题解决的一个方向.就象安德鲁·怀尔斯 (Andrew Wiles)
突发灵感地把“伊娃沙娃理论”和“科利瓦金弗莱切方法”结合在一起可以完美
地互相补足,以致最终证明了“费马大定理”一样,未来的数学家或许会让“逻
辑证明”和“计算机证明”也完美结合,从而解决更多的数学问题.
注;西蒙·辛格[英],1998 年.《费马大定理一个困惑了世间智者 358 年
的谜》,薛密 译,上海译文出版社.

113
四、 自己动手
1.一道竞赛题(以下称“原问题”)
1998 年 4 月香港数理教育学会主办的初中数学竞赛有这样一道试题:
在下面的加法算式中,每个□表示一个数字,任意两个数字都不相同,那么 A

与 B 的乘积的最大值是多少?

解答:最大值是 15.你能给出逻辑推理解法并用计算机加以验证吗?
由上述问题引伸出的三个问题:
2.满足原问题题意的不同的加法算式(竖式)共有多少个?
本问题有 60 个不同竖式(解).试给出逻辑推理解法并用计算机加以验证.
原竞赛题是针对初中生而设计的,故问题的难度被大大降低了.本练习已有
一定难度.不可否认,逻辑推理是解决问题的重要途径,而计算机模拟解题在其
中所起的作用也是不言而喻的.我们可以将练习 2 一般化,你将发现计算机模
拟解题的有效性和重要性.
3.如果在原问题中删除条件:“任意两个数字都不相同”,则满足题意的不同的加

法算式(竖式)共有多少个?
本问题实际上是一个有约束条件的全排列问题.本问题的答案是:48195 个!
这真是一个神奇的数值.要得到这个数值应该说是有一定难度的.试给出逻
辑推理解法并用计算机加以验证.
注:假如在本问题中允许三个“加数”与“和数”均可以由数字 0 作为开
头,去掉“任意两个数字都不相同”这个条件限制,本问题则变成一个真正的全
排列问题.在 a + bc + def = ghij 中,
“和数”ghij 是被动的.由 a,b,c,d,e,
f  {0,1,2,3,4,5,6,7,8,9},此时本问题有解 106 个.
练习 3 是利用计算机模拟解题的真正代表,可以说计算机模拟解题能力在
某些方面确已达到了逻辑推理解题的能力.而以下的练习 4 将把练习 2 的难度
进一步加大.你将发现运用计算机模拟解题在某些方面甚至已超过运用逻辑推理
解题.这个问题是:
4.假如违反常规,允许三个“加数”与“和数”均可以由数字 0 作为开头,保留条

件:“任意两个数字都不相同”,则满足原问题题意的不同的加法算式(竖式)共有

多少个?
本问题共有 228 个解,即在练习 2 有 60 个不同竖式(解)的基础上再增

114
加 168 个解.试给出逻辑推理解法并用计算机加以验证.
分析和观察:练习 4 的结论与本实验中的“问题三”的结论是否有一定的
联系? 有何联系?
5.验证本实验中的“问题四”、“问题五”的结论.能否给出相应的推理解法?
答案是:非常困难! 不妨一试.你是否发现运用计算机模拟解决本问题,已
超过运用逻辑推理解决本问题?
6.设 A ~ J 表示十个互不相同的数字,问:方程(注意: 组成分数的四个数的

第一位数字不能为 0)

ABC  H
DEFG IJ

共有多少个解?
答案是 110 个? 是 118 个? 是其它的数字?为什么?
7.前面所说的“用不同的语言编写出的类似程序,其运行结果居然差距很大”现

象,你遇到过吗?试结合附录 6,分析产生漏(增)解的原因.

8.利用 Matlab 文件操作技术修改附录 1,使得结果可以保存到一个文本文件

中.类似地,用 Turbo C 文件操作技术修改附录 3,使得结果也可以保存到一个

文本文件中.

五、附录
附录 1 (fulu1.m):
tic;
n=0;
for a=1:9
for b=1:9
if (b==a), continue; end
for c=1:9
if (c==a | c==b), continue; end
for d=1:9
if (d==a | d==b | d==c), continue; end
for e=1:9
if (e==a | e==b | e==c | e==d), continue; end
for f=1:9
if (f==a | f==b | f==c | f==d | f==e), continue; end
for g=1:9

115
if (g==a | g==b | g==c | g==d | g==e | g==f), continue; end
for h=1:9
if (h==a | h==b | h==c | h==d | h==e | h==f | h==g), continue; end
for i=1:9
if (i==a | i==b | i==c | i==d | i==e | i==f | i==g | i==h)
continue;
end
if (a<d & a*(10*e+f)*(10*h+i) +d*(10*b+c)*(10*h+i) == g*(10*b+c)*(10*e+f))
n=n+1;
disp(['第',num2str(n),'个解:',...
num2str(a),'/',num2str(b),num2str(c),'+',...
num2str(d),'/',num2str(e),num2str(f),'=',...
num2str(g),'/',num2str(h),num2str(i)])
end;end;end;end;end;end;end;end;end;end; %% 共有 10 个 end
t3=toc;
fprintf('\n The elapsed time(measured by tic/toc) is: %g',t3)

附录 1B (fulu1B.m):
t=cputime;n=0;
for a=1:9
for b=1:9
if b~=a
for c=1:9
if c~=a & c~=b
for d=1:9
if d~=a & d~=b & d~=c
for e=1:9
if e~=a & e~=b & e~=c & e~=d
for f=1:9
if f~=a & f~=b & f~=c & f~=d & f~=e
for g=1:9
if g~=a & g~=b & g~=c & g~=d & g~=e & g~=f
for h=1:9
if h~=a & h~=b & h~=c & h~=d & h~=e & h~=f & h~=g
for i=1:9
if i~=a & i~=b & i~=c & i~=d & i~=e & i~=f & i~=g & i~=h ...
& a+b==c & d+e==f & g+h==i*10 & a<b & d<e & a<d & g<h
n=n+1;
disp(['第', num2str(n), '个解:', ...
num2str(a), '+', num2str(b), '=', num2str(c), ' ', ...
num2str(d), '+', num2str(e), '=', num2str(f), ' ', ...
num2str(g), '+', num2str(h), '=', num2str(i), '0'])
end;end;end;end;end;end;end;end;end;end; end;end;end;end;end;end;end
%% 共有 17 个 end

116
time=cputime-t

附录 2 (fulu2.m,提速版):
t02=clock;
n=0;
A1=1:9;
for i1=1:9
a=A1(i1); A2=A1([1:i1-1,i1+1:9]);
for i2=1:8
b=A2(i2); A3=A2([1:i2-1,i2+1:8]);
for i3=1:7
c=A3(i3); A4=A3([1:i3-1,i3+1:7]);
for i4=1:6
d=A4(i4); A5=A4([1:i4-1,i4+1:6]);
for i5=1:5
e=A5(i5); A6=A5([1:i5-1,i5+1:5]);
for i6=1:4
f=A6(i6); A7=A6([1:i6-1,i6+1:4]);
for i7=1:3
g=A7(i7); A8=A7([1:i7-1,i7+1:3]);
for i8=1:2
h=A8(i8); i=A8([1:i8-1,i8+1:2]);
if (a<d & a*(10*e+f)*(10*h+i) +d*(10*b+c)*(10*h+i) == g*(10*b+c)*(10*e+f))
n=n+1;
disp(['第',num2str(n),'个解:',...
num2str(a),'/',num2str(b),num2str(c),'+',...
num2str(d),'/',num2str(e),num2str(f),'=',...
num2str(g),'/',num2str(h),num2str(i)])
end
end
end
end
end
end
end
end
end
t2=etime(clock,t02);
fprintf('\n The elapsed time(measured by clock/etime) is: %g',t2)

附录 3 (Turbo C 程序,fulu3.c):
#include<stdio.h>
main()
{ int a,b,c,d,e,f,g,h,i,j,n=0;

117
printf("\n\n");
for (a=1;a<=9;a++){
for (b=1;b<=9;b++){
if (b==a) continue;
for (c=1;c<=9;c++){
if (c==a||c==b) continue;
for (d=1;d<=9;d++){
if (d==a||d==b||d==c) continue;
for (e=1;e<=9;e++){
if (e==a||e==b||e==c||e==d) continue;
for (f=1;f<=9;f++){
if (f==a||f==b||f==c||f==d||f==e) continue;
for (g=1;g<=9;g++){
if (g==a||g==b||g==c||g==d||g==e||g==f) continue;
for (h=1;h<=9;h++){
if (h==a||h==b||h==c||h==d||h==e||h==f||h==g) continue;
for (i=1;i<=9;i++){
if(i==a||i==b||i==c||i==d||i==e||i==f||i==g||i==h) continue;
else
if ((a+b==c)&&(d+e==f) &&
(g+h==10*i)&&(a<b)&&(d<e)&&(a<d)&&(g<h))
{printf ("%3d: %d+%d=%d, %d+%d=%d, %d+%d=%d0 ",++n,a,b,c,d,e,f,g,h,i);
if (n%3==0) printf("\n");
} }}}}}}}}}
}
}

附录 4 (Mathematica 程序,fulu4.nb):
Timing[ (*a+b=c, d+e=f, g+h=i0*)
Clear[n,a,b,c,d,e,f,g,h,i]; n=0;
For[a=1,a<=9,a++,
For[b=1,b<=9,b++,If[b!=a,
For[c=1,c<=9,c++,If[c!=a&&c!=b,
For[d=1,d<=9,d++,If[d!=a&&d!=b&&d!=c,
For[e=1,e<=9,e++,If[e!=a&&e!=b&&e!=c&&e!=d,
For[f=1,f<=9,f++,If[f!=a&&f!=b&&f!=c&&f!=d&&f!=e,
For[g=1,g<=9,g++,If[g!=a&&g!=b&&g!=c&&g!=d&&g!=e&&g!=f,
For[h=1,h<=9,h++,If[h!=a&&h!=b&&h!=c&&h!=d&&h!=e&&h!=f&&h!=g,
For[i=1,i<=9,i++,If[i!=a&&i!=b&&i!=c&&i!=d&&i!=e&&i!=f&&i!=g&&i!=h
&&a+b==c&&d+e==f&&g+h==10*i&&a<b&&d<e&&a<d&&g<h,
Print[++n,": ",a,"+",b,"=",c,",",d,"+",e,"=",f,",",g,"+",h,"=",i,"0"]
]]]]]]]]]]]]]]]]] (* total have 17 right ")"s *)
]

118
附录 5 (Matlab 程序,fulu5.m):
程序基本上同附录 1,只要将倒数第 4 行至倒数第 9 行换成下列 5 行即可.
if i~=a & i~=b & i~=c & i~=d & i~=e & i~=f & i~=g & i~=h ...
& (100*a+10*b+c)+(100*d+10*e+f)==(100*g+10*h+i) & a<d
n=n+1;
disp(['第', num2str(n), '个解:', ...
num2str(100*a+10*b+c), '+', num2str(100*d+10*e+f), '=', num2str(100*g+10*h+i)])

附录 6 (Matlab 程序,fulu6.m):
程序基本上同附录 1,只要将倒数第 4 行至倒数第 9 行换成下列 6 行即可.
if i~=a & i~=b & i~=c & i~=d & i~=e & i~=f & i~=g & i~=h ...
& a/(10*b+c)+d/(10*e+f)==g/(10*h+i) & a<d
n=n+1;
disp(['第', num2str(n), '个解:', num2str(a), '/' , num2str(b), num2str(c), '+', ...
num2str(d), '/' , num2str(e) , num2str(f), '=', num2str(g), '/', num2str(h), …
num2str(i)])

119
实验八 概率与频率

一、问题背景和实验目的
概率,又称为几率、或然率,是反映某种事件发生的可能性大小的一种数量
指标.它介于 0 和 1 之间.这里的事件是指随机现象中出现的某个可能结果.
概率论是研究随机现象统计规律的一门数学分支学科,它有着悠久的历史.通
过本实验的学习,加深对频率和概率等概念的理解和认识,并帮助掌握一些概率
统计的原理.

二、相关函数(命令)简介
1.rand(m,n):生成 m  n 的随机矩阵,每个元素都在(0,1)间,生成方式为均
匀分布.
例:rand(1):即生成一个(0,1)间的随机数.
2.randn(m,n) :生成 m  n 的随机矩阵,每个元素都在(0,1)间,生成方式为
正态分布.
3. randperm(m):生成一个 1 到 m 的随机整数排列.
例:randperm(5)
ans = 3 5 2 1 4
4.perms(1:n):生成 1 到 n 的全排列,共 n!个.
5.一系列取整的函数:
(1) fix(x):截尾法取整;
(2) floor(x):退一法取整(不超过 x 的最大整数);
(3) ceil(x):进一法取整(=floor(x)+1);
(4) round(x):四舍五入法取整.
例:x=-3.49; y=3.49; z=-3.50; w=3.50
函数表达式 fix(x) fix(y) floor(x) floor(y) ceil(x)
计算结果 -3 3 -4 3 -3
函数表达式 ceil(y) round(x) round(y) round(z) round(w)
计算结果 4 3 3 -4 4
6.unique(a):合并 a 中相同的项.
例:a=[1 4 2 3 3 2 ];
unique(a)
ans = 1 2 3 4
7.switch 表达式
case 情况 1
命令系列 1
case 情况 2
命令系列 2
……
otherwise
命令系列
end

119
8.prod(x):向量 x 的所有分量元素的积.

三、实验内容
(一)试验所依据的一些基本知识:
1.随机试验
所谓随机试验是指一个实验,它满足以下三个条件:
(1)试验可以在相同的情况下重复进行;
(2)试验的所有可能结果是明确可知的(且不止一个);
(3)每次试验总是恰好出现所有可能结果中的一个,但在试验进行之前却不
能判断该次试验会出现哪个结果.
2.概率与频率的关系
概率是指某随机事件发生可能性大小的数值度量,它是该随机事件本身的属
性.频率是指某随机事件在随机试验中实际出现的次数与随机试验进行次数的比
值.我们知道,随着随机试验进行次数的增加,频率将更“靠近”概率.
3.本实验主要运用 rand( ) 函数模拟随机试验.
程序开始时,设定试验次数,并取有利事件数的初始值为零.程序主体采用
循环结构,有利事件发生则记数增加.最后试验结束,输出有利事件数与试验次
数的比值 (即事件发生的频率),验证是否与概率相近.
(二)试验过程:
1
试验 1:随机投掷均匀硬币,验证国徽朝上与国徽朝下的概率是否均为 ,
2
利用下述程序,并填写表一.
n=10000;m=0;
for i=1:n
x=randperm(2)-1;
y=x(1);
if y==0;
m=m+1;
end
end
m/n
表一
试验次数 (n)
国徽朝上频率
国徽朝下频率
1
试验 2:随机投掷均匀骰子,验证各点数出现的概率是否为 ,利用下述程序,
6
并填写表二.
n=10000;
m1=0;m2=0;m3=0;m4=0;m5=0;m6=0;
for i=1:n
x=randperm(6);y=x(1);
switch y

120
case 1
m1=m1+1;
case 2
m2=m2+1;
case 3
m3=m3+1;
case 4
m4=m4+1;
case 5
m5=m5+1;
otherwise m6=m6+1;
end
end
disp([num2str(m1/n),',',num2str(m2/n),',',num2str(m3/n),',',...
num2str(m4/n),',',num2str(m5/n),',',num2str(m6/n)])
表二
试验次数 (n)
出现一点频率
出现二点频率
出现三点频率
出现四点频率
出现五点频率
出现六点频率
试验 3:利用蒙特卡罗(monte carlo)投点法计算 
在一个边长为 a 正方形内随机投点,该点落在此正方形的内切圆中的概率应
2
a 
为内切圆与正方形的面积的比值     : a 2  ,利用下述程序,并填写表三.
2 4
n=100000;a=2;m=0;
for i=1:n
x=rand(1)*a/2;y=rand(1)*a/2;
if x^2+y^2<=(a/2)^2;
m=m+1;
end
end
4*m/n
表三
试验次数(n)
所得  的近似值
试验 4:蒲丰(buffon)投针实验
在画有许多间距为 d 的等距平行线的白纸上,随机投掷一根长为 l ( l  d )
的均匀直针,求针与平行线相交的概率,并计算  的近似值.

121
设 针 与 平 行 线 的 夹 角 为  (0     ) , 针 的 中 心 与 最 近 直 线 的 距 离 为
d l
y (0  y  ) .针与平行线相交的充要条件是 y  sin  ,则
2 2
 l
0 2 sin d 2l m
p   .
d d n

2
2nl
故又可得  的近似计算公式   ,其中 n 为随机次数,m 为针与平行线相
md
交的次数,利用下述程序,并填写表四.
n=100000;l=0.5;m=0;d=1;
for i=1:n
x=l/2*sin(rand(1)*pi);y=rand(1)*d/2;
if x>=y
m=m+1;
end
end
m/n
2*n*l/(m*d)
表四
试验次数 (n)
针长( l )/平行线间距(d)
相交频率
相交概率的理论值
 的近似值
试验 5:生日问题
设某班有 m 个学生,则该班至少有两人同一天生日的概率为多少?假设某一
学生的生日出现在一年中的每一天都是等可能的,并设一年为 365 天.古典概型
中,计算这个问题的合理解法是:设该班任两个学生的生日都不同的概率是:
 365 
   m!
 m  365!
p1  m
 ,
365 (365  m)!365 m

则至少有两个人同一天生日的概率是: p  1  p1 ,利用下述程序,并填写表五.

%%实验值计算
n=1000;p=0;m=50;
for t=1:n
a=[];q=0;
for k=1:m
b=randperm(365);
a=[a,b(1)];

122
end
c=unique(a);
if length(a)~=length(c);
p=p+1;
end
end
p/n
%%理论值计算
p1=1:365;
p2=1:(365-m);
p2=[p2,ones(1,m)*365];
pp=p1./p2;
pp=1-prod(pp)
表五
试验次数 (n)
班级人数 (m)
至少有两人生日相同的频率
至少有两人生日相同的概率的理
论值
试验 6:摸彩问题
彩票箱内有 m 张彩票,其中只有一张能中彩.问 m 个人依次摸彩,第 k(k 
m)个人中彩的概率是多少?你能得出什么结论?
古典概型中,计算这个问题的一般解法是:
1
第 1 个人中彩的概率是: p1 
m
m 1 1 1
第 2 个人中彩的概率是: p 2   
m m 1 m
m 1 m  2 1 1
第 3 个人中彩的概率是: p3    
m m 1 m  2 m
……
1
故第 k 个人中彩的概率是: p k  , k  1,2,.m .
m
利用下述程序,验证你的结论.
n=10000;
m=10;
p=0;
k=5;
for i=1:n
x=randperm(m);y=x(1);
if y==k;
p=p+1;
end
end
p/n

123
四、自己动手
1.通过实验,填写完成表格一至表格五的数据.
2.函数 randn() 产生服从正态分布的随机数.试通过实例来说明它与函数
rand() 的不同之处.
3.用 Monte Carlo 方法求两平面曲线 y  x 2 ( x  0) 与 y  1  x 2 及 y 轴所围
成的区域的面积.下面是与之相关的两个 Matlab 程序:
[程序甲]:
n=100000;a=sqrt(2)/2;b=1;S=a*b;
m=0;
for i=1:n
if rand(1)*b>=(rand(1)*a)^2&rand(1)*b<1-(rand(1)*a)^2
m=m+1;
end
end
m/n*S
quad('1-2*x.^2',0,a)
实验值(=0.4911)与实际值(=0.4714)相距甚远(偏大).
%%作为比较或对照,我们也查看了另外一部分学生提交的程序:
[程序乙]:
n=100000;a=sqrt(2)/2; b=1;S=a*b;
m=0;
for i=1:n
x=rand(1)*a;y=rand(1)*b;
if y<=1-x^2&y>x^2
m=m+1;
end
end
m/n*S
quad('1-2*x.^2',0,a)
实验值(=0.4719)与实际值(=0.4714)十分接近.
试分析[程序甲]和[程序乙] 的不同之处. 试问:哪一个程序是对的? 为什么?
4.分析附录中的 [程序丙] 和 [程序丁] 的设计本意.请问它们为什么都是
错误的?
5.设计一个三维投点的蒙特卡罗法计算  .并比较运行结果与二维投点的蒙
特卡罗法的运行结果,哪个更准确些.
提示:随机投点落在单位正方体的内切球体内部.
6.口袋里装有 10 个白球和 10 个黑球.甲乙两人轮流在口袋里摸球,每次只
摸一球且不放回.问甲先摸到白球的概率大,还是乙先摸到白球的概率大?
7.两盒火柴,每盒 20 根.每次随机在任一盒中取出一根火柴.问其中一盒
中的火柴被取完而另一盒中还有 5 根火柴的概率有多大?

124
五、附录
[程序丙]:
n=100000;a=1;b=1;S=a*b;
m=0;
for i=1:n
x=rand(1)*a;y=rand(1)*b;
if y<=1-x^2&y>x^2
m=m+1;
end
end
m/n*S
quad('1-2*x.^2',0,a)
实验值(=0.4720)比“理论值”(=0.3333)大出很多!

[程序丁]:
n=100000;a=sqrt(2)/2;b=1;S=a*b;
m=0;
for i=1:n
if rand(1)<1-rand(1)^2&rand(1)>=rand(1)^2;
m=m+1;
end
end
aa=m/n*S
bb=quad('1-2*x.^2',0,a)
实验值 (=0.3267)比理论值(=0.4714)小出很多!!

125
实验九 网站排名问题

一、问题背景与实验目的
几乎每个人都有使用 Google 搜索引擎进行网上搜索的体验.我们在 Google
搜索引擎中输入一些关键词后,Google 会很快地找到所有与搜索关键词匹配的
网页,并给出所有的网站排名情况(一般认为排在第一个的最重要,以下类推).到
目前为止,世界上有近千万个网站,十多亿个网页,难道 Google 搜索引擎真的
如此神奇,能够在几秒、几十秒的时间内扫遍世界上所有的网站(网页)吗?答
案是否定的.事实上,Google 网站是基于自己的大型数据库系统的网站,它定
期地(比如每个月一次)对世界上的所有网站进行大搜索,并将结果保存在自己
的数据库中.我们通过 Google 搜索引擎进行网上搜索,实际上是在 Google 网站
的数据库里进行搜索,因此,所用时间一般不会太长.
要验证这一点并不难.假如你是一个“网管”,你可以控制一个网站,比如
你可以很快地向网站发布信息(内含某些特殊的关键词).此后,你迅速利用
Google 搜索引擎搜索你刚才的关键词,一般情况下是找不到的.
我们关心的重点是:与某个关键词相关的网站可能有几个、几十、……、最
多可能有几百万个,Google 是如何给出网站排名情况的呢?本实验将要介绍的
PageRank(网页级别)算法就是 Google 用于评测一个网页“重要性”的一种方法.虽
然现在不断地有改善的排名算法,但其本质上与 PageRank(网页级别)算法十分接
近.相信如能彻底理解 PageRank 算法,对于理解、设计其它算法将是十分有益
的.本实验将主要介绍该算法.
PageRank 算法用到的数学知识看上去并不十分高深,但十分实用.主要用到
线性代数的一些知识,包括:正矩阵性质、特征向量与特征值关系、幂迭代方法
(Power Iteration)和 Gauss-Seidel 迭代方法等.
实验中的一些程序看起来是小题大作,比如对已知的 6 阶方阵 A ,用 Matlab
求解代数方程 x  Ax 不是十分困难的事.但如若方阵 A 的阶数是 60、600、6000、
60000,你的方法将可能彻底崩溃.因此,认真学习本实验的一些计算方法是有
意义的.通过实践对比,你会发现这些算法的效率是相当高的,特别适合大规模
计算.事实上,Google 采用的是大规模的并行计算技术,以求解高达上亿阶的
代数方程 x  Ax .

下面我们先简要介绍一下什么是 PageRank 算法.

1. 什么是 PageRank(网页级别)?
PageRank(网页级别)是 Google 用于评测一个网页“重要性”的一种方法.在
揉合了诸如 Title 标识和 Keywords 标识等所有其它因素之后,Google 通过
PageRank 来调整结果,使那些更具“重要性”的网页在搜索结果中令网站排名
获得提升,从而提高搜索结果的相关性和质量.
简单说来,Google 通过下述几个步骤来实现网页在其搜索结果页(SERPS)中
的排名:
1) 找到所有与搜索关键词匹配的网页;
2) 根据页面因素如标题\关键词密度等排列等级;

126
3) 计算导入链接的锚文本中的关键词;
4) 通过 PageRank 得分调整网站排名结果.
事实上,真正的网站排名过程并不是这么简单,读者可参见有关网站,获得
更详细、深入的阐述.

2.PageRank 的决定因素
Google 的 PageRank 是基于这样一个理论:若 B 网页设置有连接 A 网页的链
接(B 为 A 的导入链接时),说明 B 认为 A 有链接价值,是一个“重要”的网页.当
B 网页级别(重要性)比较高时,则 A 网页可从 B 网页这个导入链接分得一定的级
别(重要性),并平均分配给 A 网页上的导出链接.
导入链接(也叫逆向链接)指链至你网站的站点,也就是我们一般所说的“外
部链接”.而当你链至另外一个站点,那么这个站点就是你的“导出链接”,即你
向其它网站提供的本站链接.
PageRank 反映了一个网页的导入链接的级别(重要性).所以一般说来,
PageRank 是由一个网站的导入链接的数量和这些链接的级别(重要性)所决定的.

3.如何知道一个网页的 PageRank 得分
可从 http://toolbar.google.com 上下载并安装 Google 的工具栏,这样就能显示
所浏览网页的 PageRank 得分了.PageRank 得分从 0 到 10,若不能显示 PageRank
得分,可检查所安装版本号,需将老版本完全卸载,重启机器后安装最新版本即
可.

4.PageRank 的重要性
搜索引擎网站排名算法中的各排名因子的重要性均取决于它们所提供信息
的质量.但如果排名因子具有易操纵性,则往往会被一些网站管理员利用来实现
不良竞争.例如初引入的排名因子之一 —关键词元标识(Meta Keywords),是由
于理论上它可以很好地概括反映一个页面的内容,但后来却由于一些网站管理员
的恶意操纵而不得不黯然退出.所以“加权值” —即我们对该因子提供信息的
信任程度是由排名因子的易操纵程度和操纵程度共同决定的.
PageRank 无疑是颇难被操纵的一个排名因子了.但在它最初推出时针对的只
是链接的数量,所以被一些网站管理员钻了空子,利用链接工厂和访客簿等大量
低劣外部链接轻而易举地达到了自己的目的.Google 意识到这个问题后,便在
系统中整合了对链接的质量分析,并对发现的作弊网站进行封杀,从而不但有效
地打击了这种做法,而且保证了结果的相关性和精准度.

5.Google 如是说
关于 PageRank,最权威的发言人自然还是 Google.虽然 Google 不会也不可
能提供相关的技术信息,但我们亦可从中窥得一斑:
Chris:PageRank 的命名是基于“Page”,还是和某个创始人有关?
Google:PageRank 是以 Google 的联合创始人兼总裁 Larry Page 的名字命名
的.
Chris:Google 是否把 PageRank 视做显著区别于其它搜索引擎的一个特性?
Google:PageRank 是一种能够使 Google 在搜索速度和搜索结果的相关性上
区别于其它搜索引擎的技术.不唯如此,在排名公式中 Google 还使用了 100 种

127
其它的算法.
Chris:Google 是否认为引入 PageRank 可以显著提高搜索结果的质量?以后
是否仍将继续使用 PageRank?
Google:由于 PageRank 使用了量化方法来分析链接,所以它仍将是决定
Google 搜索什么是 PageRank(网页级别)结果页排名的一个重要因素.
Chris:您认为 Google 工具栏上的 PageRank 的信息对普通用户/网站管理员/
搜索引擎优化专家来说各有什么意义?
Google:Google 工具栏上所提供的 PageRank 信息仅作为一种网站评估信息
使用.用户们会觉得它很有趣,网站管理员一般用它来衡量网站性能.不过,由
于 PageRank 只是一个大体评估,所以对搜索引擎专家的价值并不大.
Chris:常有网站试图通过“链接工厂”和访客簿的手段达到提升 PageRank
的目的.对这样的网站 Google 有什么举措?
Google:Google 的工程师会经常更新 Google 的排名算法以防止对 Google 排
名的恶意操纵.

二、相关函数(命令)及简介
1.spy( ):查看稀疏矩阵的形状.
例如,b=bucky; % bucky 是 Matlab 内置的一个稀疏矩阵
spy(b)
2.full( ):将稀疏矩阵还原为普通方阵.
3.double( ):若输入的是字符则转化为相应的 ASCII 码;若输入的是整型数值
则转化为相应的实型数值.
4.pagerankpow( ):用幂迭代算法得到一个网站排名的向量.具体形式为:
[x,cnt]=pagerankpow(G),
其中 x 为排名向量,cnt 为迭代次数,G 为邻接矩阵.该函数在计算高阶矩阵
时有优势.
5.pagerank( ):是 Matlab 基于稀疏矩阵的用左除运算(x=A\b)的方法求解 Ax=b
的函数(计算高阶矩阵时可能会出现问题),用来得到一个网站排名的向量.
6.surfer( ):网上冲浪.用该命令可搜索从根网站出发的 n 个相关联的网站,并
建立相应的地址列表与邻接矩阵.
例如,[U,G]=surfer(‘http://www.harvard.edu’,500)
其中 U 为地址列表,G 为邻接矩阵.

三、实验内容
1.有向图的定义、术语和部分性质
生活中的关系许多是对称的,比如互相握手、交谈.但也有不少关系不是对
称的,比如认识关系,甲认识乙,并不意味着乙认识甲.还有如:投票、比赛等
关系也不对称.
有向图就是这些不对称关系的抽象.所谓有向图,是指由有限的非空元素集
和它的不同元素的有序数对集(可能为空集)组成的结构.图 1 就是一个有向图
D,共有 3 个顶点 V(D)={u, v, w}(有限的非空元素集称为顶点集)和 3 条弧
A(D)={(u,w), (w,u), (u,v)}(不同元素的有序数对集称为弧集).当有向图用画图的

128
方式来表示时,每条弧的方向就由箭头来指定.
有向图中有如下的术语:
1) D 的顶点集的基数称为 D 的阶,记作 p(D);D 的弧集的基数称为 D 的
大小,记作 q(D).
2) a=(u,v)是有向图的一条弧,并称之为从 u 邻接到 v,而 v 是从 u 邻接的;
一般设从 u 到 v 的长度为 1.
3) 有向图 D 的顶点 u 的出度(out-degree)是 D 中从 u 邻接的顶点个数,记
作 od(u);有向图 D 的顶点 u 的入度(in-degree)是 D 中邻接到 u 的顶点个数,记
作 id(u).

例 1 在图 1 中,p(D)=3,q(D)=3;od(u)= 2,id(u)=1;od(v)= 0,id(v)=1;


od(w)= 1,id(w)=1.

例2 在图 2 中,p(D)=6,q(D)=9;并且:

序号(Index) 顶点(Node) 入度(In-degree) 出度(Out-degree)


1 alpha 2 1
2 beta 1 2
3 gamma 1 3
4 delta 2 1
5 rho 1 1
6 sigma 2 1

图1 图2

为研究需要,定义有向图 D 的邻接矩阵 G   gij  ,其中:

1, 若存在从 j 到 i 的弧
gij  
 0, 否则
于是,对于图 2 所示的有向图,有:

129
0 0 0 1 1 0
1 0 0 0 0 0
 
0 1 0 0 0 0
G 
0 1 1 0 0 0
0 0 1 0 0 0
 
0 0 1 0 1 0

邻接矩阵的性质:
1)若定义行和 ri   gij ,列和 n j   g ij ,可以看出:行和 ri   gij 就是第
j i j

i 个顶点的入度(In-degree);而列和 n j   g ij 就是第 j 个顶点的出度(Out-degree);


i

2)  ri   n j  q( D) ,即它们都等于有向图 D 的大小(弧的个数).
i j

2. 简化的 PageRank 算法
如果我们把图 2 的每个顶点看成是一个网页,并把每个弧看成是网页之间的
“超级链接”,则图 2 此时可代表一个小型的网络,其中有 6 个网页和 9 个“超
级链接”.
例 3 一个自然的问题是:在图 2 所示的这 6 个网页中,哪个最重要?
解:一个简单的回答可以这样考虑:看谁的入度(in-degree)最多!此时,alpha、
delta、sigma 各有 2 票,其余各 1 票.因此,alpha、delta、sigma 最重要,并列
第 1,而其它 3 者并列第 2.

表 1 按入度(in-degree) 排名
序号(Index) 顶点(Node) 入度(In-degree) 排名(Rank)
1 alpha 2 1
2 beta 1 2
3 gamma 1 2
4 delta 2 1
5 rho 1 2
6 sigma 2 1
但这样的回答不能令人满意.按照现在的方法,你无法说出 alpha、delta、sigma
中哪一个最重要.
简化的 PageRank 算法:一个网页的重要性可以从以下 2 个方面来考虑:(1)
看谁的入度(in-degree)多;(2)本网页在网络中的排名靠前(排名向量的分量数
值大).用数学的语言可表达为:
设 u 是某个网页,其排名为 r (u ) ,记 Fu 是 u 邻接到的那些网页的集合, Bu 是
邻接到 u 的那些网页的集合, nv | Fv | 即是 v 邻接到的那些网页的总数,则有:
r (v)
r (u )  
vBu nv
(1)

根据上述的有向图理论,我们有:| Bu | id(u ) , nv | Fv | od(v) .如果我们用

130
r  (ri ) 来表示各个网页的名次, G  {gij } 表示邻接矩阵,则(1)可写成:
gij
ri   rj (2)
j nj

r  Gn r (3)

其中 Gn  {gij / n j } .

从(3)可以看出,网页的名次 r  (ri ) 实为矩阵 Gn 的对应于特征根为 1 的特


征向量(问题是:矩阵 Gn 一定有特征根 1 吗?).
0 1
算法公式(1)有明显的问题,例如 G    时,将得到 r1  r2 ,无法排名.为
1 0
此,要对算法公式(1)进行改进.

3.改进的 PageRank 算法
设 (u ) 是网页 u 开始时的名次, x(u ) 为某时刻的 PageRank 得分(名次),采
用下面的加权算法:
x (v )
x(u )  p    (u ) (4)
vBu nv
类似地,我们记 x  x(i ), i  1, 2,..., n ,   (u ) ,一般取 p  0.85 ,而   e ,其中

e={1,1,...,1}' ,而   (1  p ) / n ,于是(4)可写成:
( I  pGD) x   e (5)

其中 G 为邻接矩阵,而 D  diag{1/ n1 ,1/ n2 ,...,1/ nn } .

若规定:
n

x i  eT x  1, xi  0 , (6)
i 1

则   e= ee T x .由 x  pGDx   e 得到:

x  pGDx   e
 pGDx   e 1
 pGDx   e  eT x
 ( pGD   eeT ) x
 Ax
x  Ax (7)
其中
A  pGD   eeT (7a)
即:

131
 g11 g12 g1n 
p n  p    
p
1 n2 nn
 
g
 p 21   g g 2n
p 22    p 
A   n1 n2 nn  (8)
     
 g gn2 g 
 p n1   p   p nn   
 n1 n2 nn 
注意:
g ij 1
1)如果 j , g ij  0, i ,此时会导致 n j  0 ,此时则规定:  ;
nj n
2)在约束条件(6)下求解问题(7),它具有唯一解 x ,其依据是:

(Perron Frobnius 定理)如矩阵 A 是正的方阵,则:


(a)A 的谱半径  ( A)  0 .这里的  ( A)  max | i | , i 是 A 的特征值;
i

(b)  ( A) 是 A 的特征值;
n
(c) 存在唯一的 x  0 ,满足 Ax   ( A) x ,  i 1 xi  1 ;
(d)  ( A) 是 A 的单特征值;
(e) 若特征根    ( A) ,则 |  |  ( A) .即:  ( A) 是 A 的模最大的唯一的特征值.

例4 对图 2 所示的小型网络,按照改进的 PageRank 算法,计算 6 个网页


的排名,其中的 p  0.85 .

解: 程序参见附录 1.结果见表 2 所示.

表 2 按 PageRank 得分排名
排名(Rank) PageRank 得分(x) 顶点(Node) 原始序号(Index)
1 0.267490 alpha 1
2 0.252418 beta 2
3 0.169769 delta 4
4 0.132302 gamma 3
5 0.115555 sigma 6
6 0.062467 rho 5
说明:
1)依据例 3 的按入度(in-degree) 排名,alpha、delta、sigma 并列第 1,现在
按 PageRank 得分排名,变成了第 1、3、5;而原来 beta、gamma、rho 并列第 2,
现在变成了第 2、4、6.由此可见,简单直观的想法往往是不准确的.事实上,
由于 alpha 的重要性(排名第 1),从而提升了 beta 的名次.
2)上述的 p  0.85 不是最要紧的,读者可以换为与之接近的别的数值,看看

将发生怎样的变化.
到此为止,问题好象已经解决.但实际情况远没有结束.前面的实验中用的
是 6 阶方阵 A ,用 Matlab 直接求解代数方程 x  Ax 或求 A 的特征根与特征向量,

132
都不是十分困难的事.但如若方阵 A 的阶数是 6000、60000,简单地使用 Matlab
的求解命令是不可能的,也是不允许的.

4.PageRank 的计算方法—幂迭代方法(Power Iteration)


我们设想前面的实验中用的方阵 A 的阶数不是 6 阶,而是 6000 阶,Matlab
不能直接求解,而必须寻求适当的算法.本实验仅介绍幂迭代方法(Power
Iteration),一些经典的方法,如:Jacobi 迭代方法、Gauss-Seidel 迭代方法等都
可以在此一用,限于篇幅,从略.
设满足 x  Ax 方阵 A 具有 n 个线性无关的特征向量 x, y2 ,..., yn ,相应的特征
根为 1  1, 2 ,..., n , | i | 1  1 , i  2 .注意: x  {xi } 为 PageRank 名次向量,
且满足:  xi  1 .设 v 是任意一个向量,把 x, y2 ,..., yn 看成一个基向量组,则 v
可以由 x, y2 ,..., yn 线性表示,即:
v  a1 x  a2 y2  ...  an yn
两边同乘以方阵 A ,有
Av  a1 Ax  a2 Ay2  ...  an Ayn
Av  a1 x  a2 2 y2  ...  an n yn
如此重复 k  1 次,有
Ak v  a1 x  a2 2 k y2  ...  an n k yn
由于 | i | 1  1 , i  2 ,故当 k 充分大后, Ak v  a1 x ,从而有
sum( Ak v )  sum(a1 x )  a1sum( x )  a1

x  Ak v / a1  Ak v / sum( Ak v )
故 PageRank 名次向量 x  {xi } 可利用下式得到:
x  Ak v / sum( Ak v) ,对充分大的 k

具体算法:
1)输入矩阵 A ,初始向量 v0 ,并设 k  0 ,精度   0 ;
2)计算向量: vk 1  Avk ;
3)若 | vk 1  vk |  ,则计算 PageRank 名次 x  Ak v / sum( Ak v) 并停止计算;否则
k  k  1 ,并转到第 2)步.
例 5 对图 2 所示的小型网络,采用幂迭代方法(Power Iteration),计算 6
个网页的排名,其中的 p  0.85 .

解: 程序参见附录 2.经过 18 步(即 k  18 )迭代,所得的结果与例 4 完


全相同,见表 2 所示,此略.

5.进一步的问题
仔细分析附录 1、2 的程序,会发现一个致命的问题,即要求有向图 D 的邻
接矩阵 G   gij  的列向和不为 0.附录 1、2 的程序没有体现上述“ 1) 如果
g ij 1
j , g ij  0, i ,此时会导致 n j  0 ,则规定  ”的思想,因此,对于象下列
nj n

133
图 3 所示的小型网络,附录 1、2 的程序将无法运行(修改相应 G 就会出问题).

图3 图4

那么,应该如何修正这些程序呢?
附录 3 给出了一个相当不错的程序,看起来很正确,其实仍然有问题,你能
发现其中的问题并加以改正吗?
附录 4 给出了一个标准的程序,来自非常权威的人物 C. B. Moler 的 Numerical
Computing With Matlab (SIAM 2004) 的 工 具 箱 : ncm.zip 中 的 函 数
pagerankpow.m (略有改造!).这个程序可以说是最高水平的 Matlab 编程,几乎
没有用到大规模的乘除法,而主要以加减法为主.这大大节约了计算时间.更重
要的是,该程序巧妙地使用了细胞数组,对于象邻接矩阵 G   gij  这样的稀疏矩

阵,其效率是惊人的.其优势是对于阶数庞大的稀疏矩阵中的大量 0 元素不作计
算,而我们的程序(附录 1~附录 3)都没有体现这一点.我们程序的缺点是:明
明看到象邻接矩阵这样的稀疏矩阵,但我们仍然把它看成一个普通矩阵,于是,
大量的计算时间白白浪费.据报道,pagerankpow.m 程序的思想就是运行在
Google 网站的程序精髓.

6.一个重要的应用实例
下载 C. B. Moler 的 Numerical Computing With MATLAB (SIAM 2004) 的工具
箱: ncm.zip,并安装在我们的 MATLAB(要求是 6.5 或以上版本)的 Toolbox
中,里面将出现 78 个文件.其中有一个文件 harvard500.mat 记录了 2003 年 8 月
与哈佛大学的主页 http://www.harvard.edu 相关的 500 个网站的邻接矩阵,我们可
以用它来体会一下可以体现稀疏矩阵技术的 pagerankpow.m 程序的魅力.

%装载规模为 500 个网站的邻接矩阵 G,


%同时得到 500 个网站的地址名称矩阵 U
load harvard500
%用 spy 函数看看稀疏矩阵 G 的形状
spy(G);
%因为 G 是稀疏矩阵,不是方阵,要先用 full(G)将其还原为方阵,
%用 double 函数使其确保转化为数值方阵
G=double(full(G));

134
%调用 pagerankpow(G)求排名向量 x,
%以及收敛时的迭代次数 cnt,这里将为 13
[x,cnt]=pagerankpow(G);

%按 page-rank 大小给出前几十名的列表与图示等
pagerank(U,G)

结果为:
page-rank in out url
1 0.0843 195 26 http://www.harvard.edu
10 0.0167 21 18 http://www.hbs.edu
42 0.0166 42 0 http://search.harvard.edu:8765/custom/query.html
130 0.0163 24 12 http://www.med.harvard.edu
18 0.0139 45 46 http://www.gse.harvard.edu
15 0.0131 16 49 http://www.hms.harvard.edu
9 0.0114 21 27 http://www.ksg.harvard.edu
17 0.0111 13 6 http://www.hsph.harvard.edu
46 0.0100 18 21 http://www.gocrimson.com
13 0.0086 9 1 http://www.hsdm.med.harvard.edu
260 0.0086 26 1 http://search.harvard.edu:8765/query.html
19 0.0084 23 21 http://www.radcliffe.edu
121 0.0079 1 3 http://www.hsdm.harvard.edu
52 0.0077 11 2 http://whitepages.med.harvard.edu
3 0.0077 21 12 http://lib.harvard.edu
222 0.0075 36 34 http://www.gse.harvard.edu/sitemap.html
262 0.0074 20 3 http://www.dana-farber.org
223 0.0071 36 10 http://www.gse.harvard.edu/search.html
16 0.0071 13 13 http://www.hds.harvard.edu
7 0.0069 11 14 http://search.harvard.edu:8765
102 0.0067 16 11 http://www.hbs.edu/siteindex/siteindex.html
27 0.0064 17 2 http://www.researchmatters.harvard.edu
26 0.0064 17 3 http://www.news.harvard.edu/gazette/calendar
8 0.0062 7 10 http://www.fas.harvard.edu
6 0.0059 12 0 http://www.haa.harvard.edu
214 0.0059 29 4 http://www.gse.harvard.edu/news
12 0.0059 9 7 http://www.dce.harvard.edu
335 0.0057 17 0 http://www.studentadvantage.com
85 0.0057 10 6 http://www.harvard.edu/copyright.html
101 0.0056 16 3 http://www.hbs.edu:8765
329 0.0055 17 18 http://gocrimson.ocsn.com/tickets/harv-tickets.html
11 0.0055 4 6 http://www.law.harvard.edu
249 0.0054 17 0 http://www.news.harvard.edu/gazette/search
281 0.0053 21 1 http://www.jimmyfund.org
261 0.0053 21 0 http://www.dana-farber.org/favicon.ico
…………

四、自己动手

135
1.将附录 1、2 中的 p  0.85 修改为 p  0.80 、p  0.75 或 p  0.90 等数值以后,

观察 PageRank 得分和排名结果的变化情况;
2.为计算图 1 所示的小型网络的排名,请修改附录 1、2 的程序;
3.分析、改正附录 3 程序中的问题.并用于处理图 3 所示的小型网络的排名计
算;
4.计算图 4 所示的小型网络的排名,分析与图 2 所示的小型网络的排名发生变
化的原因;
5.查看工具箱 ncm 中的文件 surfer.m 的作用;
6.用命令
[U,G] = surfer('http://www.ecnu.edu.cn',100)
建立与华东师范大学主页有关的 100 个网页的网址矩阵 U 和邻接矩阵 G,并回
答如下问题:
(1)请问华东师范大学图书馆主页排在第几名?Pagerank 是多少?它分别
有多少个入度和出度?
(2)请问华东师范大学 BBS 主页排在第几名?Pagerank 是多少?它分别有
多少个入度和出度?
7.用命令
[U,G] = surfer('http://www.ecnu.edu.cn',500)
建立与华东师范大学主页有关的 500 个网页的网址矩阵 U 和邻接矩阵 G.华东
师范大学数学系主页处于什么位置?

五、附录
附录 1(例 4 的程序):(fulu1.m)
clear
G=[ 0 0 0 1 0 1;
1 0 0 0 0 0;
0 1 0 0 0 0;
0 1 1 0 0 0;
0 0 1 0 0 0;
0 0 1 0 1 0];
[n,n]=size(G);
sn=sum(G,1); %%G 的列和
% Power method
p=0.85;
delta=(1-p)/n;
D=zeros(n,1);
for j=1:n,
if sn(j)==0,
D(j)=1/n;
G(:,j)=ones(n,1);
else
D(j)=1/sn(j);

136
end
end
D=diag(D);
A=p*G*D+delta*ones(n);
x=ones(n,1)/n;
z=zeros(n,1);
cnt=0;
while max(abs(x-z))>0.0001,
z=x;
x=A*x;
cnt=cnt+1;
end
[x1,index]=sort(x);
x1=flipud(x1);
index=flipud(index);
title={'排名(Rank)','PageRank 得分(x)','顶点(Node)','原始序号(Index)'};
sites={'alpha','beta','gamma','delta','rho','sigma'};
fprintf(' 按 PageRank 得分排名\n');
fprintf('------------------------------------------------------------\n');
fprintf('%-11s %-16s %-11s %s\n',title{1},title{2},title{3},title{4});
fprintf('------------------------------------------------------------\n');
for i=1:6
fprintf('%-11d %-16f %-11s %d\n',i,x1(i),sites{index(i)},index(i));
end

附录 2(例 5 的程序):(fulu2.m)
G=[0 0 0 1 0 1;
1 0 0 0 0 0;
0 1 0 0 0 0;
0 1 1 0 0 0;
0 0 1 0 0 0;
0 0 1 0 1 0]; % Link structrue
[n,n]=size(G);
p=0.85;
delta=(1-p)/n;
sn=sum(G,1); % 按列求矩阵 G 各列的列和
D=diag(1./sn);
A=p*G*D + delta;
% 幂迭代法
x=ones(n,1)/n; % 迭代初始向量
z=zeros(n,1);
cnt=0; % 用于记录迭步数
while max(abs(x-z)) > 0.0001
z = x;

137
x = A*x;
cnt=cnt+1;
end
[x1,index]=sort(x);
x1=flipud(x1);
index=flipud(index);
% 输出结果
out=[1:n; x1'; index'];
fprintf('迭代步数 = %d\n',cnt)
str1='排名'; str2='PageRank 得分';str3='序号';
fprintf('%-6s %-15s %-5s\n',str1,str2,str3);
fprintf('% -6d %-15f %-5d\n',out);

附录 3:(fulu3.m)
G=[0 0 0 1 0 1;
1 0 0 0 0 0;
0 1 0 0 0 0;
0 1 1 0 0 0;
0 0 1 0 0 0;
0 0 1 0 1 0 ]; % Link structrue
[n,n]=size(G);
sn=sum(G,1); %%G 的列和
% Power method
p=0.85;
delta=(1-p)/n;
D=zeros(n,1);
for j=1:n,
if sn(j)==0,
D(j)=1/n;
else
D(j)=1/sn(j);
end
end
D=diag(D);
A=p*G*D+delta*ones(n);
x=ones(n,1)/n;
z=zeros(n,1);
cnt=0;
while max(abs(x-z))>0.0001,
z=x;
x=A*x;
cnt=cnt+1;
end
[x1,index]=sort(x);

138
x1=flipud(x1);
index=flipud(index);
% 输出结果
out=[1:n; x1'; index'];
fprintf('迭代步数 = %d\n',cnt)
fprintf('----- 按 Rank 排列 ----- \n')
str={'排名','PageRank 得分','序号'};
fprintf('%-6s %-15s %-5s\n',str{1},str{2},str{3});
fprintf('% -6d %-15f %-5d\n',out);
fprintf('----- 按序号排列 ----- \n')
str={'序号','PageRank 得分','排名'};
x2=x; [tmp,rank]=sort(index);
out=[1:n; x2'; rank'];
fprintf('%-6s %-15s %-5s\n',str{1},str{2},str{3});
fprintf('% -6d %-15f %-5d\n',out);

附录 4:(fulu4.m)
aa=cputime;
G=[
0 0 0 1 0 1;
1 0 0 0 0 0;
0 1 0 0 0 0;
0 1 1 0 0 0;
0 0 1 0 0 0;
001010
];
G=double(full(G));
% Link structrue
[n,n]=size(G);
for j=1:n,
L{j}=find(G(:,j));
c(j)=length(L{j});
end
% Power method
p=0.85;
delta=(1-p)/n;
x=ones(n,1)/n;
z=zeros(n,1);
cnt=0;
while max(abs(x-z))>0.0001,
z=x;
x=zeros(n,1);
for j=1:n,
if c(j)==0,

139
x=x+z(j)/n;
else
x(L{j})=x(L{j})+z(j)/c(j);
end
end
x=p*x+delta;
cnt=cnt+1;
end
bb=cputime;
[x1,index]=sort(x);
x1=flipud(x1);
index=flipud(index);
title={'排名(Rank)','PageRank 得分(x)','顶点(Node)','原始序号(Index)'};
sites={'alpha','beta','gamma','delta','rho','sigma'};
fprintf(' 按 PageRank 得分排名\n');
fprintf('------------------------------------------------------------\n');
fprintf('%-11s %-16s %-11s %s\n',title{1},title{2},title{3},title{4});
fprintf('------------------------------------------------------------\n');
for i=1:6
fprintf('%-11d %-16f %-11s %d\n',i,x1(i),sites{index(i)},index(i));
end
fprintf('程序运行时间为:%12.10g 秒\n',bb-aa);

140
实验十 遗传算法与优化问题

一、问题背景与实验目的
遗传算法(Genetic Algorithm—GA),是模拟达尔文的遗传选择和自然淘汰
的生物进化过程的计算模型,它是由美国 Michigan 大学的 J.Holland 教授于 1975
年首先提出的.遗传算法作为一种新的全局优化搜索算法,以其简单通用、鲁棒
性强、适于并行处理及应用范围广等显著特点,奠定了它作为 21 世纪关键智能
计算之一的地位.
本实验将首先介绍一下遗传算法的基本理论,然后用其解决几个简单的函数
最值问题,使读者能够学会利用遗传算法进行初步的优化计算.
1.遗传算法的基本原理
遗传算法的基本思想正是基于模仿生物界遗传学的遗传过程.它把问题的参
数用基因代表,把问题的解用染色体代表(在计算机里用二进制码表示),从而
得到一个由具有不同染色体的个体组成的群体.这个群体在问题特定的环境里生
存竞争,适者有最好的机会生存和产生后代.后代随机化地继承了父代的最好特
征,并也在生存环境的控制支配下继续这一过程.群体的染色体都将逐渐适应环
境,不断进化,最后收敛到一族最适应环境的类似个体,即得到问题最优的解.值
得注意的一点是,现在的遗传算法是受生物进化论学说的启发提出的,这种学说
对我们用计算机解决复杂问题很有用,而它本身是否完全正确并不重要(目前生
物界对此学说尚有争议).
(1)遗传算法中的生物遗传学概念
由于遗传算法是由进化论和遗传学机理而产生的直接搜索优化方法;故而在
这个算法中要用到各种进化和遗传学的概念.
首先给出遗传学概念、遗传算法概念和相应的数学概念三者之间的对应关
系.这些概念如下:
序号 遗传学概念 遗传算法概念 数学概念
1 个体 要处理的基本对象、结构 也就是可行解
2 群体 个体的集合 被选定的一组可行解
3 染色体 个体的表现形式 可行解的编码
4 基因 染色体中的元素 编码中的元素
5 基因位 某一基因在染色体中的位置 元素在编码中的位置
6 适应值 个体对于环境的适应程度, 可行解所对应的适应函数
或在环境压力下的生存能力 值
7 种群 被选定的一组染色体或个体 根据入选概率定出的一组
可行解
8 选择 从群体中选择优胜的个体, 保留或复制适应值大的可
淘汰劣质个体的操作 行解,去掉小的可行解
9 交叉 一组染色体上对应基因段的 根据交叉原则产生的一组
交换 新解
10 交叉概率 染色体对应基因段交换的概 闭区间[0,1]上的一个值,
率(可能性大小) 一般为 0.65~0.90
11 变异 染色体水平上基因变化 编码的某些元素被改变

141
12 变异概率 染 色 体 上 基 因 变 化 的 概 率 开 区 间 (0,1) 内 的 一 个 值 ,
(可能性大小) 一般为 0.001~0.01
13 进化、 个体进行优胜劣汰的进化, 目标函数取到最大值,最
适者生存 一代又一代地优化 优的可行解
(2)遗传算法的步骤
遗传算法计算优化的操作过程就如同生物学上生物遗传进化的过程,主要有
三个基本操作(或称为算子):选择(Selection)、交叉(Crossover)、变异(Mutation).
遗传算法基本步骤主要是:先把问题的解表示成“染色体”,在算法中也就
是以二进制编码的串,在执行遗传算法之前,给出一群“染色体”,也就是假设
的可行解.然后,把这些假设的可行解置于问题的“环境”中,并按适者生存的
原则,从中选择出较适应环境的“染色体”进行复制,再通过交叉、变异过程产
生更适应环境的新一代“染色体”群.经过这样的一代一代地进化,最后就会收
敛到最适应环境的一个“染色体”上,它就是问题的最优解.
下面给出遗传算法的具体步骤,流程图参见图 1:
第一步:选择编码策略,把参数集合(可行解集合)转换染色体结构空间;
第二步:定义适应函数,便于计算适应值;
第三步:确定遗传策略,包括选择群体大小,选择、交叉、变异方法以及确
定交叉概率、变异概率等遗传参数;
第四步:随机产生初始化群体;
第五步:计算群体中的个体或染色体解码后的适应值;
第六步:按照遗传策略,运用选择、交叉和变异算子作用于群体,形成下一
代群体;
第七步:判断群体性能是否满足某一指标、或者是否已完成预定的迭代次数,
不满足则返回第五步、或者修改遗传策略再返回第六步.

产生初始群体

得到结果 是 是否满足终止条件


结束程序
计算每个个体的适应值

以概率选择遗传算子

选择一个个体 选择两个个体进行 选择一个个体进行


复制到新群体 交叉插入到新群体 变异插入到新群体

得到新群体

图1 一个遗传算法的具体步骤

142
遗传算法有很多种具体的不同实现过程,以上介绍的是标准遗传算法的主要
步骤,此算法会一直运行直到找到满足条件的最优解为止.
2.遗传算法的实际应用
例 1:设 f ( x)   x2  2 x  0.5 ,求 max f ( x), x  [1, 2] .
注:这是一个非常简单的二次函数求极值的问题,相信大家都会做.在此我
们要研究的不是问题本身,而是借此来说明如何通过遗传算法分析和解决问题.
在此将细化地给出遗传算法的整个过程.
(1)编码和产生初始群体
首先第一步要确定编码的策略,也就是说如何把 1 到 2 这个区间内的数用计
算机语言表示出来.
编码就是表现型到基因型的映射,编码时要注意以下三个原则:
完备性:问题空间中所有点(潜在解)都能成为 GA 编码空间中的点(染色
体位串)的表现型;
健全性:GA 编码空间中的染色体位串必须对应问题空间中的某一潜在解;
非冗余性:染色体和潜在解必须一一对应.
这里我们通过采用二进制的形式来解决编码问题,将某个变量值代表的个体
表示为一个{0,1}二进制串.当然,串长取决于求解的精度.如果要设定求解精
度到六位小数,由于区间长度为 2  (1)  3 ,则必须将闭区间 [1, 2] 分为 3 106
等分.因为 2097152  221  3 106  222  4194304 所以编码的二进制串至少需要
22 位.
将一个二进制串(b21b20 b19…b1b0)转化为区间 [1, 2] 内对应的实数值很简单,
只需采取以下两步(Matlab 程序参见附录 4):
1)将一个二进制串(b21b20 b19…b1b0)代表的二进制数化为 10 进制数:
21
(b21b20b19 b1b0 )2  ( bi  2i )10  x '
i 0

2) x ' 对应的区间 [1, 2] 内的实数:


2  (1)
x  1  x'
2 22  1
例如,一个二进制串 a=<1000101110110101000111>表示实数 0.637197.
x ' =(1000101110110101000111)2=2288967
3
x  1  2288967  22  0.637197
2 1
二进制串<0000000000000000000000>,<1111111111111111111111>,则分别
表示区间的两个端点值-1 和 2.
利用这种方法我们就完成了遗传算法的第一步——编码,这种二进制编码的
方法完全符合上述的编码的三个原则.
首先我们来随机的产生一个个体数为 4 个的初始群体如下:
pop(1)={
<1101011101001100011110>, %% a1
<1000011001010001000010>, %% a2
<0001100111010110000000>, %% a3
<0110101001101110010101>} %% a4(Matlab 程序参见附录 2)
化成十进制的数分别为:

143
pop(1)={ 1.523032,0.574022 ,-0.697235 ,0.247238 }
接下来我们就要解决每个染色体个体的适应值问题了.
(2)定义适应函数和适应值
由于给定的目标函数 f ( x )   x 2  2 x  0.5 在 [1, 2] 内的值有正有负,所以必
须通过建立适应函数与目标函数的映射关系,保证映射后的适应值非负,而且目
标函数的优化方向应对应于适应值增大的方向,也为以后计算各个体的入选概率
打下基础.
对于本题中的最大化问题,定义适应函数 g ( x) ,采用下述方法:
 f ( x )  Fmin , 若 f ( x)  Fmin  0
g ( x)  
 0, 其他
式中 Fmin 既可以是特定的输入值,也可以是当前所有代或最近 K 代中 f ( x ) 的最
小值,这里为了便于计算,将采用了一个特定的输入值.
若取 Fmin  1 ,则当 f ( x)  1 时适应函数 g ( x)  2 ;当 f ( x )  1.1 时适应函数
g ( x)  0 .
由上述所随机产生的初始群体,我们可以先计算出目标函数值分别如下
(Matlab 程序参见附录 3):
f [pop(1)]={ 1.226437 , 1.318543 , -1.380607 , 0.933350 }
然后通过适应函数计算出适应值分别如下(Matlab 程序参见附录 5、附录 6):
取 Fmin  1 ,
g[pop(1)]= { 2.226437 , 2.318543 , 0 , 1.933350 }
(3)确定选择标准
这里我们用到了适应值的比例来作为选择的标准,得到的每个个体的适应值
比例叫作入选概率.其计算公式如下:
对于给定的规模为 n 的群体 pop={ a 1 , a2 , a3 , , an },个体 ai 的适应值为 g (ai ) ,

则其入选概率为
g (ai )
Ps (ai )  n
, i  1, 2,3,, n
 g (a )
i 1
i

由上述给出的群体,我们可以计算出各个个体的入选概率.
4
首先可得  g ( a )  6.478330 ,
i
i 1
4
然后分别用四个个体的适应值去除以  g (ai ) ,得:
i 1

P(a1)=2.226437 / 6.478330 = 0.343675 %% a1


P(a2)=2.318543 / 6.478330 = 0.357892 %% a2
P(a3)= 0 / 6.478330 = 0 %% a3
P(a4)=1.933350 / 6.478330 = 0.298433 %% a4(Matlab 程序参见附录 7)
(4)产生种群
计算完了入选概率后,就将入选概率大的个体选入种群,淘汰概率小的个体,
并用入选概率最大的个体补入种群,得到与原群体大小同样的种群(Matlab 程序
参见附录 8、附录 11).

144
要说明的是:附录 11 的算法与这里不完全相同.为保证收敛性,附录 11 的
算法作了修正,采用了最佳个体保存方法(elitist model),具体内容将在后面给
出介绍.
由初始群体的入选概率我们淘汰掉 a3,再加入 a2 补足成与群体同样大小的
种群得到 newpop(1)如下:
newpop(1)={
<1101011101001100011110>, %% a1
<1000011001010001000010>, %% a2
<1000011001010001000010>, %% a2
<0110101001101110010101>} %% a4
(5)交叉
交叉也就是将一组染色体上对应基因段的交换得到新的染色体,然后得到新
的染色体组,组成新的群体(Matlab 程序参见附录 9).
我们把之前得到的 newpop(1)的四个个体两两组成一对,重复的不配对,进
行交叉.(可以在任一位进行交叉)
<110101110 1001100011110>, <1101011101010001000010>
交叉得:
<100001100 1010001000010>, <1000011001001100011110>

<10000110010100 01000010>, <1000011001010010010101>


交叉得:
<01101010011011 10010101>, <0110101001101101000010>

通过交叉得到了四个新个体,得到新的群体 jchpop (1)如下:


jchpop(1)={
<1101011101010001000010>,
<1000011001001100011110>,
<1000011001010010010101>,
<0110101001101101000010>}
这里采用的是单点交叉的方法,当然还有多点交叉的方法,不过有些烦琐,
这里就不着重介绍了.
(6)变异
变异也就是通过一个小概率改变染色体位串上的某个基因(Matlab 程序参见
附录 10).
现把刚得到的 jchpop(1)中第 3 个个体中的第 9 位改变,就产生了变异,得到
了新的群体 pop(2)如下:
pop(2)= {
<1101011101010001000010>,
<1000011001001100011110>,

<1000011011010010010101>,
<0110101001101101000010> }
然后重复上述的选择、交叉、变异直到满足终止条件为止.
(7)终止条件

145
遗传算法的终止条件有两类常见条件:(1)采用设定最大(遗传)代数的方
法,一般可设定为 50 代,此时就可能得出最优解.此种方法简单易行,但可能
不是很精确(Matlab 程序参见附录 1);(2)根据个体的差异来判断,通过计算
种群中基因多样性测度,即所有基因位相似程度来进行控制.
3.遗传算法的收敛性
前面我们已经就遗传算法中的编码、适应度函数、选择、交叉和变异等主要
操作的基本内容及设计进行了详细的介绍.作为一种搜索算法,遗传算法通过对
这些操作的适当设计和运行,可以实现兼顾全局搜索和局部搜索的所谓均衡搜
索,具体实现见下图 2 所示.

图2 均衡搜索的具体实现图示

应该指出的是,遗传算法虽然可以实现均衡的搜索,并且在许多复杂问题的
求解中往往能得到满意的结果,但是该算法的全局优化收敛性的理论分析尚待解
决.目前普遍认为,标准遗传算法并不保证全局最优收敛.但是,在一定的约束
条件下,遗传算法可以实现这一点.
下面我们不加证明地罗列几个定理或定义,供读者参考(在这些定理的证明
中,要用到许多概率论知识,特别是有关马尔可夫链的理论,读者可参阅有关文
献).
定理 1 如果变异概率为 Pm  (0,1) ,交叉概率为 Pc  [0,1] ,同时采用比例选

择法(按个体适应度占群体适应度的比例进行复制),则标准遗传算法的变换矩
阵 P 是基本的.
定理 2 标准遗传算法(参数如定理 1)不能收敛至全局最优解.
由定理 2 可以知道,具有变异概率 Pm  (0,1) ,交叉概率为 Pc  [0,1] 以及按比

例选择的标准遗传算法是不能收敛至全局最最优解.我们在前面求解例 1 时所用
的方法就是满足定理 1 的条件的方法.这无疑是一个令人沮丧的结论.
然而,庆幸的是,只要对标准遗传算法作一些改进,就能够保证其收敛性.具
体如下:我们对标准遗传算法作一定改进,即不按比例进行选择,而是保留当前
所得的最优解(称作超个体).该超个体不参与遗传.
最佳个体保存方法(elitist model)的思想是把群体中适应度最高的个体不
进行配对交叉而直接复制到下一代中.此种选择操作又称复制(copy).De Jong
对此方法作了如下定义:

146
定义 设到时刻 t(第 t 代)时,群体中 a*(t)为最佳个体.又设 A(t+1)
为新一代群体,若 A(t+1)中不存在 a*(t) ,则把 a*(t)作为 A(t+1)中的第
n+1 个个体(其中,n 为群体大小)(Matlab 程序参见附录 11).
采用此选择方法的优点是,进化过程中某一代的最优解可不被交叉和变异操
作所破坏.但是,这也隐含了一种危机,即局部最优个体的遗传基因会急速增加
而使进化有可能限于局部解.也就是说,该方法的全局搜索能力差,它更适合单
峰性质的搜索空间搜索,而不是多峰性质的空间搜索.所以此方法一般都与其他
选择方法结合使用.
定理 3 具有定理 1 所示参数,且在选择后保留当前最优值的遗传算法最终
能收敛到全局最优解.
当然,在选择算子作用后保留当前最优解是一项比较复杂的工作,因为该解
在选择算子作用后可能丢失.但是定理 3 至少表明了这种改进的遗传算法能够收
敛至全局最优解.有意思的是,实际上只要在选择前保留当前最优解,就可以保
证收敛,定理 4 描述了这种情况.
定理 4 具有定理 1 参数的,且在选择前保留当前最优解的遗传算法可收敛
于全局最优解.
例 2:设 f ( x)  3  x2  x ,求 max f ( x), x  [0, 2] ,编码长度为 5,采用上述
定理 4 所述的“在选择前保留当前最优解的遗传算法”进行.
此略,留作练习.

二、相关函数(命令)及简介
本实验的程序中用到如下一些基本的 Matlab 函数:ones, zeros, sum, size,
length, subs, double 等,以及 for, while 等基本程序结构语句,读者可参考前面
专门关于 Matlab 的介绍,也可参考其他数学实验章节中的“相关函数(命令)
及简介”内容,此略.

三、实验内容
上述例 1 的求解过程为:
群体中包含六个染色体,每个染色体用 22 位 0—1 码,变异概率为 0.01,变
量区间为 [1, 2] ,取 Fmin= 2 ,遗传代数为 50 代,则运用第一种终止条件(指

定遗传代数)的 Matlab 程序为:


[Count,Result,BestMember]=Genetic1(22,6,'-x*x+2*x+0.5',-1,2,-2,0.01,50)
执行结果为:
Count =
50
Result =
1.0316 1.0316 1.0316 1.0316 1.0316 1.0316
1.4990 1.4990 1.4990 1.4990 1.4990 1.4990
BestMember =
1.0316

147
1.4990

图2 例 1 的计算结果
(注:上图为遗传进化过程中每一代的个体最大适应度;
而下图为目前为止的个体最大适应度——单调递增)

我们通过 Matlab 软件实现了遗传算法,得到了这题在第一种终止条件下的最


优解:当 x 取 1.0316 时, Max f ( x )  1.4990 .
当然这个解和实际情况还有一点出入(应该是 x 取 1 时,Max f ( x )  1.5000 ),
但对于一个计算机算法来说已经很不错了.
我们也可以编制 Matlab 程序求在第二种终止条件下的最优解.此略,留作练
习.实践表明,此时的遗传算法只要经过 10 代左右就可完成收敛,得到另一个
“最优解”,与前面的最优解相差无几.

四、自己动手
1.用 Matlab 编制另一个主程序 Genetic2.m,求例 1 的在第二种终止条件下的最
优解.
提示:一个可能的函数调用形式以及相应的结果为:
[Count,Result,BestMember]=Genetic2(22,6,'-x*x+2*x+0.5',-1,2,-2,0.01,0.00001)
Count =
13
Result =
1.0392 1.0392 1.0392 1.0392 1.0392 1.0392
1.4985 1.4985 1.4985 1.4985 1.4985 1.4985
BestMember =
1.0392
1.4985

148
可以看到:两组解都已经很接近实际结果,对于两种方法所产生的最优解差
异很小.可见这两种终止算法都是可行的,而且可以知道对于例 1 的问题,遗传
算法只要经过 10 代左右就可以完成收敛,达到一个最优解.
2.按照例 2 的具体要求,用遗传算法求上述例 2 的最优解.
3.附录 9 子程序 Crossing.m 中的第 3 行到第 7 行为注解语句.若去掉前面的%
号,则程序的算法思想有什么变化?
4.附录 9 子程序 Crossing.m 中的第 8 行至第 13 行的程序表明,当 Dim(1)>=3
时,将交换数组 Population 的最后两行,即交换最后面的两个个体.其目的
是什么?
5.仿照附录 10 子程序 Mutation.m,修改附录 9 子程序 Crossing.m,使得交叉过
程也有一个概率值(一般取 0.65~0.90);同时适当修改主程序 Genetic1.m 或
主程序 Genetic2.m,以便代入交叉概率.
6.设 f ( x)   x2  4 x  1 ,求 max f ( x), x  [2, 2] ,要设定求解精度到 15 位小数.

五、附录
附录 1:主程序 Genetic1.m
function
[Count,Result,BestMember]=Genetic1(MumberLength,MemberNumber,FunctionFitn
ess,MinX,MaxX,Fmin,MutationProbability,Gen)
Population=PopulationInitialize(MumberLength,MemberNumber);
global Count;
global CurrentBest;
Count=1;
PopulationCode=Population;
PopulationFitness=Fitness(PopulationCode,FunctionFitness,MinX,MaxX,Mumbe
rLength);

149
PopulationFitnessF=FitnessF(PopulationFitness,Fmin);
PopulationProbability=Probability(PopulationFitnessF);
[Population,CurrentBest,EachGenMaxFitness]=Elitist(PopulationCode,Populatio
nFitness,MumberLength);
EachMaxFitness(Count)=EachGenMaxFitness;
MaxFitness(Count)=CurrentBest(length(CurrentBest));

while Count<Gen
NewPopulation=Select(Population,PopulationProbability,MemberNumber);
Population=NewPopulation;

NewPopulation=Crossing(Population,FunctionFitness,MinX,MaxX,MumberLength);
Population=NewPopulation;
NewPopulation=Mutation(Population,MutationProbability);
Population=NewPopulation;

PopulationFitness=Fitness(Population,FunctionFitness,MinX,MaxX,MumberLength);
PopulationFitnessF=FitnessF(PopulationFitness,Fmin);
PopulationProbability=Probability(PopulationFitnessF);
Count=Count+1;

[NewPopulation,CurrentBest,EachGenMaxFitness]=Elitist(Population,PopulationFitn
ess,MumberLength);
EachMaxFitness(Count)=EachGenMaxFitness;;
MaxFitness(Count)=CurrentBest(length(CurrentBest));
Population=NewPopulation;
end
Dim=size(Population);
Result=ones(2,Dim(1));
for i=1:Dim(1)
Result(1,i)=Translate(Population(i,:),MinX,MaxX,MumberLength);
end
Result(2,:)=PopulationFitness;
BestMember(1,1)=Translate(CurrentBest(1:MumberLength),MinX,MaxX,Mumb
erLength);
BestMember(2,1)=CurrentBest(MumberLength+1);
close all
subplot(211)
plot(EachMaxFitness)
subplot(212)
plot(MaxFitness)

【程序说明】主程序 Genetic1.m 包含了 8 个输入参数:


(1) MumberLength: 表示一个染色体位串的二进制长度.(例 1 中取 22)

150
(2) MemberNumber: 表示群体中染色体的个数.(例 1 中取 6 个)
(3) FunctionFitness: 表示目标函数,是个字符串,因此用表达式时,用单
引号括出.(例 1 中是 f ( x )   x 2  2 x  0.5 )
(4) MinX: 变量区间的下限.(例 1 中是 [1, 2] 中的)
(5) MaxX: 变量区间的上限.(例 1 中是 [1, 2] 中的 2)
(6) Fmin: 定义适应函数过程中给出的一个目标函数的可能的最小值,由
操作者自己给出.(例 1 中取 Fmin= 2 )
(7) MutationProbability: 表示变异的概率,一般都很小.(例 1 中取 0.01)
(8) Gen: 表示遗传的代数,也就是终止程序时的代数.(例 1 中取 50)

另外,主程序 Genetic1.m 包含了 3 个输出值: Count 表示遗传的代数;Result


表示计算的结果,也就是最优解;BestMember 表示最优个体及其适应值.

附录 2:子程序 PopulationInitialize.m
function Population=PopulationInitialize(MumberLength,MemberNumber)
Temporary=rand(MemberNumber,MumberLength);
Population=(Temporary>=0.5*ones(size(Temporary)));

【程序说明】子程序 PopulationInitialize.m 用于产生一个初始群体.这个初始群


体含有 MemberNumber 个染色体,每个染色体有 MumberLength 个基因(二进制
码).

附录 3:子程序 Fitness.m
function PopulationFitness=
Fitness(PopulationCode,FunctionFitness,MinX,MaxX,MumberLength)
Dim=size(PopulationCode);
PopulationFitness=zeros(1,Dim(1));
for i=1:Dim(1)
PopulationFitness(i)=
Transfer(PopulationCode(i,:),FunctionFitness,MinX,MaxX,MumberLength);
end

【程序说明】子程序 Fitness.m 用于计算群体中每一个染色体的目标函数值.子


程序中含有 5 个输入参数:PopulationCode 表示用 0—1 代码表示的群体,
FunctionFitness 表示目标函数,它是一个字符串,因此写入调用程序时,应该用
单引号括出,MumberLength 表示染色体位串的二进制长度.MinX 和 MaxX 分
别指变量区间的上下限.

附录 4:子程序 Translate.m
function PopulationData=Translate(PopulationCode,MinX,MaxX,MumberLength)
PopulationData=0;
Dim=size(PopulationCode);
for i=1:Dim(2)

151
PopulationData=PopulationData+PopulationCode(i)*(2^(MumberLength-i));
end
PopulationData=MinX+PopulationData*(MaxX-MinX)/(2^Dim(2)-1);

【程序说明】子程序 Translate.m 把编成码的群体翻译成变量的数值.含有 4 个


输入参数,PopulationCode, MinX, MaxX, MumberLength.

附录 5:子程序 Transfer.m
function PopulationFitness=
Transfer(PopulationCode,FunctionFitness,MinX,MaxX,MumberLength)
PopulationFitness=0;
PopulationData=Translate(PopulationCode,MinX,MaxX,MumberLength);
PopulationFitness=double(subs(FunctionFitness,'x',sym(PopulationData)));

【程序说明】子程序 Transfer 把群体中的染色体的目标函数值用数值表示出来,


它 是 Fitness 的 重 要 子 程 序 . 其 有 5 个 输 入 参 数 分 别 为 PopulationCode,
FunctionFitness, MinX, MaxX,MumberLength.

附录 6:子程序 FitnessF.m
function PopulationFitnessF=FitnessF(PopulationFitness,Fmin)
Dim=size(PopulationFitness);
PopulationFitnessF=zeros(1,Dim(2));
for i=1:Dim(2)
if PopulationFitness(i)>Fmin
PopulationFitnessF(i)=PopulationFitness(i)-Fmin;
end
if PopulationFitness(i)<=Fmin
PopulationFitnessF(i)=0;
end
end

【程序说明】子程序 FitnessF.m 是用于计算每个染色体的适应函数值的.其输入


参数如下:PopulationFitness 为群体中染色体的目标函数值,Fmin 为定义适应函
数过程中给出的一个目标函数的可能的最小值.

附录 7:子程序 Probability.m
function PopulationProbability=Probability(PopulationFitness)
SumPopulationFitness=sum(PopulationFitness);
PopulationProbability=PopulationFitness/SumPopulationFitness;

【程序说明】子程序 Probability.m 用于计算群体中每个染色体的入选概率,输


入参数为群体中染色体的适应函数值 PopulationFitness.

附录 8:子程序 Select.m

152
function NewPopulation=
Select(Population,PopulationProbability,MemberNumber)
CProbability(1)=PopulationProbability(1);
for i=2:MemberNumber
CProbability(i)=CProbability(i-1)+PopulationProbability(i);
end
for i=1:MemberNumber
r=rand(1);
Index=1;
while r>CProbability(Index)
Index=Index+1;
end
NewPopulation(i,:)=Population(Index,:);
end

【程序说明】子程序 Select.m 根据入选概率(计算累计概率)在群体中按比例


选择部分染色体组成种群,该子程序的 3 个输入参数分别为:群体 Population,
入选概率 PopulationProbability,群体中染色体的个数 MemberNumber.

附录 9:子程序 Crossing.m
function NewPopulation=
Crossing(Population,FunctionFitness,MinX,MaxX,MumberLength)
%%PopulationFitness=
%% Fitness(Population,FunctionFitness,MinX,MaxX,MumberLength);
%%PopulationProbability=Probability(PopulationFitness);
%%[SortResult,SortSite]=sort(PopulationProbability);
%%Population=Population(SortSite,:);
Dim=size(Population);
if Dim(1)>=3
Temp=Population(Dim(1),:);
Population(Dim(1),:)=Population(Dim(1)-1,:);
Population(Dim(1)-1,:)=Temp;
end
for i=1:2:Dim(1)-1
SiteArray=randperm(Dim(2));
Site=SiteArray(1);
Temp=Population(i,1:Site);
Population(i,1:Site)=Population(i+1,1:Site);
Population(i+1,1:Site)=Temp;
end
NewPopulation=Population;

【程序说明】子程序 Crossing.m 用于群体中的交叉并产生新群体.其输入参数


为:Population, FunctionFitness,MinX,MaxX,MumberLength.

153
附录 10:子程序 Mutation.m
function NewPopulation=Mutation(Population,MutationProbability)
Dim=size(Population);
for i=1:Dim(1)
Probability=rand(1);
Site=randperm(Dim(2));
if Probability<MutationProbability
if Population(i,Site(1))==1
Population(i,Site(1))=0;
end
if Population(i,Site(1))==0
Population(i,Site(1))=1;
end
end
end
NewPopulation=Population;

【程序说明】子程序 Mutation.m 用于群体中少量个体变量并产生新的群体.输


入参数为:群体 Population 和变异概率 MutationProbability.

附录 11:子程序 Elitist.m
function [NewPopulationIncludeMax,CurrentBest,EachGenMaxFitness]=
Elitist(Population,PopulationFitness,MumberLength)
global Count CurrentBest;
[MinFitness,MinSite]=min(PopulationFitness);
[MaxFitness,MaxSite]=max(PopulationFitness);
EachGenMaxFitness=MaxFitness;
if Count==1
CurrentBest(1:MumberLength)=Population(MaxSite,:);
CurrentBest(MumberLength+1)=PopulationFitness(MaxSite);
else
if CurrentBest(MumberLength+1)<PopulationFitness(MaxSite);
CurrentBest(1:MumberLength)=Population(MaxSite,:);
CurrentBest(MumberLength+1)=PopulationFitness(MaxSite);
end
Population(MinSite,:)=CurrentBest(1:MumberLength);
end
NewPopulationIncludeMax=Population;

【程序说明】子程序 Elitist.m 用到最佳个体保存方法(“优胜劣汰”思想).输入


参 数 为 : 群 体 Population, 目 标 函 数 值 PopulationFitness 和 染 色 体 个 数
MumberLength.

154

You might also like