MATLAB基础知识的掌握是学习MATLAB的关键之一。本章涉及的基础知识包括:MATLAB数据类型、MATLAB运算符与运算、字符串处理、矩阵基础知识。通过对这些内容的学习,可以将已学的数学基础知识渐渐融入MATLAB的学习中来。
知识要点
MATLAB中的基础数据类型主要包括数值类型、字符串、结构、单元数组和函数句柄等数据类型。本小节主要介绍这些基础数据类型及其相关的基础操作。
数值类型按数值在计算机中存储与表达的基本方式进行分类,主要有整数、单精度浮点数和双精度浮点数三类,如表2.1所示。在默认情况下,MATLAB对所有数值按照双精度浮点数类型进行存储等操作。
表2.1 数值类型分类
相对于双精度浮点数类型数据,整数型与单精度浮点型数据的优点在于节省变量占用的内存空间;在满足精度要求的情况下,可以考虑优先采用。需要时,可以指定系统按照整数型或单精度浮点型对指定的数字或数组进行存储、运算等操作。
提示
MATLAB自动进行内存的分配和回收,因此操作数据相对C/C++等编程语言而言简单了很多,有利于专心于程序算法的编制。
下面介绍这三种数值类型及衍生出来的复数类型。
1.整数类型
MATLAB中提供了4种有符号整数类型和4种无符号整数类型;有符号整数类型可以表示整数和负数,而无符号整数类型仅能表示负数。这8种类型的存储占用位数、能表示的数值范围和转换函数均不相同,如表2.2所示。
表2.2 MATLAB中的关系操作符
提示
不同的整数类型所占用的位数不同,因此能够表示的数值范围也不同。在实际应用中,应根据实际需要合理选择合适的整数类型。
由于MATLAB中数值的默认存储类型是双精度浮点类型,因此在将变量设置为整数类型时,需要使用表2.3中所示的转换函数,将双精度浮点数转换为指定的整数类型。
表2.3 MATLAB中的取整函数
2.浮点数类型
MATLAB中提供了单精度浮点数类型和双精度浮点数类型,其存储位宽、能够表示的数值范围、数值精度各方面均不相同,具体如表2.4所示。
表2.4 MATLAB中的取整函数
MATLAB中的默认数值类型为双精度浮点类型,但可以通过转换函数来创建单精度浮点类型。
双精度浮点数参与运算时,返回值的类型依赖于参与运算的其他数据类型。参与运算的其他数据为逻辑形、字符型时,返回结果为双精度浮点型;其他数据为整数型时,返回结果为相应的整数类型;其他数据为单精度浮点型时,返回结果为相应的单精度浮点型。
注意
在MATLAB中,单精度浮点类型不能与整数类型直接进行算术运算;例如,在命令行窗口输入:
a=uint32(1);b=single(22.809);ab=a*b;
输出结果如下:
Error using .* Integers can only be combined with integers of the same class, or scalar doubles.
下面通过示例说明浮点类型数据的相关操作。
例2-1,使用realmax和realmin函数求浮点类型数据可表达范围。
在命令行窗口输入:
str1 = '双精度浮点数的范围为:\n\t%g 到 %g\t 和 \t %g 到 %g'; sprintf(str1, -realmax, -realmin, realmin, realmax) str2 = '单精度浮点数的范围为:\n\t%g 到 %g\t 和 \t %g 到 %g'; sprintf(str2,-realmax('single'),-realmin('single'),realmin('single'),realmax('s ingle'))
得到的结果如下所示:
ans = 双精度浮点数的范围为: -1.79769e+308到 -2.22507e-308 和 2.22507e-308到 1.79769e+308 ans = 单精度浮点数的范围为: -3.40282e+38到 -1.17549e-38 和 1.17549e-38到 3.40282e+38
例2-2,查看双精度数与其他类型数的求解结果类型。
在命令行窗口输入:
a=uint32(1);b=single(1.0);c=1.0; a1=a*c;b1=b*c;c1=c*c; whos
输出结果如下所示:
Name Size Bytes Class Attributes a 1x1 4 uint32 a1 1x1 4 uint32 b 1x1 4 single b1 1x1 4 single c 1x1 8 double c1 1x1 8 double
提示
该结果表明双精度数与其他类型数的求解结果由其他数据类型决定。
由于浮点数只占用一定的存储位宽,其中只有有限位分别用来存储指数部分和小数部分,所以浮点类型能够表示的实际数值是有限且离散的,即任何两个最近相邻的浮点数之间都有间隙,而处在间隙中的数值都只能用这两个相邻的浮点数之一表示。
在MATLAB中,使用eps函数可以获取一个数值和最接近该数值的浮点数之间的间隙。
例2-3,浮点数的精度。
在命令行窗口输入:
format long;e1=eps(6), e2=eps(single(6)), format short
输出结果如下:
e1 = 8.881784197001252e-16 e2 = 4.7683716e-07
提示
MATLAB中eps可视为0,0附近的eps近似为2.2e-16,这种特殊表达在避免0作为分母时是很有用。
在MATLAB中几乎所有的计算都使用双精度浮点数,然而由于计算机所能处理的精度有限,有些时候这种局限性可能会导致错误。
例2-4,使用双精度浮点数进行计算时可能出现的错误。
在命令行窗口输入:
e1= 1 - 3*(4/3 - 1) a = 0.0;for i = 1:10,a = a + 0.1;end, e2=a-1.0 b = 1e-16 + 1 - 1e-16;c = 1e-16 - 1e-16 + 1; e3= b-c e4= (2^53 + 1) - 2^53 e5=sin(pi) % pi为圆周率在MATLAB中的表达 e6= sqrt(1e-16 + 1)-1
输出结果如下:
e1 = 2.2204e-16 e2 = -1.1102e-16 e3 = -1.1102e-16 e4 = 0 e5 = 1.2246e-16 e6 = 0
例2-4中为使用MATLAB进行计算时常见的错误用法,虽然在很多时候这样用并不会造成太大的错误,但在使用中还是应该注意并加以避免。
3.复数
复数由实部和虚部两部分构成。在MATLAB中,字符i或j默认作为虚部标志。创建复数时,可以直接按照复数形式进行输入或者利用complex函数。
关于复数的相关函数如表2.5所示。
表2.5 MATLAB中的相关函数
例2-5,复数基本操作示例。
在命令行窗口输入:
c1=complex(3,5);c2=6+2i;c=c1-c2 r1=real(c) i1=imag(c) a1=abs(c) ag1=angle(c) cn1=conj(c)
输出结果如下:
c = -3.0000 + 3.0000i r1 = -3 i1 = 3 a1 = 4.2426 ag1 = 2.3562 cn1 = -3.0000 - 3.0000i
4.无穷量(Inf)和非数值量(NaN)
MATLAB中使用Inf和-Inf分别代表正无穷量和负无穷量,NaN表示非数值量。正负无穷量一般由于运算溢出产生,非数值量则是由于类似0/0或Inf/Inf类型的非正常运算产生。
MATLAB提供Inf函数和NaN函数来创建指定数值类型的无穷量和非数值量,生成结果默认为双精度浮点类型中还有一种特殊的指数类型的数据叫作非数,通常表示运算得到的数值结果超出了运算范围。非数的实部用NaN表示,虚部用InF表示。
例2-6,无穷量及非数值量的产生和性质。
在命令行窗口中输入:
a = 0 / 0,a1=1/0, b = log( 0 ),c =exp(1000),d=NaN- NaN whos
输出结果如下:
a = NaN a1 = Inf b = -Inf c = Inf d = NaN Name Size Bytes Class Attributes a 1x1 8 double a1 1x1 8 double b 1x1 8 double c 1x1 8 double d 1x1 8 double
MATLAB将文本作为特征字符串或简单地当作字符串。这些字符串显示在屏幕上,也可以用来构成一些命令。字符串是存储在行向量中的文本,这行向量中的每一个元素代表一个字符。
实际上,元素中存放的是字符的内部代码,即ASCII码。但在屏幕上显示字符变量的值时,显示出来的是文本,而不是ASCII编码,这是因为在显示前已经对ASCII编码进行了输出处理。
字符串一般是ASCII值的数值数组,它作为字符串表达式进行显示。字符串可以通过其下标对其中的任一元素进行访问,也可以通过矩阵下标索引进行访问,但是矩阵的每行字符数必须相同。
例2-7,字符串属性示例。
在命令行窗口输入:
string ='good boy' whos s1=abs (string) s2=abs (string+'0')
输出结果如下:
string = good boy Name Size Bytes Class Attributes string 1x8 16 char s1 = 103 111 111 100 32 98 111 121 s2 = 151 159 159 148 80 146 159 169
图2.1 结构patient的示意图
MATLAB的结构与C语言类似,一个结构可以通过字段存储多个不同类型的数据。结构相当于一个数据容器,可以把多个相关联的不同类型的数据封装在一个结构对象中。
一个结构中可以具有多个字段,每个字段又可以存储不同类型的数据,这样,通过这种方式就把多个不同类型的数据组织在了一个结构对象中。
如图2.1所示,结构patient中有3个字段,姓名字段name中存储了一个字符串类型的数据;账单字段billing中存储了一个浮点数值;成绩字段test中存储了三维浮点数矩阵。
下面通过示例来说明创建、访问和连接结构对象等基本操作。
1.创建结构对象
创建结构对象的方法有两种,可以直接通过赋值语句给结构的字段赋值,也可以使用struct函数创建结构。两种方法的具体操作步骤如下:
(1)通过字段赋值创建结构
在对结构的字段进行赋值时,赋值表达式的变量名使用“结构名称.字段名称”的形式书写,对同一个结构可以进行多个字段的赋值。
例2-8,通过赋值创建结构。
在命令行窗口输入:
patient.name = 'John Doe'; patient.billing = 127.00; patient.test = [79, 75, 73; 180, 178, 177.5; 220, 210, 205]; patient whos
输出结果如下:
patient = name: 'John Doe' billing: 127 test: [3x3 double] Name Size Bytes Class Attributes patient 1x1 468 struct
例2-8中,通过对3个字段赋值,创建了结构对象patient,然后用whos函数分析出patient是一个1×1的结构数组。
提示
进行赋值操作时,对于没有明确赋值的字段,MATLAB默认赋值为空数组。通过圆括号索引进行字段赋值,还可以创建任意尺寸的结构数组。另外,同一个结构数组中的所有结构对象具有相同的字段组合。
(2)利用struct函数创建结构
例2-9,通过struct函数创建结构。
在命令行窗口输入:
patient=struct('name','John Doe','billing',127.00,'test',[79,75,73; 180,178,177.5; 220,210,205]) whos
输出结果如下:
patient = name: 'John Doe' billing: 127 test: [3x3 double] Name Size Bytes Class Attributes patient 1x1 468 struct
2.访问结构对象
通过对结构对象的字段和其在结构对象组中的位置可以访问结构对象。
例2-10,访问结构对象。
在命令行窗口输入:
patient(1)=struct('name','John Doe','billing',127.00,'test',[79,75,73;180,178,177.5; 220,210,205]); patient(2).name = ' Tim Burg '; patient(2).billing = 335.00; patient(2).test = [89, 80, 72; 183, 175, 172.5; 221, 211, 204]; p1=patient(1),p2= patient(2), p1name=patient(1).name, p2name=patient(2).name
输出结果如下:
p1 = name: 'John Doe' billing: 127 test: [3x3 double] p2 = name: 'Tim Burg' billing: 335 test: [3x3 double] p1name =John Doe p2name =Tim Burg
3.连接结构对象
使用直接连接的方式就可以将结构对象连接起来。
例2-11,连接结构对象。
在命令行窗口输入:
patient1=struct('name','John Doe','billing',127.00,'test',[79,75,73;180,178,177.5; 220,210,205]); patient2=struct('name','Tim Burg','billing',128.00,'test',[79,75,73;180,178,177.5; 220,210,205]); patient=[ patient1, patient2]; whos
输出结果如下:
Name Size Bytes Class Attributes patient 1x2 1056 struct patient1 1x1 624 struct patient2 1x1 624 struct
从结果中可以看出,patient结构对象由patient1和patient2连接而成。
单元数组(Cell Arrays)是一种广义矩阵。每一个单元可以包括一个任意数组,如数值数组、字符串数组、结构体数组或另外一个单元数组,因而每一个单元可以具有不同的尺寸和内存占用空间。
1.创建单元数组
单元数组的创建有两种方法:通过赋值语句或cell函数创建。
(1)使用赋值语句创建单元数组:单元数组使用花括号“{}”来创建,使用逗号“,”或空格分隔单元,使用分号“;”来分行。
(2)使用cell函数创建空单元数组。
例2-12,创建单元数组。
在命令行窗口输入:
A= {'x',[2;3;6];10,2*pi} B = cell(2,2) whos
输出结果如下:
A = 'x' [3x1 double] [10] [ 6.2832] B = [] [] [] [] Name Size Bytes Class Attributes A 2x2 282 cell B 2x2 16 cell
提示
使用cell函数创建空单元数组主要是为该单元数组预先分配连续的存储空间,提高执行效率。
2.访问单元数组
在单元数组中,单元和单元中的内容属于不同范畴,这意味着寻访单元和单元中的内容是两个不同的操作。MATLAB为上述两种操作设计了相对应的操作对象:单元外标识(cell indexing)和单元内编址(content indexing)。
单元外标识使用圆括号进行操作,对于单元数组C,C(m,n)指的是单元数组中第m行第n列的单元;单元内编址使用大括号进行操作,对于单元数组C,C{m,n}指的是单元数组中第m行第n列的单元中的内容。
例2-13,单元数组的访问。
在命令行窗口输入:
A= {'x',[2;3;6];10,2*pi}; b= A(1,2) C=A{1,2}
输出结果如下:
b = [3×1 double] C = 2 3
3.单元数组的操作
单元数组的操作包括:合并、删除单元数组中的指定单元和改变单元数组的形状等。
(1)单元数组的合并
例2-14,单元数组的合并。
在命令行窗口输入:
A= {'x',[2;3;6];10,2*pi}; B= {'Jan'} C = {A B} whos
输出结果如下:
B = 'Jan' C = {2x2 cell} {1x1 cell} Name Size Bytes Class Attributes A 2x2 282 cell B 1x1 66 cell C 1x2 468 cell
(2)删除单元数组中指定单元
如果要删除单元数组中指定的某个单元,只需要将空矩阵赋给该单元,即:C{ m,n} = []。
例2-15,删除单元数组中指定单元。
在命令行窗口输入:
A= {'x',[2;3;6];10,2*pi}; A{ 1,2}=[];A1=A whos
输出结果如下:
A1 =' x' [] [10] [6.2832] Name Size Bytes Class Attributes A 2x2 258 cell A1 2x2 258 cell
(3)使用reshape函数改变单元数组的形状。
例2-16,改变单元数组的形状。
在命令行窗口输入:
A= {'x',[2;3;6];10,2*pi} newA = reshape(A,1,4) whos
输出结果如下:
A = 'x' [3x1 double] [10] [ 6.2832] newA = 'x' [10] [3x1 double] [6.2832] Name Size Bytes Class Attributes A 2x2 282 cell newA 1x4 282 cell
在MATLAB中,可以实现对函数的间接调用,这归功于函数句柄提供了一种间接调用函数的方法。
创建函数句柄需要使用到操作符@,对MATLAB库函数中提供的各种M文件中的函数和使用者自主编写的程序中的内部函数,也都可以创建函数句柄,进而通过函数句柄来实现对这些函数的间接调用。
创建函数句柄的一般句法格式为:
Function_Handle = @Function_Filename;
其中,
例2-17,函数句柄的创建与调用。
在命令行窗口输入:
F_Handle = @sin x = 0 : 0.25 * pi : pi; F_Handle( x ) %通过函数句柄调用函数
输出结果如下:
F_Handle = @sin ans = 0 0.7071 1.0000 0.7071 0.0000
MATLAB库函数提供了大量处理函数句柄的操作函数,将函数句柄的功能与其他数据类型联系起来;这扩展了函数句柄的应用。函数句柄的简单操作函数如表2.6所示。
表2.6 函数句柄的操作函数
例2-18,函数句柄的基本操作。
在命令行窗口输入:
F_Handle=@sin f1=functions( F_Handle ) t= func2str(F_Handle) F_Handle1 = str2func(t) f2=functions( F_Handle1)
输出结果如下:
F_Handle = @sin f1 = function: 'sin' type: 'simple' file: '' t = sin F_Handle1 = @sin f2 = function: 'sin' type: 'simple' file: ''
映射容器(Map Containers,也叫Map对象)可以将一个量映射到另一个量。例如,将一个字符串映射为一个数值,则相应字符串就是映射的键(key),相应值就是映射的数据(value)。可以将Map容器理解为一种快速键查找数据结构。
对一个Map元素进行寻访的索引称为“键”,一个“键”可以是以下任何一种数据类型:
(1)1×N字符串;
(2)单精度或双精度实数标量;
(3)有符号或无符号标量整数。
键和其对应的数据存储在映射容器中,存在一一对应的关系。映射容器p中存储的数据可以是任何类型,包括数值类型、字符或字符串类型、结构体类型、单元类型或其他映射容器。
单个映射容器对象是MATLAB Map类的对象。Map类的所有对象具有3种属性,如表2.7所示。用户不能直接对这些属性进行修改,但可以通过Map类操作函数来进行修改。
表2.7 Map类的属性
属性的查看方法为:Map名+“.”+Map的属性名。例如,为了查看mapObj对象包括的数据类型,可以使用:
mapObj.ValueType
下面将讨论Map对象的创建、读取和编辑等内容。
1.创建Map对象
Map构造方法如下:
mapObj = containers.Map({key1,key2,…},{val1,val2,…})
当键和值是字符串时,需要对上述语法稍作变更,即
mapObj = containers.Map({'keystr1','keystr2',…},{val1,val2,…})
例2-19,创建Map对象。
在命令行窗口输入:
k = {'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec', 'Annual'}; v = {327.2, 368.2, 197.6, 178.4, 100.0, 69.9, 32.3, 37.3, 19.0, 37.0, 73.2, 110.9, 1551.0}; rainfallMap = containers.Map(k, v) whos rainfallMap
输出结果如下:
rainfallMap = containers.Map handle Package: containers Properties: Count: 13 KeyType: 'char' ValueType: 'double' Methods, Events, Superclasses Name Size Bytes Class Attributes rainfallMap 13x1 60 containers.Map
此外,Map对象的创建可以分为两个步骤:首先创建一个空Map对象;然后使用keys和Value方法对其进行内容补充。空Map对象的创建方法如下:
newMap = containers.Map()
输入上述命令,得到的结果如下所示:
newMap = containers.Map handle Package: containers Properties: Count: 0 KeyType: 'char' ValueType: 'any' Methods, Events, Superclasses
2.查看和读取Map对象
Map对象中的每个条目包括两个部分:唯一的键及其对应的值。可以通过使用keys函数查看Map对象中包含的所有键;通过values函数查看所有的值。
例2-20,查看Map对象。
在命令行窗口输入:
k = {'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec', 'Annual'}; v = {327.2, 368.2, 197.6, 178.4, 100.0, 69.9, 32.3, 37.3, 19.0, 37.0, 73.2, 110.9, 1551.0}; rainfallMap = containers.Map(k, v); kv=keys(rainfallMap) vv=values(rainfallMap)
输出结果如下:
kv = 'Annual' 'Apr' 'Aug' 'Dec' 'Feb' 'Jan' 'Jul' 'Jun' 'Mar' 'May' 'Nov' 'Oct' 'Sep' vv = [1551] [178.4000] [37.3000] [110.9000] [368.2000] [327.2000] [32.3000] [69.9000] [197.6000] [100] [73.2000] [37] [19]
用户可以对Map对象进行数据的寻访。寻访指定键(keyName)所对应的值(valueName)使用的格式如下:
valueName = mapName(keyName)
当键名是一个字符串时,需使用单引号将键名括起来。
例2-21,Map对象数据寻访。
在命令行窗口输入:
k = {'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec', 'Annual'}; v = {327.2, 368.2, 197.6, 178.4, 100.0, 69.9, 32.3, 37.3, 19.0, 37.0, 73.2, 110.9, 1551.0}; rainfallMap = containers.Map(k, v); v5= rainfallMap ('May')
输出结果如下:
v5 = 100
如果需要对多个键进行访问,可以使用values函数,例如输入:
vs=values(rainfallMap, {'Jan', 'Dec', 'Annual'})
得到的结果为:
vs = [327.2000] [110.9000] [1551]
注意
在对多个键进行访问时,不能像在其他数据类型中那样使用冒号“:”,否则将导致错误的产生。
3.编辑Map对象
(1)删除keys/values对
可以使用remove函数从Map对象中删除keys/values对。
例2-22,删除keys/values对。
在命令行窗口依次输入:
k = {'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun'}; v = {327.2, 368.2, 197.6, 178.4, 100.0, 69.9}; rainfallMap = containers.Map(k, v); remove(rainfallMap, 'Jan'); ks=keys(rainfallMap) vs=values(rainfallMap)
得到的结果为:
ks = 'Apr' 'Feb' 'Jun' 'Mar' 'May' vs = [178.4000] [368.2000] [69.9000] [197.6000] [100]
(2)添加keys/values对
可以直接向Map对象中删除keys/values对。
例2-23,添加keys/values对。
在命令行窗口依次输入:
k = {'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun'}; v = {327.2, 368.2, 197.6, 178.4, 100.0, 69.9}; rainfallMap = containers.Map(k, v); rainfallMap('Jul')=33.3; ks=keys(rainfallMap) vs=values(rainfallMap)
得到的结果如下:
ks = 'Apr' 'Feb' 'Jan' 'Jul' 'Jun' 'Mar' 'May' vs = [178.4000] [368.2000] [327.2000] [33.3000] [69.9000] [197.6000] [100]
(3)修改keys与values
如果在需要值不变的情况下对键名进行更改,首先要删除键名和对应的值,然后再添加一个有正确键名的新条目。通过赋值操作,覆盖原有的值,即可对Map对象中的值进行修改。
例2-24,修改keys与values。
在命令行窗口输入:
k = {'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun'}; v = {327.2, 368.2, 197.6, 178.4, 100.0, 69.9}; rainfallMap = containers.Map(k, v); remove(rainfallMap, 'Jan'); rainfallMap('JAN')= 327; rainfallMap(' Mar ')=33.3; ks=keys(rainfallMap) vs=values(rainfallMap)
程序运行结果为:
ks = ' Mar ' 'Apr' 'Feb' 'JAN' 'Jun' 'Mar' 'May' vs = [33.3000] [178.4000] [368.2000] [327] [69.9000] [197.6000] [100]
数据类型识别用以确定变量的数据类型,常用到的函数如表2.8所示。
表2.8 数据类型识别函数
MATLAB提供了如表2.9所示的函数用以完成不同数据类型间的转换。
表2.9 数据类型转换函数
(续表)
例2-25,将字符串数转换为浮点数。
在命令行窗口输入:
c = {'37.294e-1'; '-58.375'; '13.796'} d = str2double(c)
得到的结果为:
c = '37.294e-1' '-58.375' '13.796' d = 3.7294 -58.3750 13.7960
MATLAB中的运算符分为算术运算符、关系运算符和逻辑运算符三种。这三种运算符可以分别使用,也可以同时出现。在同一运算式中同时出现两种或两种以上运算符时,运算按优先级顺序进行:算术运算符优先级最高,其次是关系运算符,最低级别是逻辑运算符。
MATLAB中的算术运算符有四则运算符和带点四则运算符等,相关运算法则如表2.10所示。
表2.10 MATLAB中的算术运算符
例2-26,数值与矩阵的算术运算示例。
在命令行窗口输入:
A =2* eye(2), B = ones(2), C = A * B, D = A .* B, E=A.^2
输出结果如下:
A = 2 0 0 2 B = 1 1 1 1 C = 2 2 2 2 D = 2 0 0 2 E = 4 0 0 4
MATLAB带有6个关系运算符,其运算法则如表2.11所示。
表2.11 MATLAB中的关系运算符
‘==’和‘=’的区别在于:‘==’的运算法则是比较两个变量,当它们相等时返回1,当它们不相等时返回0;而‘=’则是被用来赋值的。
表中的运算符可以用来对数值、数组、矩阵或是字符串等数据类型进行比较,也可以进行不同类型两个数据之间的比较。
比较的方式根据所比较的两个数据类型的不同而不同,例如对矩阵与一个标量进行比较时,即将矩阵中的每个元素与标量进行比较;而将结构相同的矩阵进行比较时,则将矩阵中的元素相互比较:关系运算符比较对应的元素,产生一个仅包含1和0的数值或矩阵。其元素代表的意义如下:
例2-27,关系运算符运算。
在命令行窗口输入:
A=1:5, B=6-A TrueorFalse1 = ( A>4 ) TrueorFalse2 = ( A==B ) TrueorFalse3 = ( A>B )
输出结果如下:
A = 1 2 3 4 5 B = 5 4 3 2 1 TrueorFalse1 = 0 0 0 0 1 TrueorFalse2 = 0 0 1 0 0 TrueorFalse3 = 0 0 0 1 1
逻辑运算符提供组合或否定关系表达方法。MATLAB逻辑运算符如表2.12所示。
表2.12 MATLAB中的逻辑运算符
例2-28,逻辑运算符的运用。
在命令行窗口输入:
A=1:5, B=6-A TrueorFalse1 =~ ( A>4 ) TrueorFalse2 =(A>1)&(A<5) TrueorFalse3 =(A>3)|(B>3)
输出结果如下:
A = 1 2 3 4 5 B = 5 4 3 2 1 TrueorFalse1 = 1 1 1 1 0 TrueorFalse2 = 0 1 1 1 0 TrueorFalse3 = 1 1 0 1 1
逻辑运算符与关系运算符一样可以进行矩阵与数值之间的比较,方式为将矩阵的每一个元素都与数值进行比较,比较结果为相同维数的矩阵,矩阵的每一个元素都代表比较矩阵中相同位置上的元素与数值的逻辑运算结果。
使用逻辑运算符比较两个相同维数的矩阵时,按元素来进行比较,其结果是一个包含1和0的矩阵。0元素表示逻辑为假,1元素表示逻辑为真。
除了上面的逻辑运算符,MATLAB还提供了各种逻辑函数,如表2.13所示。
表2.13 MATLAB部分逻辑函数
MATLAB中具体的运算优先级排列如表2.14所示。在表达式中,算术运算符优先级最高,其次是关系运算符,最后是逻辑运算符。需要时,可通过加括号来改变运算顺序。
表2.14 运算符优先级
注:表中优先级数值越小则优先级别越高。在表达式的书写中,建议采用括号的方式明确运算的先后顺序。
MATLAB提供了大量的字符串函数,如表2.15所示。
表2.15 字符串相关函数
字符串或字符串数组的构造可以通过直接给变量赋值来实现,字符串的内容需要写在单引号内;如果字符串的内容包含单引号,则需要以两个重复的单引号来表示。
构造多行字符串时,如果字符串内容写在[]内,那么多行字符串的长度必须相同;如果字符串内容写在{}内,则字符串的长度可以不同。
例2-29,直接赋值构造字符串。
在命令行窗口输入:
Str1='How are you?', Str2='Fine, thank you.', Str = strcat( Str1, Str2) Str_mat1 = {'July';'August';'September';} Str_mat2 = ['July';'August';'September';]%将报错,如结果输出部分
输出结果如下:
Str1 =How are you? Str2 =Fine, thank you. Str =How are you?Fine, thank you. Str_mat1 = 'July' 'August' 'September Error using vertcat Dimensions of matrices being concatenated are not consistent
MATLAB还提供了strvcat函数和char函数用于纵向连接多个字符串。
strvcat函数连接多行字符串时,每行字符串的长度不要求相等,所有非最长字符串的右边会自动补偿空格,使每行字符串的长度相同。
char函数与strvcat函数类似,不过当多行字符串中有空字符串时,strvcat函数会自动进行忽略,而char函数会把空字符串也用空格补偿后,再进行连接。
例2-30,连接字符串示例。
在命令行窗口输入:
A='Top'; B='Middle'; C='Bottom'; CAT1=strvcat(A,B,C),CAT2=char(A,B,C),size=[size(CAT1);size(CAT2)]
输出结果如下:
CAT1 = Top Middle Bottom CAT2 = Top Middle Bottom size = 3 6 3 6
有时需要比较两个字符串之间的关系,可以通过关系运算符,也可以使用strcmp函数来比较两个字符串。
例2-31,比较字符串。
在命令行窗口输入:
A1 = ('Hello' == 'World') B1 = ('Hello' == 'Hello') A2 = strcmp('Hello', 'World') B2 = strcmp('Hello', 'Hello')
输出结果如下:
A1 = 0 0 0 1 0 B1 = 1 1 1 1 1 A2 = 0 B2 = 1
注意
使用关系运算符进行比较时,返回值是一个与字符串长度相同大小的数组,这时要求被比较的两个字符串的长度必须相同;而strcmp函数则是判断两个字符串是否相同,无被比较的两个字符串的长度必须相同的要求,返回值为数值0或1。
通过findstr函数可以实现字符串的查找与搜索。
通过对字符串数组中相应的元素直接赋值可以实现字符串的替换,也可以使用strrep函数来实现字符串的替换。
例2-32,查找与替换字符串示例。
在命令行窗口输入:
string =' You smile like sunshine. ' ; spacePos=findstr(string,' ') %搜索字符串内的空格位置 ePos= findstr(string,'e') %搜索字母e ouPos= findstr(string,'ou') %搜索字符串ou dstring=' We smile like sunshine. ' idstring= strrep( string, ' You', 'We')
输出结果如下:
spacePos = 1 5 11 16 26 ePos = 10 15 24 ouPos = 3 dstring = We smile like sunshine. idstring =We smile like sunshine.
注意
MATLAB还提供了大量字符串与各种数据类型之间的转换函数,如表2.16所示。
表2.16 字符串类型与数据类型转换函数
例2-33,将数字转换成字符串示例。
在命令行窗口输入:
r=4; a=pi*r^2; string =[' A circle of radius ' num2str(r) ' has an area of ' num2str(a) ' . ' ] ; disp(string)
输出结果如下:
A circle of radius 4 has an area of 50.2655 .
矩阵的基本操作主要包括构造矩阵、改变矩阵维度与矩阵大小、矩阵索引、获取矩阵属性信息等。MATLAB提供了相应的命令或相应的库函数与各操作对应。
有关矩阵的概念,可以参考有关的数学书籍,这里不再赘述。但向量其本质上是一维的矩阵,在使用MATLAB进行科学计算时,基本不区分矩阵与向量,因此需要注意。
数组是在程序设计中,把具有相同类型的若干变量按有序的形式组织起来的一种形式,这些按序排列的同类数据元素的集合称为数组。
矩阵和数组在MATLAB中的区别主要表现在两方面:
两者的联系主要体现在,矩阵是以数组的形式存在的,一维数组相当于向量,二维数组相当于矩阵,可将矩阵视为数组的子集。
矩阵可以通过两种方式创建:
表2.17 特殊矩阵的创建函数
注:k=0为主对角线;k< 0为下第k对角线;k> 0为上第k对角线。
下面介绍简单矩阵和特殊矩阵的创建方法。
1.创建简单矩阵
采用矩阵构造符号——方括号“[]”,将矩阵元素置于方括号内,同行元素之间用空格或逗号来隔开;行与行之间用分号“;”隔开。
例2-34,创建简单矩阵示例。
在命令行窗口输入命令:
A = [1,2,3;4,6,8] % 逗号和分号的使用构造矩阵 B = [2 3 4;3 2 1] % 空格和分号的使用构造矩阵 V1 = [6,9,12,3] % 构造行向量 V2 = [1;8] % 构造列向量
程序运行过程中的输出为:
A = 1 2 3 4 6 8 B = 2 3 4 3 2 1 V1 = 6 9 12 3 V2 = 1 8
2.创建特殊矩阵
使用表中命令可以创建特殊矩阵。
例2-35,创建特殊矩阵示例。
在命令行窗口输入:
OnesMat= ones(2) ZerosMat= zeros(2) IdenMat = eye(2) IdenMat23 = eye(2, 3) IdenMat32 = eye(3, 2)
输出结果如下:
OnesMat = 1 1 1 1 ZerosMat = 0 0 0 0 IdenMat = 1 0 0 1 IdenMat23 = 1 0 0 0 1 0 IdenMat32 = 1 0 0 1 0 0
3.创建空矩阵
可以使用[]代表空矩阵,通过直接赋值的方法来创建空矩阵。
矩阵大小和结构可以改变,实现的方式主要有旋转矩阵、改变矩阵维度、删除矩阵元素等。MATLAB提供的此类函数如表2.18所示。
表2.18 矩阵结构改变函数
(续表)
例2-36,矩阵的旋转与维度的改变。
在命令行窗口输入:
A = [1,2,3;4,6,8] B= reshape(A, 2, 3) C= fliplr(A ) D= rot90(A) E= repmat(A,[1 2])
输出结果如下:
A = 1 2 3 4 6 8 B = 1 2 3 4 6 8 C = 3 2 1 8 6 4 D = 3 8 2 6 1 4 E = 1 2 3 1 2 3 4 6 8 4 6 8
矩阵元素索引可分为双下标索引和单下标索引。
下面介绍访问矩阵元素的具体方法。
1.矩阵下标引用
常用的矩阵索引表达式如表2.19所示。
表2.19 矩阵的索引表达式
例2-37,矩阵下标的引用示例。
在命令行窗口输入:
M= magic(5) , SubM = M( 2:3, 3:4 ), AM = M ( [7:8 16:18] )
输出结果如下:
M = 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 SubM = 7 14 13 20 AM =5 6 8 14 20
2.引用转换
矩阵中某一元素的单下标索引值和双下标索引值之间,可以通过sub2ind函数进行转换。
例2-38,单双下标索引值转换示例。
在命令行窗口输入:
ind = sub2ind([3 4], 1,3), [I J]= ind2sub([3 4], 7)
输出结果如下:
ind = 7 I = 1 J = 3
3.访问多个矩阵元素
例2-39,访问多个矩阵元素示例。
在命令行窗口输入:
A=magic(3) A1= A(1:2:9) A2= A(1:3,1:2)
输出结果如下:
A = 8 1 6 3 5 7 4 9 2 A1 =8 4 5 6 2 A2 =8 1 3 5 4 9
矩阵的信息主要包括矩阵结构、矩阵大小、矩阵维度、矩阵的数据类型及内存占用等。
1.矩阵结构
矩阵的结构是指矩阵子元素的排列方式。MATLAB提供了如表2.20所示结构判断函数,这类函数的返回值是逻辑类型的数据:返回值为“1”表示该矩阵是特定类型的矩阵;返回值为“0”表示该矩阵不是该特定类型的矩阵。
表2.20 矩阵结构判断函数
例2-40,矩阵结构判断函数的使用方法示例。
在命令行窗口输入:
A=magic(3); p1=isempty(A) % 判断矩阵A是否为空矩阵 p2=isscalar(A) % 判断矩阵A是否为标量 p3=isvector(A) % 判断矩阵A是否为向量 p4=issparse(A) % 判断矩阵A是否为稀疏矩阵
输出结果如下:
p1 = 0 p2 = 0 p3 = 0 p4 = 0
2.矩阵大小
矩阵的形状信息通常包括:
MATLAB提供了4个函数,分别用于获取矩阵形状以上三方面的相关信息,如表2.21所示。
表2.21 矩阵形状信息查询函数
例2-41,矩阵形状信息查询函数的使用示例。
在命令行窗口输入:
X=[magic(3) [1 1 1]'] nd=ndims(X) [r,c]=size(X) l=length(X) n=numel(X)
输出结果如下:
X = 8 1 6 1 3 5 7 1 4 9 2 1 nd =2 r = 3 c = 4 l = 4 n = 12
3.矩阵维度
MATLAB将空矩阵、标量矩阵、一维矩阵和二维矩阵都作为普通二维数组对待,并提供ndims函数计算矩阵维度。
例2-42,矩阵维度示例。
在命令行窗口输入:
A = []; B = 5; C = 1:3; D = zeros(2); E(:,:,2) = [1 2; 3 4]; Nd= [ndims(A) ndims(B) ndims(C) ndims(D) ndims(E)]
输出结果如下:
Nd = 2 2 2 2 3
4.矩阵数据类型
矩阵的元素可以使用各种各样的数据类型,对应不同数据类型的元素,可以是数值、字符串、单元数组、结构等。
MATLAB中提供了一系列关于数据类型的判断函数,如表2.22所示。这类函数的返回值是逻辑类型数据:返回值为“1”表示是某一特定的数据类型;返回值为“0”表示不是该特定的数据类型。
表2.22 矩阵数据类型的测试函数
例2-43,矩阵元素的数据类型的判断示例。
在命令行窗口输入:
A =[magic(3) [1 1 1]']; p1=isnumeric(A) p2=isfloat(A) p3=islogical(A)
得到的结果为:
p1 = 1 p2 = 1 p3 = 0
5.矩阵占用的内存
可以通过whos命令查看当前工作区中的指定变量的所有信息,包括变量名、矩阵大小、内存占用和数据类型等。
例2-44,查看矩阵占用的内存示例。
在命令行窗口输入:
Matrix = rand(3); whos Matrix
输出结果如下:
Matrix = 0.2551 0.6991 0.5060 0.8909
在命令行窗口输入:
whos Matrix
输出结果如下:
Name Size Bytes Class Attributes Matrix 3x3 72 double
本章中涉及的基础知识包括:MATLAB数据类型、MATLAB运算符与运算、字符串处理、矩阵基础知识,这些知识的学习旨在建立起对MATLAB的基础认识。在接下来的章节里,将应用这些知识来深入学习MATLAB。