图

Matlab 的变量与矩阵

预备知识 Matlab 简介, 自然对数底, 矩阵

变量与矩阵

   变量(variable)可用于储存数据并通过变量名获取变量值.变量名可以由多个字母,数字和下划线组成. 注意变量名区分大小写,且首字符只能是字母. 合法的变量名如 iia3odd_numberevenNumber. 用等号可以对变量赋值, 被赋值的变量放在等号左边, 等号右边的表达式的运算结果会储存在被赋值的变量中, 直到再次被赋值. 表达式由若干变量, 常数和算符组成. 注意同一个变量可以出现在等号左边以及右边的表达式中.

1
2
3
4
>> a = 1.2/3.4 + (5.6+7.8)*9 -1
a = 119.9529
>> a = atan(a + 1)
a = 1.5625
如果新的变量第一次被赋值,它会自动出现在 Workspace 窗口中.注意 Workspace 中的一个特殊的变量 ans,如果命令的输出结果没有赋值给变量,就会自动赋值给 ans.注意一般不要对 ans 赋值. 另外两个特殊的变量是 pi (圆周率)和 i (虚数单位), 一般也不要对他们赋值. 自然对数底没有对应的变量, 若要使用自然对数底, 用 exp(1) 即可.

   另外,如果在命令后面加分号(semicolon)“ ;”,则命令执行后不输出结果.也可以用分号把多个命令写到一行.

1
2
>> 1 + 1; a = ans^2
a = 4
用 Editor 编写程序时,每个命令后面都需要加分号, 需要在 Command Window 输出时, 用 disp 函数.
1
2
3
>> disp('something'); disp(10);
something
10

   clear 命令可以清空 Workspace 中的所有变量,用 clear <var1>,<var2> ... 清除指定的变量(<var1>,<var2>是变量名).用 clc 命令可以清空 Command Window (按上箭头仍然可以查看历史命令).

   本书只涉及到 3 种变量类型(class)双精度(double)字符(char)逻辑(logical).

双精度变量

   双精度变量用于储存数值,有效数字约为 16 位(如果是复数,实部和虚部各 16 位),取值范围约为 $10^{-308}$ 到 $10^{308}$. 如无变量类型声明,所有命令中出现的常数及储存数值的变量都为 double

   Matlab 中的所有变量都可以理解为矩阵,单值变量(标量, scalar)可以理解为 1×1 的矩阵,只有一行或一列的矩阵叫做行矢量(row vector)列矢量(column vector).一些简单的矩阵操作如下

1
2
>> a = [1,2,3]
a = 1  2  3
用方括号创建矩阵,用逗号分隔每行的矩阵元,行矢量中逗号可省略
1
2
>> a = [1 2 3]
a = 1  2  3
用分号分隔行
1
2
3
4
5
6
7
8
9
10
>> b = [1;2;3]
b =
    1
    2
    3
>> c = [1 2 3; 2 3 4; 3 4 5]
c =
    1  2  3
    2  3  4
    3  4  5
方括号还可以用来合并矩阵(注意矩阵尺寸必须合适)
1
2
3
4
5
6
7
>> d = [a; a]
d =
    1  2  3
    1  2  3
>> e = [a a]
e =
    1  2  3  1  2  3
size 函数获取矩阵尺寸, 如果使用两个输入变量, 则第二个用于指定维度(行是第一个维度, 列是第二个). 用 numel 函数获取矩阵元个数.
1
2
3
4
5
6
>> size(d)
ans = 2  3
>> size(d,1)
ans = 2
>> numel(d)
ans = 6
zeros 函数生成全零矩阵
1
2
3
4
>> zeros(2,3)
ans =
    0  0  0
    0  0  0
zeros([2,3])zeros(size(d)) 结果也相同.用 ones 可以生成全 1 矩阵,也可以乘以任意常数
1
2
3
4
>> ones(2,3)*5
ans =
    5  5  5
    5  5  5
