目录
一、基本概念
1. 常量、变量和标量
(1)常量
常量是程序语句中值不会改变的那些量。如,表达式 y=3.1415*x 中的系数3.1415 就是一个数值常量;表达式:s='Name and Tel' 中单引号内的英文字符串是一个字符串常量。在MATALB中,系统会默认给定一个符号来表示某些特定常量,如pi表示圆周率π,这些常量也被称为系统预定义的变量。
名称 | 含义 | 名称 | 含义 |
---|---|---|---|
ans | MATLAB中默认的结果变量 | nargin | 所用函数的输入参数个数 |
pi | 圆周率 π 的双精度表示 | nargout | 所用函数的输出参数个数 |
Inf | 无穷大,由 0 作为除数引入此量 | realmin | 最小可用正实数, |
NaN | 不定值,表示非数值量,产生于0/0、∞/∞、0*∞等运算 | realmax | 最大可用正实数, |
i、j | 复数中的虚数单位 | eps | 容差变量,浮点数的最小分辨率, |
(2)变量
在程序运行过程中,其值可以改变的量称为变量,变量用变量名表示。
1) 变量的命名规则
① 变量名必须以字母开头,且只能由字母、数字或下画线3类符号组成,不能包含空格和标点符号等。
② 变量名区分字母的大小写,如 a 和 A 代表不同的变量。
③ 变量名不能超过63个字符,第63个字符后的字符会被忽略。
④ 关键字(如 if、while等)不能作为变量名;不要使用特殊常量符号作为变量名。
⑤ 常见的错误命名有%x、f(x+y)、y'、y"、A²、A(x)、while 等。
2) 变量的声明与删除
① 变量的声明:在matlab中没有变量声明语句,当使用一个变量的时候,matlab会搜索这个变量名字,当没有这个名字的时候,默认自动生成。
② 变量的删除:使用 clear 函数可以进行变量的删除。
clear x % x为变量名,将变量x进行删除
clear % 如果直接使用clear函数,后面不添加变量名,会将全部变量删除
(3)标量
在MATLAB中,标量被视为矩阵的一种。当矩阵的行数和列数都为1时,我们称之为标量。标量可以被视为特殊的1x1矩阵或1x1向量。
2. 向量、矩阵和数组
(1)向量
向量是一个数学量,在 MATLAB 中,可视其为矩阵的特例,即仅有一行或一列的矩阵。一个n维的行向量是一个 1×n 阶的矩阵,一个n维的列向量是一个 n×1 阶矩阵。
(2)矩阵
矩阵是一个数学概念, MATLAB 将矩阵引入基本运算量后,不但实现了矩阵的简单加减乘除运算,而且许多与矩阵相关的其他运算也大大简化了。在线性代数中,矩阵是一个由数字按照一定的排列规则组成的矩形阵列。m×n阶矩阵就是一个由m行和n列元素组成的矩形阵列。当m=n时,我们称之为n阶方阵。
(3)数组
数组是一个用于高级语言程序设计的概念,不是一个数学量。如果数组元素按一维线性方式组织在一起,那么称其为一维数组,一维数组的数学原型是向量。如果数组元素分行、列排成一个二维平面表格,那么称其为二维数组,二维数组的数学原型是矩阵。
如果元素在排成二维数组的基础上,将多个行数和列数分别相同的二维数组叠成一个立体表格,便形成三维数组。依次类推,便有了多维数组的概念。
注意:数组的维和向量的维是两个完全不同的概念。数组的维是根据数组元素排列后形成的空间结构去定义的:线性结构是一维,平面结构是二维,立体结构是三维,还有四维和多维。向量的维相当于一维数组中的元素个数。
二、向量
1. 向量的创建
(1)直接输入法
向量名 = [a1,a2,a3,...] % 采用逗号符创建行向量
向量名 = [a1 a2 a3 ...] % 采用空格符创建行向量
向量名 = [a1;a2;a3;...] % 采用分号符创建列向量
% 直接输入法创建向量
>> a=[2,3,4,5]
a =
2 3 4 5
>> b=[1 2 3 4]
b =
1 2 3 4
>> c=[3;4;5;6]
c =
3
4
5
6
(2)冒号表达式法
向量名 = a1 : step : an % a1是向量的第一个元素,an是向量的最后一个元素的限定值;step是变化步长,可以是正数、负数或小数,省略时系统默认步长为1。MATLAB支持构造任意步长的向量,步长甚至可以是负数。
% 冒号表达式法创建向量
>> a=1:2:10
a =
1 3 5 7 9
>> b=-2.5:2.5
b =
-2.5000 -1.5000 -0.5000 0.5000 1.5000 2.5000
>> c=2:-0.5:-1
c =
2.0000 1.5000 1.0000 0.5000 0 -0.5000 -1.0000
(3)函数法
MATLAB提供了两个函数用于直接创建向量:一个是实现线性等分的函数 linspace ;另一个是实现对数等分的函数 logspace。
A = linspace(a1,an,n) % 用于生成一个在指定范围内的等间距的向量。a1是向量的首元素,an是向量的尾元素,n表示向量中元素的个数。若省略n,则默认创建含有100个元素的线性等分向量。
A = logspace(a1,an,n) % 用于生成一个在指定范围内以10为底数的等比数列。a1是向量首元素的幂,即 A(1) 为10的a1次幂;an是向量尾元素的幂,即A(n)为10的an次幂,n是向量的维数。若省略n,则默认创建含有50个元素的对数等分向量。
% 利用线性等分函数和对数等分函数创建向量
>> a=linspace(1,10); % 创建1~10的100个元素,采用“;”结尾,不显示结果
>> b=linspace(1,5,6) % 创建1~5的6个线性等分元素
b =
1.0000 1.8000 2.6000 3.4000 4.2000 5.0000
>> c=logspace(0,4); % 创建1~10000的50个元素,采用“;”结尾,不显示结果
>> d=logspace(0,4,5) % 创建1~10000的5个对数等分元素
d =
1 10 100 1000 10000
注意:
① 在冒号表达式法中, an不一定恰好是向量的最后一个元素,只有当向量的倒数第二个元素加步长等于an时, an才正好构成尾元素。
② 在使用线性等分函数前,必须先确定创建向量的元素个数,但使用冒号表达式法将依据步长和an的限制去创建向量,无须考虑元素个数的多少。
③ 实际应用时,同时限定尾元素和步长去创建向量,可能会出现矛盾,此时要么坚持步长优先,调整尾元素限制;要么坚持尾元素限制,调整等分步长。
2. 向量的算数运算
在MATLAB中,维数(元素个数)相同的行向量可以相加减,维数相同的列向量也可以相加减,不同维数的向量之间不允许进行加减运算;标量数值可以与向量直接相乘除。
% 向量的加减和数乘、数除运算
>> a=[2 4 6 8]; % 直接输入法创建行向量a
>> b=3:2:9; % 冒号表达式法创建行向量b
>> a1=a'; % “'”表示转置,即行向量变为列向量,列向量变为行向量
>> b1=b';
>> e1=a+b % 求和
e1 =
5 9 13 17
>> e2=a-b % 求差
e2 =
-1 -1 -1 -1
>> e3=a1+b1
e3 =
5
9
13
17
>> g1=4*a % 相乘
g1 =
8 16 24 32
>> g2=b/4 % 相除
g2 =
0.7500 1.2500 1.7500 2.2500
3. 向量的点积与叉积运算
(1)点积运算——数量积
点积运算的定义是将参与运算的两向量各“对应位置”上的元素相乘,再将各乘积相加。因此,向量点积的结果是一标量而非向量。
① 对于长度为n的两个实数向量的点积为:
② 对于复数向量,点积涉及复共轭。为确保向量与自身的内积都为实数正定矩阵,需对其中一个向量的每个元素都取其共轭:
点积运算函数 dot() 调用格式为:
C = dot(A,B) % 返回A和B的标量点积
C = dot(A,B,dim) % 计算A和B沿维度dim的点积, dim的输入是一个正整数标量
说明:如果A和B是向量,则它们的维数必须相同;如果A和B为矩阵或多维数组,则它们必须具有相同大小。对于实数向量,dot(u,v)=dot(v,u);对于复数向量,复数关系不可互换,dot(u,v)=conj(dot(v,u))。
(2)叉积运算——向量积
两个三维向量 A、B 之间的叉积生成一个与这两个向量都垂直的新向量C, 即C的方向垂直于A与B决定的平面。用三维坐标表示为:
叉积运算的函数是 cross(A,B),该函数计算的是A、B叉积后各分量的元素值,且A、B只能是三维向量。
叉积运算函数 cross() 调用格式为:
C = cross(A,B) % 返回A和B的向量叉积
C = cross(A,B,dim) % 计算A和B沿维度dim的叉积, dim输入是一个正整数标量
说明: 如果A和B为向量,则它们的长度必须为 3;如果A和B为矩阵或多维数组,则它们必须具有相同大小,此时cross函数将A和B视为三元素向量集合,计算对应向量沿大小等于3的第一个数组维度的叉积。
(3)混合积运算
在三维向量之间,综合运用上述两个函数,可实现点积和叉积的混合运算。
D = dot(C,cross(A,B)) % 正确的混合积运算形式,叉积的结果是向量,满足最后点积运算的要求
E = cross(C,dot(A,B)) % 错误的混合积运算形式,点积的结果是标量,不满足最后叉积运算的要求
% 向量的点积与叉积运算
>> A=[2 4 6 8]; B=3:6; AT=A'; BT=B';
>> e=dot(A,B) % 点积运算
e =
100
>> f=dot(AT,BT) % 点积运算
f =
100
>> A=3:5; B=2:4; C=[3 2 1];
>> E=cross(A,B) % 叉积运算
E =
1 -2 1
>> D=dot(C,cross(A,B)) % 混合积运算
D =
0
>> E=cross(C,dot(A,B)) % 错误混合积运算
错误使用 cross
在获取交叉乘积的维度中,A 和 B 的长度必须为 3。
三、矩阵
1. 矩阵的构造
(1)简单矩阵的构造
使用矩阵构造符“[ ]”是最简单的构造矩阵的方法。构造一行的矩阵,可以把矩阵元素放在矩阵构造符中,并以空格或逗号隔开,一行的矩阵即行向量,一列的矩阵即列向量,其格式是:
row = [a1,a2,...,an] % 采用逗号符构造单行矩阵
row = [a1 a2 ... an] % 采用空格符构造单行矩阵
A = [row1;row2;...;rown] % 利用分号符构造多行矩阵,行与行之间用分号隔开
% 4×4矩阵的创建
>> a=[1,2,3,4;5,6,7,8;9,10,11,12;13,14,15,16]
a =
1 2 3 4
5 6 7 8
9 10 11 12
13 14 15 16
>> whos a
Name Size Bytes Class Attributes
a 4x4 128 double
(2)特殊矩阵的构造
见附录!!!
% 利用特殊矩阵函数创建特殊矩阵
>> a=ones(2,3) % 创建一个2×3的全1矩阵
a =
1 1 1
1 1 1
>> b=eye(3) % 创建一个3×3的单位矩阵
b =
1 0 0
0 1 0
0 0 1
>> c=magic(3) % 创建一个3×3的魔方矩阵
c =
8 1 6
3 5 7
4 9 2
>> rand(4) % 创建一个4×4的随机数矩阵
ans =
0.8147 0.6324 0.9575 0.9572
0.9058 0.0975 0.9649 0.4854
0.1270 0.2785 0.1576 0.8003
0.9134 0.5469 0.9706 0.1419
例题:(矩阵的简单应用)
计算与多项式 对应的伴随矩阵。
>> a=[1 0 -7 6]; % 多项式的系数
>> x=compan(a) % 多项式对应的伴随矩阵
x =
0 7 -6
1 0 0
0 1 0
>> y=eig(x) % x的特征值是多项式的根
y =
-3.0000
2.0000
1.0000
[V, D] = eig(A) % A是一个方阵,V是对应的特征向量组成的矩阵,D是对角线上的元素,即特征值。如果矩阵 A 不是方阵,则 eig(A) 会报错。
>> A = [1 2 3; 4 5 6; 7 8 9];
[V,D] = eig(A)
V =
-0.2320 -0.7858 0.4082
-0.5253 -0.0868 -0.8165
-0.8187 0.6123 0.4082
D =
16.1168 0 0
0 -1.1168 0
0 0 -0.0000
>> x=eig(A)
x =
16.1168
-1.1168
-0.0000
2. 矩阵拓展与裁剪
矩阵的拓展指的是改变矩阵的现有大小,增加新的元素,使矩阵的行数或列数增加;矩阵的裁剪指的是从现有矩阵中抽取部分元素,组成一个新的矩阵。
(1)矩阵合并
1)构造符合并
矩阵的合并就是把两个或两个以上的矩阵数据连接起来得到一个新的矩阵。水平合并,需保证两矩阵行数相同;竖直合并,需保持两矩阵列数相同。前面介绍的矩阵构造符不仅可用于构造矩阵,还可作为一个矩阵合并操作符。表达式如下:
C = [A B] % 表示在水平方向上合并矩阵A和B
C = [A , B] % 表示在水平方向上合并矩阵A和B
C = [A ; B] % 表示在数值方向上合并矩阵A和B
% 矩阵的合并
>> a=eye(2,4); % 创建一个2×4单位矩阵
>> b=ones(2,4); % 创建一个2×4全1矩阵
>> c=[a;b] % 竖直合并
c =
1 0 0 0
0 1 0 0
1 1 1 1
1 1 1 1
>> d=[a b] % 水平合并
d =
1 0 0 0 1 1 1 1
0 1 0 0 1 1 1 1
2)合并函数合并
% 利用矩阵合并函数合并矩阵
>> a=ones(3); % 创建一个3×3全1矩阵
>> b=eye(2); % 创建一个2×2列单位矩阵
>> c=blkdiag(a,b) % 合并构造对角化矩阵
c =
1 1 1 0 0
1 1 1 0 0
1 1 1 0 0
0 0 0 1 0
0 0 0 0 1
(2)赋值拓展
赋值拓展是对原矩阵的修改。对于一个m×n的矩阵,通过使用超出目前矩阵(数组)大小的索引数字,并对该位置元素进行赋值来完成矩阵的拓展。对于未指定的新位置,默认赋值为0。
>> a=magic(3); % 创建一个3×3魔方矩阵
>> a(4,5)=12 % 通过赋值将矩阵拓展为4×5矩阵,4行5列元素为12,其余默认为0
a =
8 1 6 0 0
3 5 7 0 0
4 9 2 0 0
0 0 0 0 12
>> a(:,4)=16 % 将第4列所有元素均赋值为16
a =
8 1 6 16 0
3 5 7 16 0
4 9 2 16 0
0 0 0 16 12
>> b=a(:,[1:5,1:5]) % 取a的全部行及1~5列、取a的全部行及1~5列、进行矩阵合并
b =
8 1 6 16 0 8 1 6 16 0
3 5 7 16 0 3 5 7 16 0
4 9 2 16 0 4 9 2 16 0
0 0 0 16 12 0 0 0 16 12
>> b=a(:,[1:4,1:5]) % 取a的全部行及1~4列、取a的全部行及1~5列、进行矩阵合并
b =
8 1 6 16 8 1 6 16 0
3 5 7 16 3 5 7 16 0
4 9 2 16 4 9 2 16 0
0 0 0 16 0 0 0 16 12
(3)矩阵行/列的删除
矩阵行/列的删除是对原矩阵的修改。要删除矩阵的某一行或某一列,只要给该行或该列赋予一个空矩阵即可。当某一索引位置上不是数字而是冒号时,表示提取该索引位置上的所有元素。
% 创建一个魔方矩阵,然后删除矩阵的第3行
>> a=magic(3) % 创建一个3×3魔方矩阵
a =
8 1 6
3 5 7
4 9 2
>> whos a
Name Size Bytes Class Attributes
a 3x3 72 double
>> a(3,:)=[] % 将矩阵第3行的所有元素设为空即可删除该行
a =
8 1 6
3 5 7
>> whos a
Name Size Bytes Class Attributes
a 2x3 48 double
(4)矩阵的提取
通过提取现有矩阵的元素可以创建新的矩阵,矩阵的提取不改变原矩阵,提取格式如下:
B = A([ x1,x2,x3,... ] , [ y1,y2,y3,... ]) % 提取矩阵A中第x1、x2、x3、...行,第y1、y2、y3、...列元素,组成新的矩阵B。
>> a=magic(5) % 创建一个5×5魔方矩阵A
a =
17 24 1 8 15
23 5 7 14 16
4 6 13 20 22
10 12 19 21 3
11 18 25 2 9
>> b=a(2,:) % 提取第2行所有元素,不改变原矩阵
b =
23 5 7 14 16
>> c=a(1:2:5,2:2:5) % 提取第1、3、5行中的第2、4个元素
c =
24 8
6 20
18 2
>> d=a(1:2:5,:) % 提取第1、3、5行中的所有元素
d =
17 24 1 8 15
4 6 13 20 22
11 18 25 2 9
>> e=a([1,4],[2,2,5]) % 提取第1、4行中的第2、2、5个元素
e =
24 24 15
12 12 3
>> f=a([1,2,5],:) % 提取第1、2、5行中的所有元素
f =
17 24 1 8 15
23 5 7 14 16
11 18 25 2 9
>> a([1,2,5],:)=[] % 删除第1、2、5行中的所有元素,创建新的矩阵A
a =
4 6 13 20 22
10 12 19 21 3
3. 矩阵下标引用
(1)矩阵下标访问单个矩阵元素(全下标寻址)
若A是一个二维矩阵,则可以通过A( i , j )表示矩阵A的第 i 行第 j 列元素,同时还可以通过对A( i , j )进行赋值来改变对应位置元素的值。
% 创建一个4阶魔方矩阵,查找第2行第4列的数字,并改变该值为0
>> a=magic(4) % 创建一个4×4的魔方矩阵
a =
16 2 3 13
5 11 10 8
9 7 6 12
4 14 15 1
>> b=a(2,4)
b =
8
>> a(2,4)=0 % 通过赋值的方式改变某一元素的数值
a =
16 2 3 13
5 11 10 0
9 7 6 12
4 14 15 1
(2)线性引用矩阵元素(单下标寻址)
在 MATLAB中,还可以通过单下标来引用矩阵元素,引用格式为A(k)。通常, 这样的引用适用于行向量或列向量,但有时也适用于二维矩阵。
MATLAB在存储矩阵元素时,并不是按照其命令行输出矩阵的格式来进行的。实际上,矩阵可以看成是按列优先排列的一个长列向量格式来存储的。对于一个 m 行 n 列的矩阵,若第 i 行第 j 列的元素 A( i , j )用A(k)表示,则k=(j−1)×m+i。
>> a=[1 2 3;4 5 6;7 8 9]
a =
1 2 3
4 5 6
7 8 9
>> b=a(4)
b =
2
上面的矩阵a实际上在内存中是被存储成以1、4、7、2、5、8、3、6、9排列的一个列向量。矩阵a的第1行第2列,即值为2的元素实际上在存储空间中是第4个元素。要访问2这个元素,可以用a(1,2)格式,也可以用a(4)格式,a(4)就是线性引用矩阵元素的方法。
(3)引用矩阵元素方式转换
如果已知矩阵的下标,却想用线性引用矩阵元素方式访问矩阵,可使用sub2ind函数。反之,如果想从线性引用的下标得到矩阵的下标,就可以用函数 ind2sub。
ind = sub2ind( sz , row , col ) % 针对大小为sz的矩阵返回由row和col指定的行列下标的对应线性索引 ind。row和col的格式可以是一个标数,也可以是维数相同的向量。sz的格式是包含两个元素的向量,即[m , n],表示一个 m 行 n 列的矩阵。
[ row , col ] = ind2sub( sz , ind ) % 返回数组 row和col,其中包含与大小为sz的矩阵的线性索引ind对应的等效行和列下标
>> row=[1 2 3 1]; % 行下标构成的向量
>> col=[2 2 2 3]; % 列下标构成的向量
>> sz=[3 3];
>> ind=sub2ind(sz,row,col) % 将全下标(1,2)(2,2)(3,2)(1,3)转换为线性索引(4)(5)(6)(7)
ind =
4 5 6 7
>> ind=[3 4 5 6];
>> sz=[3 3];
>> [row,col]=ind2sub(sz,ind) % 将线性索引(3)(4)(5)(6)转换为全下标(3,1)(1,2)(2,2)(3,2)
row =
3 1 2 3
col =
1 2 2 2
>> a=[1 2 3 4 5;6 7 8 9 10;11 12 13 14 15;16 17 18 19 20;21 22 23 24 25]
a =
1 2 3 4 5
6 7 8 9 10
11 12 13 14 15
16 17 18 19 20
21 22 23 24 25
>> row=2;
>> col=3;
>> ind=sub2ind(size(a),row,col) % 对于已经给出的矩阵,可以直接通过size函数求解其大小
ind =
12
>> a(12)
ans =
8
4. 矩阵信息的获取
(1)矩阵尺寸信息
>> a=rand(3,4) % 创建一个3×4随机矩阵
a =
0.8147 0.9134 0.2785 0.9649
0.9058 0.6324 0.5469 0.1576
0.1270 0.0975 0.9575 0.9706
>> n1=length(a) % 求矩阵a的最长方向长度
n1 =
4
>> n2=ndims(a) % 求矩阵a的维数,准确来说ndims函数是用来求解数组的维数的
n2 =
2
>> n3=numel(a) % 求矩阵中元素的个数
n3 =
12
>> n4=size(a) % 求矩阵各个方向的长度
n4 =
3 4
(2)矩阵元素的数据类型和结构信息
1)判断矩阵中元素的数据类型的函数
2)测试矩阵类型的函数
函数名 | 函数描述 | 基本调用格式 |
isempty | 测试矩阵是否为空矩阵 | tf = isempty(a) |
isscalar | 测试矩阵是否为标量 | tf = isscalar(a) |
issparse | 测试矩阵是否为稀疏矩阵 | tf = issparse(a) |
isvector | 测试矩阵是否为矢量 | tf = isvector(a) |
5. 矩阵结构的改变
>> a=rand(3) % 随机生成一个3×3的0~1均匀分布矩阵
a =
0.9572 0.1419 0.7922
0.4854 0.4218 0.9595
0.8003 0.9157 0.6557
>> b=flipud(a) % 以水平方向为轴做镜像
b =
0.8003 0.9157 0.6557
0.4854 0.4218 0.9595
0.9572 0.1419 0.7922
>> c=fliplr(a) % 以竖直方向为轴做镜像
c =
0.7922 0.1419 0.9572
0.9595 0.4218 0.4854
0.6557 0.9157 0.8003
>> d=transpose(a) % 以对角线为轴做镜像
d =
0.9572 0.4854 0.8003
0.1419 0.4218 0.9157
0.7922 0.9595 0.6557
四、稀疏矩阵
1. 稀疏矩阵相关概念
在很多情况下,一个矩阵只有少数的元素是非零的,对于零值和非零值, 均需要花费同样的空间来存储的矩阵称为满矩阵。这种存储方式会浪费很多存储空间,有时还会减慢计算速度。
稀疏矩阵是一种针对矩阵元素大多数都是零值的存储方式,由非零元素及其行列索引数组来进行表示。稀疏矩阵不能自动生成,不论有多少个元素为零,定义在满矩阵上的运算只能生成满矩阵。但是,一旦以稀疏矩阵来存储,稀疏矩阵的存储方式就会传播下去。也就是说,定义在稀疏矩阵上的运算生成稀疏矩阵,定义在满矩阵上的运算生成满矩阵。
在使用稀疏矩阵前,需要确定矩阵中是否包含足够高百分比的零元素,只有数据量极大且密度非常低的矩阵适用稀疏矩阵。矩阵的密度是指非零元素数目除以矩阵元素总数,可以通过下面的方法确定矩阵的密度:
nnz(a) / prod(size(a)) % nnz 函数用于计算矩阵中非零元素的数量,size 函数得到矩阵的行数和列数,在通过prod函数进行行数和列数相乘,得到矩阵中总元素个数
nnz(a) / numel(a) % numel 函数用于计算矩阵或数组中元素的个数
2. 满矩阵和稀疏矩阵的转换
MATLAB提供了 sparse 函数,可以将满矩阵转换为稀疏矩阵,其调用格式如下:
a = sparse(x) % 将满矩阵a转换为稀疏矩阵b
a = sparse(m , n) % 生成m×n的全零稀疏矩阵
a = sparse(i , j , k) % 设置稀疏矩阵中的第 i 行第 j 列为非零元素 k
a = sparse(i , j , k , m , n) % 将稀疏矩阵a的大小设置为m×n
同时,MATLAB 还提供了 full 函数,可以将稀疏矩阵转换为满矩阵,其调用格式如下:
a = full(x) % 将稀疏矩阵x转换为满存储矩阵a
>> a=[0 0 5 0;8 0 0 0;0 1 0 0;0 0 0 7]
a =
0 0 5 0
8 0 0 0
0 1 0 0
0 0 0 7
>> nnz(a)/prod(size(a)) % 查看矩阵密度
ans =
0.2500
>> b=sparse(a) % 稀疏矩阵存储
b =
(2,1) 8
(3,2) 1
(1,3) 5
(4,4) 7
>> c=full(b) % 满矩阵存储
c =
0 0 5 0
8 0 0 0
0 1 0 0
0 0 0 7
>> d=sparse(3,4)
d =
全零稀疏矩阵: 3×4
>> e=sparse(1,2,3)
e =
(1,2) 3
>> f=sparse(1,2,3,4,5)
f =
(1,2) 3
>> size(f)
ans =
4 5
3. 基于对角线元素创建稀疏矩阵
基于稀疏矩阵的对角线元素创建稀疏矩阵是一种常见操作,在MATLAB中可通过函数 spdiags 实现该功能,其调用格式如下:
a = spdiags(B , d , m , n) % 创建大小为 m×n 且元素在 p 对角线上的输出矩阵a。其中,d 代表稀疏矩阵a的对角线编号,主对角线作为0对角线,主对角线下面为负对角线,上面为正对角线,数据之间用分号隔开;p 代表稀疏矩阵a的非零对角线的数目,其与向量 d 的维数相同;B 是大小为 min(m,n)×p 的矩阵,将 B 的每一列元素用来填充稀疏矩阵a对角线上的值;如果 B 的列长度超过了将要填充的的对角线长度,则上对角线从 B 列的下部开始获取,下对角线从 B 列的上部开始获取。
>> B=[41 11 0;52 22 0;63 33 13;74 44 24];
>> d=[-3;0;2];
>> a=spdiags(B,d,7,4) % 创建7×4稀疏矩阵a
a =
(1,1) 11
(4,1) 41
(2,2) 22
(5,2) 52
(1,3) 13
(3,3) 33
(6,3) 63
(2,4) 24
(4,4) 44
(7,4) 74
>> full(a)
ans =
11 0 13 0
0 22 0 24
0 0 33 0
41 0 0 44
0 52 0 0
0 0 63 0
0 0 0 74
矩阵B:
41 11 0
52 22 0
63 33 13
74 44 24
稀疏矩阵a的大小为7行4列,min(7,4)=4;
p的大小为3,与向量d的维数相同;
矩阵B满足min(m,n)×p即4行3列;
稀疏矩阵a的-3对角线上的元素“从上到下”依次是 B 的第一列元素:41 52 63 74,稀疏矩阵a的0对角线上的元素“从上到下”依次是 B 的第二列元素:11 22 33 44,由于稀疏序列a的2对角线只有两个元素,2对角线为上对角线,所以元素从 B 的第三列的下部开始取。
a相当于下面的矩阵:(空的地方用00进行表示)
11 00 13 00
00 22 00 24
00 00 33 00
41 00 00 44
00 52 00 00
00 00 63 00
00 00 00 74
4. 特殊稀疏矩阵的创建
5. 稀疏矩阵非零值信息的查看
>> a=sprand(3,4,0.3) % 创建随机数的稀疏矩阵
a =
(3,2) 0.7060
(3,3) 0.0318
(1,4) 0.1712
>> b=full(a) % 满矩阵存储形式
b =
0 0 0 0.1712
0 0 0 0
0 0.7060 0.0318 0
>> c=nonzeros(b) % 返回非零值
c =
0.7060
0.0318
0.1712
6. 稀疏矩阵的运算规则
MATLAB系统中的各种命令都可以用于稀疏矩阵的运算。当有稀疏矩阵参加运算时,得到的结果将遵循以下规则。
① 把矩阵转换为标量或定长向量的函数总是给出满矩阵。把标量或定长向量转换为矩阵的函数(如zeros、ones、eye、rand等)总是给出满矩阵;而能给出稀疏矩阵结果的相应函数有 speye 和 sprand等。
② 从矩阵到矩阵或向量的转换函数将以原矩阵的形式出现。也就是说,定义在稀疏矩阵上的运算生成稀疏矩阵,定义在满矩阵上的运算生成满矩阵。
③ 两个矩阵运算符(如+、-、*、\、|)操作后的结果一般都是满矩阵,除非参加运算的矩阵都是稀疏矩阵,或者操作本身(如.*、&)保留矩阵的稀疏性。
④ 在参与矩阵扩展(如[AB ; CD])的子矩阵中,只要有一个是稀疏矩阵,所得的结果就是稀疏矩阵。
⑤ 在矩阵引用中,将仍以原矩阵形式给出结果。若S矩阵是稀疏的,而Y矩阵是全元素的,则不管I、J 是标量还是向量,右引用 Y=S(I,J) 都生成稀疏矩阵,左引用 S(I,J)=Y 都生成满矩阵。
五、多维数组
1. 多维数组的属性
(1)多维数组的构建
前面“矩阵合并”中已经介绍过如何通过 cat 命令实现矩阵的合并,在MATLAB中也可以通过 cat 函数来构建多维数组。在多维数组中,cat 函数的调用格式如下:
c = cat(dim , a , b) % 沿维度 dim 将 b 串联到 a 的末尾
c = cat(dim , a1 , a2 , ... , an) % 沿维度 dim 串联a1、a2、a3、...、an
使用方括号运算符“[ ]”也可以实现二维数组(矩阵)的串联。如,[a , b]或[a b]将数组 a 和 b 进行水平串联,[a ; b]将数组 a 和 b 进行垂直串联。
>> a=ones(3); % 创建一个3×3全1矩阵
>> b=zeros(3); % 创建一个3×3全0矩阵
>> c1=cat(1,a,b) % 垂直方向上合并数组
c1 =
1 1 1
1 1 1
1 1 1
0 0 0
0 0 0
0 0 0
>> c2=cat(2,a,b) % 水平方向上合并数组
c2 =
1 1 1 0 0 0
1 1 1 0 0 0
1 1 1 0 0 0
>> c3=cat(3,a,b) % 创建三维数组,具有行、列、页三个维度
c3(:,:,1) =
1 1 1
1 1 1
1 1 1
c3(:,:,2) =
0 0 0
0 0 0
0 0 0
>> c4=cat(4,a,b) % 创建四维数组
c4(:,:,1,1) =
1 1 1
1 1 1
1 1 1
c4(:,:,1,2) =
0 0 0
0 0 0
0 0 0
(2)多维数组属性的获取
>> a=cat(4,[6 2 0;4 5 9],[0 3 2;9 4 2],[7 1 2;4 8 4]) % 构建多维数组
a(:,:,1,1) =
6 2 0
4 5 9
a(:,:,1,2) =
0 3 2
9 4 2
a(:,:,1,3) =
7 1 2
4 8 4
>> size(a) % 获取数组a的尺寸属性
ans =
2 3 1 3
>> ndims(a) % 获取数组a的维度属性
ans =
4
>> whos a
Name Size Bytes Class Attributes
a 2x3x1x3 144 double
2. 多维数组相关操作
(1)多维数组的索引
MATLAB 中多维数组的索引方式也可分为“多下标索引”和“单下标索引”。实际上在内存中是按照“行-列-页...”的顺序将多维数组的所有元素进行线性存储的。
>> a=randn(3,5,2)
a(:,:,1) =
-0.8637 -1.1135 -0.7697 1.1174 0.5525
0.0774 -0.0068 0.3714 -1.0891 1.1006
-1.2141 1.5326 -0.2256 0.0326 1.5442
a(:,:,2) =
0.0859 -1.0616 0.7481 -0.7648 0.4882
-1.4916 2.3505 -0.1924 -1.4023 -0.1774
-0.7423 -0.6156 0.8886 -1.4224 -0.1961
>> a(3,2,2) % 数组a的第3行第2列第2页元素
ans =
-0.6156
>> a(21) % 数组a的第21个元素(即第3行第2列第2页元素)
ans =
-0.6156
(2)多维数组的维度操作
多维数组的维度操作包括对多维数组形状的重排和维度的重新排序。reshape 函数可以改变多维数组的形状,但操作前后MATLAB按照“行-列-页-...”优先级对多维数组进行线性存储的方式不变。reshape 函数的调用格式如下:
B = reshape(A, sz1, ...,szN) % 将 A 重构为一个 sz1×…×szN数组,其中 sz1、…、szN指定每个维度的大小
许多多维数组在某一维度上只有一个元素,可以利用函数 squeeze 来消除这种单值维度。其调用格式如下:
B = squeeze(A) % 返回一个数组,其元素与输入数组 A 相同,但删除了长度为1的维度。例: 若 A 是 3×1×2 数组,则 squeeze(A)返回 3×2 矩阵
注意:当 A 是行向量、列向量、标量或没有长度为1的维度的数组,则返回原来的 A。
>> a1=ones(3,2,3); % 创建一个3×2×3的全1数组
>> b1=reshape(a1,3,6) % 将数组a1转换为3行6列矩阵
b1 =
1 1 1 1 1 1
1 1 1 1 1 1
1 1 1 1 1 1
>> b2=reshape(a1,2,[]) % 将数组a1转换为2行3×3=9列矩阵
b2 =
1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1
>> a2=zeros(3,1,3); % 创建一个3×1×3的全0数组
>> a2(:,:,1)=[1 2 3]'; % 重置数组a2第1页元素
>> a2(:,:,2)=[-2 -4 -6]'; % 重置数组a2第2页的元素
>> b3=squeeze(a2) % 将3×1×3的数组a2转换为3×3矩阵
b3 =
1 -2 0
2 -4 0
3 -6 0
permute 函数可以按照指定的顺序重新定义多维数组的维度顺序,其调用格式如下:
B = permute(A, dimorder) % 按照向量 dimorder 指定的顺序重新排列数组的维度。
注意:permute 重新定义后的多维数组是把原来在某一维度上的所有元素移动到新的维度上,这会改变多维数组线性存储的位置,与reshape是不同的。
>> a=rand(3,5,2) % 创建一个3×5×2的数组,对行、列、页进行编号,3、5、2依次对应1、2、3
a(:,:,1) =
0.8147 0.9134 0.2785 0.9649 0.9572
0.9058 0.6324 0.5469 0.1576 0.4854
0.1270 0.0975 0.9575 0.9706 0.8003
a(:,:,2) =
0.1419 0.7922 0.0357 0.6787 0.3922
0.4218 0.9595 0.8491 0.7577 0.6555
0.9157 0.6557 0.9340 0.7431 0.1712
>> b=permute(a,[3 2 1]) % 将数组a按照编号顺序进行维度的修改,b为2×5×3数组
b(:,:,1) =
0.8147 0.9134 0.2785 0.9649 0.9572
0.1419 0.7922 0.0357 0.6787 0.3922
b(:,:,2) =
0.9058 0.6324 0.5469 0.1576 0.4854
0.4218 0.9595 0.8491 0.7577 0.6555
b(:,:,3) =
0.1270 0.0975 0.9575 0.9706 0.8003
0.9157 0.6557 0.9340 0.7431 0.1712
>> c=permute(b,[3 2 1]) % 将数组b按照编号顺序进行维度的修改,c为3×5×2数组
c(:,:,1) =
0.8147 0.9134 0.2785 0.9649 0.9572
0.9058 0.6324 0.5469 0.1576 0.4854
0.1270 0.0975 0.9575 0.9706 0.8003
c(:,:,2) =
0.1419 0.7922 0.0357 0.6787 0.3922
0.4218 0.9595 0.8491 0.7577 0.6555
0.9157 0.6557 0.9340 0.7431 0.1712
>> d=permute(a,[1 3 2]) % 将数组a按照编号顺序进行维度的修改,b为3×2×5数组
d(:,:,1) =
0.8147 0.1419
0.9058 0.4218
0.1270 0.9157
d(:,:,2) =
0.9134 0.7922
0.6324 0.9595
0.0975 0.6557
d(:,:,3) =
0.2785 0.0357
0.5469 0.8491
0.9575 0.9340
d(:,:,4) =
0.9649 0.6787
0.1576 0.7577
0.9706 0.7431
d(:,:,5) =
0.9572 0.3922
0.4854 0.6555
0.8003 0.1712
(3)多维数组参与数学计算
多维数组参与数学计算,可以针对某一维度的向量,也可以针对单个元素,或者针对某一特定页面上的二维数组。
① sum(和)、mean(均值) 等函数可以对多维数组中第1个不为1的维度上的向量进行计算。
② sin(正弦)、cos(余弦) 等函数则对多维数组中的每一个单独元素进行计算。
③ eig 等针对二维数组(矩阵)的运算函数则需要用指定页面上的二维数组作为输入函数。
>> a=randn(2,4,2) % 创建一个2×4×2随机数组
a(:,:,1) =
0.8884 -1.0689 -2.9443 0.3252
-1.1471 -0.8095 1.4384 -0.7549
a(:,:,2) =
1.3703 -0.1022 0.3192 -0.8649
-1.7115 -0.2414 0.3129 -0.0301
>> sum(a) % 行与行之间两个相邻元素求和
ans(:,:,1) =
-0.2587 -1.8784 -1.5059 -0.4297
ans(:,:,2) =
-0.3412 -0.3437 0.6321 -0.8949
>> sin(a) % 对每个元素求正弦
ans(:,:,1) =
0.7761 -0.8767 -0.1960 0.3195
-0.9116 -0.7239 0.9912 -0.6852
ans(:,:,2) =
0.9800 -0.1021 0.3138 -0.7610
-0.9901 -0.2391 0.3078 -0.0300
>> eig(a(:,[1 2],1)) % 对数组a中的第1页中的2行2列元素求特征值
ans =
1.4347
-1.3558
>> a=[ 0.8884 -1.0689; -1.1471 -0.8095]; % 进行验证
>> eig(a)
ans =
1.4347
-1.3558
六、数据类型
MATLAB作为一种可编程语言,其数据作为计算机处理对象,支持多种数据类型。在MATLAB中,基本数据类型分别是整型数据(8种)、单精度浮点型、双精度浮点型、逻辑型、字符型、元胞数组、结构体和函数句柄等,如下图所示。每种基本的数据类型均以矩阵的形式出现,该矩阵可以是最小的 0×0 矩阵,也可以是任意大小的 n 维矩阵。在实际应用中,数据类型的选取需要考虑以下方面的内容:①数据的大小和范围。②数据的精度要求。③数据的显示格式。
1. 数值型
(1)整数型
① 在MATLAB中,整数类型包含4种有符号整数和4种无符号整数,支持 1B、2B、4B 和 8B 的有符号整数和无符号整数(B:Byte 字节)。
② 在实际应用时,要根据“数据的大小和范围”,选择合适的整数类型。例如:最大值为100的数据可以用 1B 的整数表示,而没有必要使用 8B 的整数来表示。
③ 类型转换函数不仅可以将其它数据类型的数值强制转换为整数类型,还可以用于生成整数类型的数值。
④ 如果要验证一个变量是否为整数类型,可以使用isinteger函数,;如果想要查看数据类型并输出,可以使用class函数。
b = isinteger(a) % a是输入变量,b是输出逻辑值。如果a是整数,则b为1;否则,b为
class(x) % ans会直接给出变量 x 的数据类型。(变量要用括号括起来)
>> x=uint16(16628) %无符号2B整数
x =
uint16
16628
>> isinteger(x) %验证变量是否为整数,如果x是整数,则返回值为1;否则,返回值为0。
ans =
logical
1
>> class(x) %查看变量的数据类型,ans会直接给出变量的数据类型
ans =
'uint16'
(2)浮点数型
① 在MATLAB中浮点数分为“单精度浮点数(single)”和“双精度浮点数(double)”。
② 双精度浮点数(double)是MATLAB中默认数据类型。
③ 可以使用类型转换函数将数据类型转换为单精度或双精度浮点类型。
b = single(a); % a 是输入的数值或数组,b 是转换后的单精度浮点类型数组。
whos x % 用于查看当前工作空间中的变量列表,显示变量的名称、大小、字节占用等信息。(变量不需要用括号括起来)
>> a=1.3
a =
1.3000
>> whos a
Name Size Bytes Class Attributes
a 1x1 8 double
>> a=single(a)
a =
single
1.3000
>> whos a
Name Size Bytes Class Attributes
a 1x1 4 single
(3)复数型
① 复数包括实部和虚部两部分,虚部单位是 -1 的平方根,在MATLAB中,可以用 i 或 j 表示。
② 可以直接使用赋值语句产生复数,也可以利用 copmlex 函数创建复数。
③ 利用 real 和 imag 函数,可以把复数分为实数和虚数两部分。
z = complex(a,b) % 通过两个实数 a,b 创建一个复数 z,z=a+bi
z = complex(x) % 返回 x 的等效复数。x 为实数,返回 x+0i;x 为复数,则 z 与 x 相同
z = 3+4i
real(z) % 返回复数的实部,返回值为3
imag(z) % 返回复数的虚部,返回值为4
R = rand % 返回一个区间在(0,1)内的均匀分布的随机数
R = rand(n) % 生成 n×n 的矩阵随机数,每个元素均位于(0,1)之间
>> a=12+6i
a =
12.0000 + 6.0000i
>> x=rand(2)*(-3); % 生成一个2×2的随机浮点矩阵,然后矩阵中的每个元素均乘-3
>> y=rand(2)*5; % 生成一个2×2的随机浮点矩阵,然后矩阵中的每个元素具乘5
>> z=complex(x,y) % 创建复数,x、y是实数,z是以x为实部、y为虚部的复数
z =
-2.4442 + 3.1618i -0.3810 + 1.3925i
-2.7174 + 0.4877i -2.7401 + 2.7344i
>> x=rand(2); % 生成一个2×2的随机矩阵,每个元素均位于(0,1)之间
>> z=complex(x) % 创建复数,x是实数,z是以x为实部、0为虚部的复数
z =
0.9575 + 0.0000i 0.1576 + 0.0000i
0.9649 + 0.0000i 0.9706 + 0.0000i
(4)Inf 和 NaN
① 规定用 Inf 和 -Inf 分别表示“正无穷大”和“负无穷大”。在除法运算时,除数为0或运算结果溢出(结果超出了设定的数据类型所对应的范围)都会导致出现 Inf 或 -Inf 的结果。
② 规定用 NaN 表示一个既不是实数又不是复数的数值(非数),NaN是Not a Number 的缩写,类似0/0、Inf/Inf 的表达式得到的结果均为 NaN 。
③ isinf 函数可以用于验证变量是否为无穷大。
b = isinf(a) % a是输入变量,b是输出逻辑值。如果a是无穷大,则b为1;否则,b为0
exp(x) % 用于计算欧拉数e(约为2.71828)的指数,结果为 e 的 x 次方
logm(n) % 用于计算一个数的自然对数,结果为以 m 为底,n 的对数
ln(y) % 用于计算以 e(欧拉数) 为底,y 的对数
>> 1000/0
ans =
Inf
>> x=exp(1000)
x =
Inf
>> x=log(0)
x =
-Inf
>> 0/0
ans =
NaN
>> Inf/Inf
ans =
NaN
>> isinf(x)
ans =
logical
1
2. 逻辑型
逻辑型用1和0表示 true 和 false 两种状态。可以用函数 logical 得到逻辑类型的数值,函数 logical 可以把任何非零的数值转换为逻辑 true(1),把数值0转换为逻辑 false(0)。复数值和 NaN不能转换为逻辑值,强制转换时会提示转换错误。
B = logical(A) % A是一个数值数组,B是返回的逻辑数组。如果A中的元素是非零值,则B中相应的元素为true;如果A中的元素是零,则B中相应的元素为false。
disp(A) % 用于在命令窗口中显示文本或变量的值
>> logical(1)
ans =
logical
1
>> logical(0)
ans =
logical
0
>> logical(-100)
ans =
logical
1
>> a=[1,0,2,0,3];
>> b=logical(a);
>> disp(b)
1 0 1 0 1
3. 字符型
% 在MATLAB中,字符变量、字符串和字符数组之间存在一定的关系。首先,一个字符串被视为一个行向量,而字符串中的每一个字符(包括空格符)则是以其ASCII的形式存放于此向量的每一个元素中。这意味着,我们可以对字符串进行搜索、替换、分割和合并等操作。其次,字符变量在MATLAB中是以字符数组的形式存在的。每个字符变量都有一个长度和一个字节数,可以容纳任意长度的文本数据。最后,需要明确的是,尽管这几个概念在操作上有许多相似之处,但它们在数据类型上是不同的。字符变量是一种特殊的数据类型,用于存储字符数据;字符串则是字符数组的一种表现形式,它以可读的形式显示出来;而字符数组则是一种更为通用的数据结构,可以容纳各种类型的数据。%
% 在MATLAB中,使用单引号和双引号都可以定义字符串数组。但是,它们之间有一些区别。使用单引号定义的字符串数组被视为字符向量,即一个包含单个字符的行向量或列向量。而使用双引号定义的字符串数组被视为字符串数组,即一个包含一个或多个字符串的行向量或列向量。此外,使用双引号定义的字符串数组可以包含转义序列和特殊字符,例如换行符和制表符,而使用单引号定义的字符串数组不能包含这些字符。%
① 字符和字符串统称为字符型数据,规定用char表示字符数据类型。一个 char类型的1×n数组可以称为字符串 string。
② MATLAB中的 char 类型都是以 2B(16bit) 的 unicode 字符存储的。(Unicode 是一种计算机中用于表示文本的标准,了解即可。)
③创建字符串可以采用直接赋值法,也可以采用 char 函数。
ch = ' A ' % 将变量 ch 定义为字符数组‘A’,直接赋值法
str = char(A) % 将输入数组 A 转换为字符数组,若 A 是字符串“abc”,则 str 是字符数组‘abc’
str = char(A1,...,An) % 将数组 A1 到 An 转换为一个字符数组。转换为字符后,输入数组变为 str 中的行,str 的列数与数组 A1 到 An 中的“最大列数”保持一致,小于该列数的行,用空格进行填充;如果某输入数组是空字符数组,则 str 中相应的行是一行空格。输入数组 A1,...,An 不能是字符串数组、元胞数组或分类数组。
>> str="abc"
str =
"abc"
>> whos str
Name Size Bytes Class Attributes
str 1x1 150 string
>> str='a'
str =
'a'
>> whos str
Name Size Bytes Class Attributes
str 1x1 2 char
>> str='abc'
str =
'abc'
>> whos str
Name Size Bytes Class Attributes
str 1x3 6 char
>> str=char("abc")
str =
'abc'
>> whos str
Name Size Bytes Class Attributes
str 1x3 6 char
>> str=char('my','name','is','ding')
str =
4×4 char 数组
'my '
'name'
'is '
'ding'
>> str=char('my','name','is',' ','ding')
str =
5×4 char 数组
'my '
'name'
'is '
' '
'ding'