MATLAB完全自学教程
上QQ阅读APP看书,第一时间看更新

2.8 数组

数组是MATLAB进行计算和处理的核心内容之一,出于快速计算的需要,数组总是被看作存储和运算的基本单元,标量数据也被看作1×1的数组。因此,数组的创建、寻址和操作就显得非常重要。MATLAB提供了各种数组的创建方法和操作方法,使得MATLAB的数值计算和操作更加灵活、方便。数组的创建和操作是MATLAB计算和操作的基础,针对不同维数的数组,MATLAB提供了各种不同的数据创建方法,甚至可以通过创建低维数组来得到高维数组。

2.8.1 一维数组的创建

概括而言,创建一维数组时,可以采用以下几种方法。

直接输入法:此时,可以直接通过空格、逗号和分号来分隔数组元素,在数组中输入任意的元素,生成一维数组。

步长生成法:x=a:inc:b,在使用这种方法创建一维数组时,ab为一维向量数组的起始数值和终止数值,inc为数组的间隔步长。如果ab为整数,省略inc可以生成间隔为1的数组。根据ab的大小不同,inc可以采用正数,也可以采用负数来生成一维向量数组。

等间距线性生成法:x=linspace(a,b,n),这种方法采用函数在ab之间的区间内得到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