eye(N) 生成 N×N 的单位矩阵. 用 rand(M,N) 生成随机矩阵,矩阵元从 0 到 1 均匀分布, 如果不提供输入变量, rand 相当于 rand(1,1). 用 M:step:N 生成等差数列(行矢量),例如
1
2
3
4
5
6
>> 1:2:10
ans = 1  3  5  7  9
>> 0:pi/3:pi*2
ans = 0  1.0472  2.0944  3.1416  4.1888  5.2360  6.2832
>> 10:-2:1
ans = 10  8  6  4  2
如果只用一个冒号, 那么间隔默认为 1
1
2
>> 1:3
ans = 1  2  3
linspace(x1,x2,Nx) 生成指定首项尾项和项数的等差数列(行矢量)
1
2
>> linspace(0,pi,4)
ans = 0  1.0472  1.2566  2.0944  3.1416

   下面介绍矩阵运算.形状相同的矩阵可以进行 +- 运算,矩阵和标量也可以, 结果是把每个矩阵元加(减)标量;矩阵乘法“*”既可以把常数与矩阵相乘,也可以进行数学上的矩阵乘法;矩阵的幂“^”相当于矩阵与自己多次相乘;“/”可以把矩阵除以一个常数.

1
2
3
4
5
6
7
8
9
>> a = [1 2; 3 4]; b = [1 -1; 2 -2];
>> a + b
ans =
    2  1
    5  2
>> a * b
ans =
    5  -5
    11  -11
若两个矩阵尺寸相同,可进行逐个元素运算, 如
1
2
3
4
>> a .* b
ans =
    1  -2
    6  -8
这里把 a 的每个矩阵元和 b 的对应矩阵元相乘, 得到新矩阵的对应矩阵元. 为了区分矩阵乘法, 需要在乘号前面加一个英文句号. 类似地, 我们也可以进行逐个元素的除法运算(“./”)和幂运算(“.^”).
1
2
3
4
5
6
7
8
>> a ./ b
ans =
    1.0000  -2.0000
    1.5000  -2.0000
>> a.^2
ans =
    1  4
    9  16

   逐个元素运算也可以用于一些尺寸不同的情况, 例如对 2×3 的矩阵与 2×1 的矢量进行逐个元素运算, 相当于将后者复制成 2×3 的矩阵再进行运算. 又例如 1×3 的矢量与 2×1 的矢量进行逐个元素运算, 相当于把两个矢量都复制成 2×3 的矩阵再进行运算. 再例如一个标量和一个矩阵做逐个元素运算相当于把标量复制成同尺寸的矩阵再进行运算.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
>> m1 = [1 3 5; 2 4 6]; m2 = [1; 2];
>>  m1.*m2
ans =
    1  3  5
    4  8  12
>> m1 = [1, 2, 3]; m2 = [2; 3];
>> m1 + m2
ans =
    3  4  5
    4  5  6
>> a = [1 2; 3 4];
>> 24./a
ans =
    24  12
    8    6

   单引号“'”可以使实数矩阵转置,或使复矩阵取厄米共轭(即转置并取复共轭).若只需要对复矩阵转置,用“.'”即可.

1
2
3
4
5
6
7
8
9
10
11
12
>> c = a + 1i*b
c =
    1.0000 + 1.0000i  2.0000 - 1.0000i
    3.0000 + 2.0000i  4.0000 - 2.0000i
>> c'
ans =
    1.0000 - 1.0000i  3.0000 - 2.0000i
    2.0000 + 1.0000i  4.0000 + 2.0000i
>> c.'
ans =
    1.0000 + 1.0000i  3.0000 + 2.0000i
    2.0000 - 1.0000i  4.0000 - 2.0000i
使用 fliplrflipud 函数可以分别把矩阵左右翻转和上下翻转, 例如
1
2
3
4
5
6
7
8
>> fliplr(a)
ans =
    2  1
    4  3
