程序设计是MATLAB进行科学计算的基础。MATLAB 程序是合法的MATLAB语句的集合,MATLAB语句包括MATLAB内部的功能和用户自己编码写的命令。
在程序执行过程的任何时候按下快捷 Ctrl+C
(即同时按下Ctrl
键和C
键),就中断了MATLAB 的运算过程。
MATLAB基本数据类型包括常量、变量、数值、字符、结构体和单元数据类型。
MATLAB变量命名规则:区分大小写、最多识别到31个字符、必须以字母开始、不允许出现标点符号(很多标点符号在MATLAB中有特殊意义)、关键保留字不能作为变量名(如for、end、if等)、尽量不要与常量名重复。
恢复常量原来特定值的途径:重新启动MATLAB系统,对被覆盖的值执行clear
命令。
>> eps
ans = 2.2204e-16
>> eps = 1
eps = 1
>> eps
eps = 1
>> clear eps
>> eps
ans = 2.2204e-16
>>
MATLAB 系统对数值型数据提供以下几种基本数学运算:加法(+
)、减法(-
)、乘法(*
)、除法(/
或者\
)、乘方(^
)。
几乎在所有的情况下,MATLAB中的数值都是用双精度来表示的,这些双精度数在MATLAB系统内部是用二进制来表示的。
MATLAB也用双精度浮点数来表示整数。在这种表示方式下,所有的整数都能被精确表示。整数所能表示的上下限分别为 f l i n t m a x flintmax flintmax、 − f l i n t m a x -flintmax −flintmax。
可以在提示符下输入相应的format
命令来指定数值显示格式。
MATLAB系统不仅提供了强大的数值处理能力,还拥有丰富的字符串处理功能。一个字符串就是用单引号括起来的简单文本。
为了看见一个字符串的底层ASCII
表示,用户只需对这个字符串进行某项数学运算或者用函数double
,函数char
执行与double
相反的操作。
>> s = 'Hello, world!'
s = Hello, world!
>> asi = double(s)
asi =
72 101 108 108 111 44 32 119 111 114 108 100 33
>> char(asi)
ans = Hello, world!
>>
MATLAB语言也提供了丰富的字符串处理函数,函数disp
允许显示一个字符串而不用输出这个字符串变量的变量名。
在很多情况下,需要把一个数值型结果转换成一个字符串,或者把一个字符串转换成数值型数据。MATLAB提供了函数int2str
、num2str
、mat2str
、sprintf
、fprintf
,可把数值型结果转换成字符串。
MATLAB把所有的非 0 0 0 数值当作true
,而把 0 0 0 当作false
。所有关系和逻辑表达式,如果是真,就返回逻辑数组 1 1 1;如果为假,就返回逻辑数组 0 0 0。
在MATLAB中,算术运算符的优先级最高,关系运算符优先级次之,逻辑运算符优先级最低。
通常,对于带有时间的数字都涉及将时间转换成日期数字格式,对时间执行标准数学运算,然后将结果数字再转换成简明的日期格式。
单元数组是以元素为单元的MATLAB数组,在单元数组的每个单元都可以包含任何的MATLAB数据类型,包括数值型数据、字符串、其他单元数组及结构。
MATLAB为定义结构体变量提供了函数struct
,其调用格式如下:
结构体变量名=struct(属性名1,属性值1,属性名2,属性值2,……)
使用该函数可以定义结构体变量的各个属性,并相应地赋以属性值。
数组与矩阵是MATLAB语言的核心,MATLAB中几乎一切运算都是以对数组和矩阵的操作作为基础的。
标量与数组的运算是将数组中的每一个元素与标量进行相应的运算,标量与数组的运算遵循与标量表达式中相同的计算优先级运算的先后顺序。只有当两个数组的维数相同时,才能在数组元素对元素之间进行加、减、乘、除运算。
./
和.\
都是用斜线斜上方的数组去除以斜线斜下方的数组;.^
可以进行数组元素之间的指数运算;数组的模可以通过norm(x)
函数求解;维数相同的数组的点积运算可以通过 d o t ( x , y ) dot(x,y) dot(x,y) 求得,等价于 s u m ( x . ∗ y ) sum(x.^*y) sum(x.∗y);数组的叉积运算要求参与运算的数组必须是维数为 3 3 3 的,叉积运算可以通过 c r o s s ( x , y ) cross(x,y) cross(x,y) 函数来求得。
zero/ones
函数clear
clc
%测试 zeros、ones
A=zeros(3,4);
B=ones(3,4);
size/length
函数clear
clc
%测试 zeros、ones、size、length
A=zeros(3,4);
B=ones(3,4);
[C,D]=size(A);
E=[5 3 2 4];
F=length(E);
max/min
函数clear
clc
%测试 max、min、isempty
E=[5 3 2 4];
[maxValue,maxIndex]=max(E);
[minValue,minIndex]=min(E);
isempty
函数clear
clc
%测试 isempty
X=[1,2;3,4];
Y=isempty(X);
unique
函数clear
clc
%测试unique
A=[9 9 8 7 6 7 6 8 1 1 0];
[B,C]=unique(A);
cell
函数clear
clc
%测试cell
A1=[1,2,3];
A2=[4,5,6,7];
A3=[8,9,10,11,12];
A=cell(3,1);
A{1,1}=A1;
A{2,1}=A2;
A{3,1}=A3;
矩阵是一类特殊的数组。矩阵与标量的运算是要完成矩阵的每一个元素与该标量的运算。矩阵的乘方要求矩阵为方阵。矩阵与矩阵之间的加减法运算要求参与运算的矩阵的维数完全相同,这些运算完成对参与运算的矩阵的相应元素相加减。
两个矩阵的乘法要求它们的维数相容,也就是说,第一个矩阵的列数等于第二个矩阵的行数,只有这样才能进行乘法运算。此外,MATLAB还有kronecker
乘法运算,有kron()
完成。
矩阵的除法运算有左除和右除两种,左除 A A A \ B B B= A − 1 B A^{-1}B A−1B, A A A 为方阵且可逆;右除 A / B = A B − 1 A/B=AB^{-1} A/B=AB−1, B B B为方阵且可逆。
矩阵运算的点运算与数组的点运算是一样的,即两个矩阵之间的点运算就是这两个矩阵对应元素的直接运算,可以看出矩阵之间的点运算要求这两个矩阵的维数完全相同。
MATLAB系统提供了许多特殊矩阵,它们有些有着广泛的用途,有些在数学上有特殊的性质,在数据初始化过程中应用广泛。
一般来说,当矩阵维数比较大而矩阵元素中非零元素很少时,就应该采用稀疏矩阵。
稀疏矩阵的存储需要使用三个一维数组,第一个数组用于存储非零元素的值,第二个数组用于存储非零元素在矩阵中的行下标,第三个数组则用于存储稀疏矩阵中每一列的第一个非零元素在第一个数组中的偏移量,而对于复数元素的稀疏矩阵,则还需要一个数组用来存储非零元素的虚部。
稀疏矩阵的存储方式决定了对满矩阵采用稀疏矩阵的方式存储会占据更多的空间。
稀疏矩阵是使用函数sparse
来创建的,函数sparse(A)
用来将一个普通的完全矩阵转换成稀疏矩阵,函数full
可以将该稀疏矩阵转换成普通的完全矩阵。
MATLAB提供了 5 5 5 种流程控制结构:for
循环结构、while
循环结构、if-else-end
结构、switch-case
结构、try-catch
模块。
for
循环语句for
循环的总体结构如下:
for 循环控制变量=array
commands
end
示例如下:
clear
clc
% 求1到10的和
T=0;
for i=1:10
T=T+i;
end
while
循环语句while
循环总体结构如下:
while 循环判断语句
commands
end
在while
与end
之间的commands
,只要循环判断语句为true
,就会一直被执行;当循环判断语句为false
,就会退出循环体。示例如下:
clear
clc
% 求1到10的和
T=0;
i=1;
while i<=10
T=T+i;
i=i+1;
end
if-else-end
语句if-else-end
总体结构如下所示:
if 逻辑判断语句1
commands1
elseif 逻辑判断语句2
commands2
elseif 逻辑判断语句3
commands3
.
.
.
else
commands
end
示例如下:
clear
clc
%已知A,求B
A=6;
if A>5
B=1;
elseif A>0
B=2;
else
B=3;
end
switch-case
语句switch-case
总体结构如下所示:
switch 选择判断量
case 选择判断值1
commands1
case 选择判断值2
commands2
.
.
.
otherwise
commands
end
与其他程序设计语言的switch-case
语句不同的是,当其中一个case
语句后面的条件为true
时,switch-case
语句就不会对其后的case
语句进行判断。即便有多条case
判断语句为真,也只执行所遇到的第一条为真的语句。
try-catch
语句try-catch
模块提供了用户控制的错误捕获机制。try-catch
模块的一般表达形式如下:
try
commands1
catch
commands2
end
在这些语句中,commands1
中的语句都要被执行,如果没有出现错误,程序就直接跳到end
语句。但是,如果在执行commands1
的语句时出现错误了,程序就立刻转到catch
语句,然后执行表达式commands2
。
MATLAB提供的M文件有两类:脚本文件和函数文件。脚本文件没有输入/输出变量,函数文件是在同功能的脚本文件的基础上在文件代码的开始处多添加一行函数声明。
函数是MATLAB的基本功能,他们使得用户可以对一组有用的命令进行封装,然后可以一次次地调用。如果不想单独编写M文件来定义函数,可以定义一个直接插入的函数(MATLAB提供了函数inline
来实现这个功能)。
feval
函数函数feval
可以将一个函数的字符串名传递给一个函数进行计算。feval
一般语法如下所示:
[y1,y2,...] = feval(function,x1,x2,...,xn) % function 是一个函数的字符串名,该函数由M函数定义,x1,x2,...xn 是函数名为 function 的M函数的参数列表,不是字符型的。
[y1,y2,...] = feval(fhandle,x1,x2,...,xn) % fhandle 是一个函数句柄,x1,x2,...xn 是函数名为 function 的M函数的参数列表,不是字符型的。
当在一个函数的名字字符串已知的情况下,函数str2func
可以用来创建函数句柄;而函数func2str
执行相反的工作,是将函数句柄转换成字符串。
函数句柄可以被函数feval
调用,但不能被函数eval
调用,前面介绍的直接插入函数命令inline
创建的函数可以被函数feval
调用。
另外,MATLAB
也提供了函数isa
来判断变量是否为函数句柄,函数isequal
可以判断两函数句柄是否相同。与其他数据数型相同,使用函数save
也可以将函数句柄保存为MATLAB 数据文件,而使用函数load
则同样可以打开该数据文件。
在MATLAB表达式中可能存在两种错误:语法错误(是 MATLAB 运行一个表达式或者一个函数时被编译进入内存时发现的)和运行错误(体现在执行结果不对,运行中出现异常)。
对于简单的问题,可以采用下述方法进行排查:
(1)将函数中被选定的行的分号去掉,这样运算的中间结果就能在命令窗口中输出来,从中可以发现这些问题。
(2)在程序中的适当位置添加一些语句,用来显示要查看的重要变量的值。
(3)在 M 文件中选定的位置添加keyboard 语句,以便将临时控制权交给键盘,等待用户输入。
(4)可以通过在M
文件开头函数的定义语句之前添加注释号%
把函数变成一个脚本M
文件,这样在出现错误的时候就可以查询这个工作区。
(5)如果考虑的问题比较复杂,则可以用MATLAB 的Debug
调试工具,使用help
函数查看Debug
调试工具的命令。
MATLAB 语言是一种解释型语言,其执行速度不是很理想。为了提高执行速度,根据经验我们给出一些小技巧:
(1)尽量避免使用循环(如for
循环和while
循环),而选择使用矢量化。
(2)在必须使用循环的情况下,应该在外面的循环执行循环次数少的,而在里面的循环执行循环次数多的,这样也可以显著提高速度。
(3)在定义大型矩阵时,建议用MATLAB的内部函数如zeros()
或ones()
预先确定维数,然后再进行其他操作。
(4)采用有效的算法可以提高程序的运行速度。
(5)考虑用其他语言,如C
或FORTRAN
语言。按照Mex
技术要求的格式编写相应部分的程序,然后编译连接,这样可以显著地加快运算速度。
MATLAB从入门到实践(第2版)