2.8 数组
数组是MATLAB进行计算和处理的核心内容之一,出于快速计算的需要,数组总是被看作存储和运算的基本单元,标量数据也被看作1×1的数组。因此,数组的创建、寻址和操作就显得非常重要。MATLAB提供了各种数组的创建方法和操作方法,使得MATLAB的数值计算和操作更加灵活、方便。数组的创建和操作是MATLAB计算和操作的基础,针对不同维数的数组,MATLAB提供了各种不同的数据创建方法,甚至可以通过创建低维数组来得到高维数组。
2.8.1 一维数组的创建
概括而言,创建一维数组时,可以采用以下几种方法。
● 直接输入法:此时,可以直接通过空格、逗号和分号来分隔数组元素,在数组中输入任意的元素,生成一维数组。
● 步长生成法:x
=a:inc:b
,在使用这种方法创建一维数组时,a
和b
为一维向量数组的起始数值和终止数值,inc
为数组的间隔步长。如果a
和b
为整数,省略inc
可以生成间隔为1的数组。根据a
和b
的大小不同,inc
可以采用正数,也可以采用负数来生成一维向量数组。
● 等间距线性生成法:x
=linspace(a
,b
,n
),这种方法采用函数在a
和b
之间的区间内得到n
个线性采样数据点。
● 等间距对数生成法:x
=logspace(a
,b
,n
),采用这种方法时,在设定采样点总个数n
的情况下,采用常用对数计算得到n
个采样点数据值。
例2.51 一维数组的创建。
>> x1=[0,pi,0.3
*pi,1.5,2] %直接输入法
x1 =
0 3.1416 0.9425 1.5000 2.0000
>> x2=0:0.6:6 %步长生成法
x2 =
Columns 1 through 8
0 0.6000 1.2000 1.8000 2.4000 3.0000 3.6000 4.2000
Columns 9 through 11
4.8000 5.4000 6.0000
>> x3=linspace(1,6,7) %等间距线性生成法
x3 =
1.0000 1.8333 2.6667 3.5000 4.3333 5.1667 6.0000
>> x3=linspace(1,4,5)
x3 =
1.0000 1.7500 2.5000 3.2500 4.0000
>> x4=logspace(1,4,5) %等间距对数生成法
x4 =
1.0e+004 *
0.0010 0.0056 0.0316 0.1778 1.0000
当创建数组后,对单个元素的访问可以直接通过元素的索引来进行;如果访问数组内的一块数据,则可以通过冒号的方式进行;如果访问其中的部分数值,则可以通过构造访问序列或通过构造向量列表进行。在访问数组元素的过程中,访问的索引数组必须是正整数,否则,系统将会提示警告信息。
例2.52 一维数组的访问。
>> x1(4) %
通过索引访问数组元素
ans =
1.5000
>> x1(1:4) %访问一块数据
ans =
0 3.1416 0.9425 1.5000
>> x1(3:end) %访问一块数据
ans =
0.9425 1.5000 2.0000
>> x1(1:2:5) %构造访问数组
ans =
0 0.9425 2.0000
>> x1([1 5 3 4 2]) %直接构造访问数组
ans =
0 2.0000 0.9425 1.5000 3.1416
>> x1(3,2)
Index exceeds matrix dimensions.
一维数组可以是一个行向量,也可以是一列多行的列向量。在定义的过程中,如果元素之间通过“;”分隔,那么生成的向量是列向量;而通过空格或逗号分隔元素的则为行向量。当然列向量和行向量之间可以通过转置操作(“'”)来进行相互之间的转换。但需要注意的是,如果一维数组的元素是复数,那么经过转置操作后,得到的是复数的共轭转置结果,而采用点-共轭转置操作得到的转置数组,并不进行共轭操作。
例2.53 一维复数数组的运算。
>> A=[1;2;3;4;5]
A =
1
2
3
4
5
>> B=A'
B =
1 2 3 4 5
>> C=linspace(1,6,5)'
C =
1.0000
2.2500
3.5000
4.7500
6.0000
>> Z=A+C*i
Z =
1.0000 + 1.0000i
2.0000 + 2.2500i
3.0000 + 3.5000i
4.0000 + 4.7500i
5.0000 + 6.0000i
>> Z1=Z'
Z1 =
Columns 1 through 3
1.0000 - 1.0000i 2.0000 - 2.2500i 3.0000 - 3.5000i
Columns 4 through 5
4.0000 - 4.7500i 5.0000 - 6.0000i
>> Z2=Z.'
Z2 =
Columns 1 through 3
1.0000 + 1.0000i 2.0000 + 2.2500i 3.0000 + 3.5000i
Columns 4 through 5
4.0000 + 4.7500i 5.0000 + 6.0000i
2.8.2 多维数组的创建
二维数组的创建方法和一维数组的创建方法不同,常用创建方法如下。
直接输入二维数组的元素来创建。此时,二维数组的行和列可以通过一维数组的创建方法来创建,不同行之间的数据可以通过分号进行分隔,同一行中的元素可以通过逗号或空格进行分隔。
例2.54 二维数组的创建。
>> A=[1 2 3 4 5;linspace(0,6,5);1:2:9;4:8]
A =
1.0000 2.0000 3.0000 4.0000 5.0000
0 1.5000 3.0000 4.5000 6.0000
1.0000 3.0000 5.0000 7.0000 9.0000
4.0000 5.0000 6.0000 7.0000 8.0000
>> A=[1 2 3 4 5;linspace(0,6,5);1:2:9;4:9]
Error using vertcat
CAT arguments dimensions are not consistent.
>> B=[1 2 3
4 5 6
7 8 9]
B =
1 2 3
4 5 6
7 8 9
在创建二维数组的过程中,需要严格保证所生成矩阵的行和列的数目相同。如果两者的数目不同,那么系统将会出现错误提示。此外,在直接生成矩阵的过程中,可以通过按Enter键来保证矩阵生成另一行元素。
对于多维数组,如在三维数组中存在行、列和页这三维,即三维数组中的第3维是页。在每一页中,存在行和列。在MATLAB中,可以创建更高维的多维数组,但实际上主要用到的还是三维数组。三维数组的创建方法有以下几种。
● 直接创建法。可以选择使用MATLAB提供的一些内置函数来创建三维数组,如zeros()、ones()、rand()、randn()等。
● 通过直接索引的方法进行创建。
● 使用MATLAB的内置函数reshape()和repmat()将二维数组转换为三维数组。
● 使用cat()函数将低维数组转换为高维数组。
例2.55 三维数组的创建。
>> A=zeros(5,4,2)
A(:,:,1) =
0 0 0 0
0 0 0 0
0 0 0 0
0 0 0 0
0 0 0 0
A(:,:,2) =
0 0 0 0
0 0 0 0
0 0 0 0
0 0 0 0
0 0 0 0
>> B=zeros(3,3) %通过创建三维数组来扩展
B =
0 0 0
0 0 0
0 0 0
>> B(:,:,2)=ones(3,3) %向三维数组中添加三维数组来增加页
B(:,:,1) =
0 0 0
0 0 0
0 0 0
B(:,:,2) =
1 1 1
1 1 1
1 1 1
>> B(:,:,3)=5 %通过标量扩展得到三维数组的另外一页
B(:,:,1) =
0 0 0
0 0 0
0 0 0
B(:,:,2) =
1 1 1
1 1 1
1 1 1
B(:,:,3) =
5 5 5
5 5 5
5 5 5
>> C=reshape(B,3,9) %得到三维数组
C =
0 0 0 1 1 1 5 5 5
0 0 0 1 1 1 5 5 5
0 0 0 1 1 1 5 5 5
>> C=[B(:,:,1) B(:,:,2) B(:,:,3)] %直接扩展得到三维数组
C =
0 0 0 1 1 1 5 5 5
0 0 0 1 1 1 5 5 5
0 0 0 1 1 1 5 5 5
>> reshape(C,3,3,3) %将得到的三维数组重新生成三维数组
ans(:,:,1) =
0 0 0
0 0 0
0 0 0
ans(:,:,2) =
1 1 1
1 1 1
1 1 1
ans(:,:,3) =
5 5 5
5 5 5
5 5 5
>> A1=zeros(2)
A1 =
0 0
0 0
>> A2=ones(2)
A2 =
1 1
1 1
>> A3=repmat(2,2,2)
A3 =
2 2
2 2
>> A=cat(3,A1,A2,A3) %在第3维上合并低维数组
A(:,:,1) =
0 0
0 0
A(:,:,2) =
1 1
1 1
A(:,:,3) =
2 2
2 2
>> A=cat(2,A1,A2,A3) %在第2维上合并低维数组
A =
0 0 1 1 2 2
0 0 1 1 2 2
>> A=cat(1,A1,A2,A3) %在第1维上合并低维数组
A =
0 0
0 0
1 1
1 1
2 2
2 2
通过以上内容可以看出,三维数组可以通过多种方法进行创建。在利用内置函数创建三维数组的过程中,关于这些内置函数的其他用法,读者可以通过help命令查找相应的帮助文件。
2.8.3 数组的运算
数组的运算包括数组和标量之间的运算,以及数组和数组之间的运算。对于数组和标量之间的运算,是数组的元素和标量之间直接进行数学运算,比较简单。对于数组和数组之间的运算,尤其是对于乘、除运算和乘方运算,如果采用点方式进行运算,则表明是数组的元素之间的运算;而如果是直接进行乘、除、乘方运算,则是向量或矩阵之间的运算。两者的意义完全不同。
此外,还需要注意的是,对于向量的除法运算,左除“\”和右除“/”的意义不同。两者的除数和被除数是不同的。
例2.56 数组的基本运算。
>> A=[1:3;4:6;7:9]
A =
1 2 3
4 5 6
7 8 9
>> B=[1 1 1;2 2 2;3 3 3]
B =
1 1 1
2 2 2
3 3 3
>> A.*B
ans =
1 2 3
8 10 12
21 24 27
>> A./B
ans =
1.0000 2.0000 3.0000
2.0000 2.5000 3.0000
2.3333 2.6667 3.0000
>> A.\B
ans =
1.0000 0.5000 0.3333
0.5000 0.4000 0.3333
0.4286 0.3750 0.3333
>> A/B
Warning: Matrix is singular to working
precision.
ans =
NaN NaN NaN
NaN NaN NaN
NaN NaN NaN
>> A\B
Warning: Matrix is close to singular or badly
scaled. Results may be inaccurate. RCOND =
1.541976e-018.
ans =
-0.3333 -0.3333 -0.3333
0.6667 0.6667 0.6667
0 0 0
>> A.^2
ans =
1 4 9
16 25 36
49 64 81
>> A^2
ans =
30 36 42
66 81 96
102 126 150
对于矩阵的加、减运算以及其他点运算,都是针对矩阵的元素进行的。而对于乘、除、乘方运算则通过矩阵运算进行。关于更详细的数组和矩阵运算方面的内容,读者可以查阅矩阵运算方面的数学理论书籍。
2.8.4 常用的标准数组
MATLAB中提供了一些函数,用来创建常用的标准数组。常用的标准数组包括全0数组、全1数组、单位矩阵、随机矩阵、对角矩阵以及元素为指定常数的数组等。MATLAB中创建标准数组的函数如表2-8所示。
表2-8 MATLAB中创建标准数组的函数
例2.57 常用标准数组的创建。
>> A=eye(3)
A =
1 0 067
0 1 0
0 0 1
>> B=randn(3)
B =
-0.4336 2.7694 0.7254
0.3426 -1.3499 -0.0631
3.5784 3.0349 0.7147
>> C=1:5
C =
1 2 3 4 5
>> diag(C,1)
ans =
0 1 0 0 0 0
0 0 2 0 0 0
0 0 0 3 0 0
0 0 0 0 4 0
0 0 0 0 0 5
0 0 0 0 0 0
>> diag(C,-2)
ans =
0 0 0 0 0 0 0
0 0 0 0 0 0 0
1 0 0 0 0 0 0
0 2 0 0 0 0 0
0 0 3 0 0 0 0
0 0 0 4 0 0 0
0 0 0 0 5 0 0
2.8.5 低维数组的寻址和搜索
数组中包含多个元素,在对数组的单个元素或多个元素进行访问时,需要对数组进行寻址操作。MATLAB提供了强大的功能函数,可以用于确定用户感兴趣的数组元素的索引,实现插入、提取和重排子数组。数组寻址如表2-9所示。
表2-9 数组寻址
例2.58 数组寻址方法的使用。
>> A=[1 2 3;4 5 6;7 8 9]
A =
1 2 3
4 5 6
7 8 9
>> A(2,2)=2 %设置二维数组的元素数值
A =
1 2 3
4 2 6
7 8 9
>> A(:,3)=3 %改变二维数组的一列元素数值
A =
1 2 3
4 2 3
7 8 3
>> B=A(3:-1:1,1:3) %通过寻址方法创建新的二维数组
B =
7 8 3
4 2 3
1 2 3
>> C=A([1 3],1:2) %通过列向量创建二维数组
C =
1 2
7 8
>> D=A(:) %通过提取A的各列元素延展成列向量
D =
1
4
7
2
2
8
3
3
3
>> A(:,2)=[] %通过空赋值语句删除数组元素
A =
1 3
4 3
7 3
排序是数组操作的一个重要方面。MATLAB提供了sort()函数来进行排序。对于sort()函数的具体使用方法,读者可以通过help sort语句加以查询。在进行一维数组排序时,默认的排序方式为升序排序。如果需要降序排序,则可以在sort()函数的第2个参数处用descend
代替。
例2.59 一维数组的排序。
>> A=randn(1,9)
A =
Columns 1 through 7
0.8229 -0.4887 0.8278 -1.0559 0.0414 -1.9709 1.2506
Columns 8 through 9
-1.6884 0.7757
>> [As,idx]=sort(A,'ascend')
As =
Columns 1 through 4
-2.4574 -1.2488 -0.8461 0.2478
Columns 5 through 9
0.3462 0.3627 1.0335 1.3073 1.7602
idx =
2 6 9 1 4 3 7 5 8
在进行二维数组排序时,sort()函数只对数组的列进行排序。一般情况下,用户只关心对某一列的排序问题,此时可以通过一定的方式来进行重新排序。如果对行进行排序,则需要为 sort()函数提供第2个参数2,如下面的程序。
>> A=randn(4,3)
A =
0.2109 -0.7524 0.5744
-0.4274 -0.6697 -0.6965
-0.1321 -1.5276 -0.5026
1.2908 -0.7053 0.0306
>> [As,idx]=sort(A)
As =
-0.4274 -1.5276 -0.6965
-0.1321 -0.7524 -0.5026
0.2109 -0.7053 0.0306
1.2908 -0.6697 0.5744
idx =
2 3 2
3 1 3
1 4 4
4 2 1
>> [tmp,idx]=sort(A(:,3)) %第3列进行排序
tmp =
-0.6965
-0.5026
0.0306
0.5744
idx =
2
3
4
1
>> As=A(idx,:) %利用idx向量来重新排序
As =
-0.4274 -0.6697 -0.6965
-0.1321 -1.5276 -0.5026
1.2908 -0.7053 0.0306
0.2109 -0.7524 0.5744
>> As=sort(A,2) %对行进行排序
As =
-0.7524 0.2109 0.5744
-0.6965 -0.6697 -0.4274
-1.5276 -0.5026 -0.1321
-0.7053 0.0306 1.2908
在MATLAB中,子数组搜索功能可以通过系统提供的find()函数来实现,可以返回符合条件的数组的索引数值,对于二维数组可以返回两个索引数值。关于搜索的其他命令,用户可以用help find来查询。
例2.60 数组搜索方法介绍。
>> A=-4:4
A =
-4 -3 -2 -1 0 1 2 3 4
>> h=find(A>0)
h =
6 7 8 9
>> B=[1 2 3;4 5 6;7 8 9]
B =
1 2 3
4 5 6
7 8 9
>> [i,j]=find(B>5)
i =
3
3
2
3
j =
1
2
3
3
>> h=find(B>5)
h =
3
6
8
9
>> x=randperm(8)
x =
2 5 3 4 1 6 7 8
>> find(x>5)
ans =
6 7 8
>> find(x>5,1)
ans =
6
>> find(x>5,2,'last')
ans =
7 8
如果要搜索最大值或最小值,那么可以使用max()或min()函数来进行。如果搜索的是二维数组,那么这两个函数返回每一列的最大值或最小值,如下面的程序。
>> A=rand(4,4)
A =
0.1761 0.8952 0.2469 0.8967
0.4339 0.4594 0.0963 0.9151
0.2068 0.7995 0.9865 0.3734
0.1102 0.8554 0.2648 0.2686
>> [mx,rx]=max(A) %搜索每一列的最大值
mx =
0.4339 0.8952 0.9865 0.9151
rx =
2 1 3 2
>> [mx,rx]=min(A) %搜索每一列的最小值
mx =
0.1102 0.4594 0.0963 0.2686
rx =
4 2 2 4
2.8.6 低维数组的处理函数
低维数组的处理函数如表2-10所示。
表2-10 低维数组的处理函数
例2.61 低维数组处理函数介绍。
>> A=[1:4;5 6 7 8;9:12]
A =
1 2 3 4
5 6 7 8
9 10 11 12
>> B=fliplr(A) %左右对称变换
B =
4 3 2 1
8 7 6 5
12 11 10 9
>> C=flipud(A) %上下对称变换
C =
9 10 11 12
5 6 7 8
1 2 3 4
>> D=rot90(A) %旋转90°
D =
4 8 12
3 7 11
2 6 10
1 5 9
>> circshift(A,1) %循环移动第1行
ans =
9 10 11 12
1 2 3 4
5 6 7 8
>> circshift(A,[0,1]) %循环移动第1列
ans =
4 1 2 3
8 5 6 7
12 9 10 11
>> circshift(A,[-1,1]) %循环移动行和列
ans =
8 5 6 7
12 9 10 11
4 1 2 3
>> diag(A,1) %提取对角线元素
ans =
2
7
12
>> tril(A) %保留下三角矩阵
ans =
1 0 0 0
5 6 0 0
9 10 11 0
>> tril(A,1)
ans =
1 2 0 0
5 6 7 0
9 10 11 12
>> triu(A) %保留上三角矩阵
ans =
1 2 3 4
0 6 7 8
0 0 11 12
>> triu(A,2)
ans =
0 0 3 4
0 0 0 8
0 0 0 0
在提取对角线元素和保留上、下三角矩阵时,所定义的第2个参数是以k
=0
的起始对角线,向上三角方向移动时,k
的数值增大;而向下三角方向移动时,k
的数值减小。此外,对于非方阵的矩阵,以过第1个元素的方阵的对角线为对角线的起始位置。
例2.62 举例说明Kronecker张量积。
>> A=[1 2;3 4]
A =
1 2
3 4
>> I=eye(3)
I =
1 0 0
0 1 0
0 0 1
>> kron(A,I)
ans =
1 0 0 2 0 0
0 1 0 0 2 0
0 0 1 0 0 2
3 0 0 4 0 0
0 3 0 0 4 0
0 0 3 0 0 4
>> kron(I,A)
ans =
1 2 0 0 0 0
3 4 0 0 0 0
0 0 1 2 0 0
0 0 3 4 0 0
0 0 0 0 1 2
0 0 0 0 3 4
kron()函数执行的是Kronecker张量积运算,即将第1个参数数组的每一个元素和第2个参数数组的每一个元素相乘,形成一个分块矩阵。上面的例子同样也说明Kronecker张量积具有不可交换性。
2.8.7 高维数组的处理和运算
随着数组维数的增加,数组的运算和处理就会变得越来越困难,MATLAB提供了一些函数,可以进行高维数组的处理和运算。此处对高维数组(主要介绍三维数组)的一些处理和运算函数进行介绍。高维数组的处理和运算函数如表2-11所示。
表2-11 高维数组的处理和运算函数
例2.63 举例说明高维数组的处理和操作。
>> A=[1:4;5:8;9:12]
A =
1 2 3 4
5 6 7 8
9 10 11 12
>> B=reshape(A,[2 2 3])
B(:,:,1) =
1 9
5 2
B(:,:,2) =
6 3
10 7
B(:,:,3) =
11 8
4 12
>> C=cat(4,B(:,:,1),B(:,:,2),B(:,:,3))
C(:,:,1,1) =
1 9
5 2
C(:,:,1,2) =
6 3
10 7
C(:,:,1,3) =
11 8
4 12
>> D=squeeze(C) %降维操作
D(:,:,1) =
1 9
5 2
D(:,:,2) =
6 3
10 7
D(:,:,3) =
11 8
4 12
>> sub2ind(size(D),1,2,3) %索引转换
ans =
11
>> [i,j,k]=ind2sub(size(D),11)
i =
1
j =
2
k =
3
>> flipdim(D,1) %按行进行翻转
ans(:,:,1) =
5 2
1 9
ans(:,:,2) =
10 7
6 3
ans(:,:,3) =
4 12
11 8
>> flipdim(D,2) %按列进行翻转
ans(:,:,1) =
9 1
2 5
ans(:,:,2) =
3 6
7 10
ans(:,:,3) =
8 11
12 4
>> flipdim(D,3) %按页进行翻转
ans(:,:,1) =
11 8
4 12
ans(:,:,2) =
6 3
10 7
ans(:,:,3) =
1 9
5 2
>> shiftdim(D,1) %移动一维
ans(:,:,1) =
1 6 11
9 3 8
ans(:,:,2) =
5 10 4
2 7 12
>> E=permute(D,[3 2 1])
E(:,:,1) =
1 9
6 3
11 8
E(:,:,2) =
5 2
10 7
4 12
>> F=ipermute(E,[3 2 1])
F(:,:,1) =
1 9
5 2
F(:,:,2) =
6 3
10 7
F(:,:,3) =
11 8
4 12