>> flipud(a)
ans =
    3  4
    1  2

   用 sum 函数可以分别求矩阵每列或每行的和. 当矩阵为行矢量或列矢量时, sum 对所有矩阵元求和. 其他情况下, sum 默认对每列求和, 若想对每行求和, 可以在第二个输入变量中输入 2 (行是矩阵的第二个维度). 例如

1
2
3
4
5
6
7
>> a = [1,2; 3,4];
>> sum(a)
ans = 4  6
>> sum(a,2)
ans =
    3
    7
mean 函数可以求平均值, 使用格式与 sum 相同.

   给 norm 函数输入一个行矢量或列矢量时, 得到该矢量的模长(即各矢量元的平方和再开根号).

   用 det 函数可以求方阵的行列式, 用 “\” 算符可以解线性方程组 $\mat A \bvec x = \bvec b$. 如1

1
2
3
4
5
6
7
8
9
10
>> A = [1,2; 3,4]; det(A)
ans = -2
>> x = [-1; 1]; b = A*x
b =
    1
    1
>> A \ b
ans =
    1
    -1

   Matlab 自带的数学函数一般支持矩阵自变量,结果是该函数对每个矩阵元分别运算. 这样的函数叫做矢量化(vectorized)的函数.

1
2
3
>> cos(0:pi/4:pi)
ans =
1.0000  0.7071  0.0000  -0.7071  -1.0000
用矢量化的运算可以使代码简短易懂,且提高计算效率(因为只需要进行一次函数调用).

矩阵索引

   矩阵索引 用于表示矩阵部分矩阵元,例如

1
2
3
4
5
6
7
>> a = [1 2 3; 4 5 6; 7 8 9];
ans =
    1  2  3
    4  5  6
    7  8  9
>> a(1,2)
ans = 2
索引括号中的两个数或变量分别代表行标和列标, 也可以是矩阵, 例如
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
>> a(2:3,1)
ans =
    4
    7
>> a(2:3,1:2)
ans =
    4  5
    7  8
>> a([3,2],[1,2])
ans =
    7  8
    4  5
>> a(:,2)
ans =
    2
    5
    8
>> a(1:end-1,2:3)
ans =
    2  3
    5  6
其中单独一个冒号表示某个维度的全部索引, end 表示某维度的最大索引. 注意索引不仅可以用来取值,还可以放在等号左边赋值.
1
2
3
4
5
>> b = a; b(1:3) = a(2:4)
b =
    4  2  3
    7  5  6
    2  8  9
要求左边的矩阵元个数等于右边.唯一的例外是当右边为标量
1
2
3
4
5
b(1:3) = 0
b =
    0  2  3
    0  5  6
    0  8  9
我们还可以用单个索引
1
2
3
4
>> a(2:5)
ans = 4  7  2  5
>> a(7:end)
ans = 3  6  9
注意单个索引的顺序是先增加第一个维度(行标),再增加第二个维度(列标). 虽然上面都是以双精度矩阵为例, 但这些索引方法适用于任何数据类型的矩阵.

字符变量

   字符型变量一般用于控制行输出结果或对生成的图片进行标注.把 N 个字符放在一对单引号内,可生成 1×N 的字符类型数组.

1
2
3
4
5
>> str1 = '这是一个字符串'; str2 = 'this is a string';
>> [str1, ',' , str2]
ans = '这是一个字符串, this is a string'
>> numel(ans)
ans = 24
把双精度类型变为字符串可以用 num2str 函数(注意 2 的英文读音与“to”相同, num 代表“number”, str 代表字符串“string”),通常用于与其他字符矩阵合并,如
1
2
>> number = 3; str = ['The number is', num2str(number), '.']
str = 'The number is 3.'
若要在字符串中加入英文单引号,可用两个英文单引号表示.

逻辑变量

   逻辑变量只能具有 01 两个值,分别代表假(false)真(true). 以下算符

1
>,>=(大于等于),<,<=,==(等于), ~= (不等于)
可用于比较双精度数组,返回逻辑型数组
1
2
>> L = 1 + 1 > 3
L = logical 0

   逻辑“与”,“或”,“非”算符分别为(仅用于逻辑标量)&&,||,\texttilde. 当算符两边都为真时,与运算才能为真, 若至少有一边为真,或运算就为真. 非运算用于把真假互换. 例如

1
2
3
4
5
6
>> 1 > 0 && 2 > 1
ans = logical 1
>> 1 > 0 || 2 < 1
ans = logical 1
>> ~ (1 > 0)
ans = logical 0
注意由于非运算的优先级比 > 运算要高, 所以最后一条命令必须要加括号.

   在需要的时候, 双精度变量可以自动转换为逻辑变量, 规则是只有双精度的 0 转换为逻辑 0, 其他双精度值一律转换为逻辑 1. 如

1
2
>> 1.3 && -0.8
ans = logical 1
其中 1.30.8 分别转换为逻辑 1, 然后进行与运算得到逻辑 1

   除了上文中介绍的索引方法外, 我们还可以用相同大小逻辑数组索引任意矩阵. 注意逻辑索引的输出结果是一个列矢量, 以下为了节约空间我们将输出结果改为行矢量.

1
2
3
>> a = [1 2 3; 4 5 6; 7 8 9];
>> mark = logical([1 0 0; 0 0 1; 1 0 0]); a(mark)
ans = 1  7  6 % 列矢量
逻辑索引常见的例子如
1
2
>> a(a <= 4)
ans = 1  4  2  3 % 列矢量
注意逻辑索引中不能使用双精度类型代替逻辑类型.

   find 函数可以用于寻找逻辑矩阵中所有值为 1 的矩阵元的位置. 如果只提供一个输出变量(或不提供输出变量), 函数返回单索引, 如果提供两个输出变量, 函数返回行标和列标. 例如

1
2
3
4
5
6
7
8
9
>> a = [1, 0; 0, 1]
a =
    1  0
    0  1
>> find(a)
ans = 1  4
>> [r, c] = find(a)
r = 1  2 % 列矢量
c = 1  2 % 列矢量
注意以上的双精度矩阵 a 被自动转换为逻辑矩阵.

   any 函数用于判断逻辑矩阵中的每一列是否存在任何值为“真” 的矩阵元, 若有, 则返回真, 否则返回假. all 函数用于判断逻辑矩阵中的每一列是否所有矩阵元都为“真”, 若是, 返回真, 否则返回假. 这两个函数的使用格式与 summean 类似, 当第二个输入变量为 2 时, 对每行进行操作.

1
2
3
4
5
6
7
8
9
10
11
>> a = [1 6 7; 2 7 1; 3 8 9];
>> all(a > 5)
ans = 1×3 logical array
    0  1  0
>> any(a > 7, 2)
ans = 3×1 logical array
    0
    0
    1
>> all(a(:) < 10)
ans = logical 1


1. 若 $\abs{\mat A} = 0$, 即方程组存在无数个解的时候, “\” 算符只能得到一个特解. 若 $\mat A$ 是一个超定方程组, 即行数大于列数, 算法见“超定线性方程组”.

致读者: 小时物理百科一直以来坚持所有内容免费且不做广告,这导致我们处于日渐严重的亏损状态。长此以往很可能会最终导致我们不得不选择商业化,例如大量广告,内容付费,会员制,甚至被收购。因此,我们鼓起勇气在此请求广大读者热心捐款,使网站得以健康发展。如果看到这条信息的每位读者能慷慨捐助 10 元,我们几天内就能脱离亏损状态,并保证网站能在接下来的一整年里向所有读者继续免费提供优质内容。感谢您的支持。
—— 小时(项目创始人)

编辑词条 返回目录 返回主页 捐助项目 © 小时物理百科 保留一切权利