1. 先把矩阵看成“动作”:线性变换的几何直觉
很多学生第一次学矩阵乘法时,最困惑的不是怎么算,而是“算完之后到底发生了什么”。尤其是AB和BA,明明只是调换了一下左右位置,结果却经常不一样,甚至形状都变了。我想说的是,这个困惑很正常,因为如果只看数字,你很难发现规律;但只要把矩阵当成一个“动作”,在二维平面上一画,左右乘的几何意义立刻就会清晰起来。
矩阵最朴素的理解,就是一台线性变换机器:输入一个向量,输出另一个向量。它保持原点不动、把直线变成直线、把平行线变成平行线。二维平面里最常见的线性变换有四种:旋转、缩放、切变、投影。旋转矩阵让图形转一个角度,缩放矩阵把某一方向的长度拉长或压扁,切变矩阵把图形斜着推一下,投影矩阵把整个平面压到一条直线或者一个点上。单位矩阵是什么都不做的机器,零矩阵则是把所有向量都压到原点的机器。
这种“机器视角”的关键在于:矩阵对向量施加作用时,遵循线性叠加原则。简单说,如果你先给了两个输入向量,各自过一遍机器再相加,和先把两个输入向量相加再一起过机器,结果是一样的。这就是线性代数里最核心的线性性。正因为有这个性质,当我们有一大堆点要处理时,不需要一个个单独看,而是可以把它们拼成一个矩阵,一次性“过机器”,这就是后面要讲的左乘批量处理点集的基础。
1.1 矩阵不是数字盒子,而是一台几何机器
我见过太多人把矩阵单纯看作“一堆数字的表格”,然后去背乘法口诀。这样背下来,你只知道怎么算,不知道为什么这么算。比如二维旋转矩阵:
[ R(\theta) = \begin{bmatrix} \cos\theta & -\sin\theta \ \sin\theta & \cos\theta \end{bmatrix} ]
当你把向量 ((1, 0)) 左乘这个矩阵,就得到 ((\cos\theta, \sin\theta)),这正好是把x轴上的单位向量逆时针旋转 (\theta) 角后的结果。你把向量 ((0, 1)) 左乘它,得到 ((-\sin\theta, \cos\theta)),也正好是y轴单位向量旋转后的位置。所以这个矩阵的每一列,其实是标准基向量经过旋转之后的“照片”。
记住这个结论:矩阵的列向量,就是标准基向量被这个矩阵映射后的目标位置。这也是为什么矩阵乘法有“按列理解”的方法。一旦你习惯了“矩阵的列就是基向量的归宿”,后面理解左乘右乘就顺了。把矩阵当数字盒子和当成几何机器,学习效率完全是两回事。
1.2 复合变换:为什么矩阵要从右往左读
假设你有一台旋转机器 (R),一台缩放机器 (S),现在你想先让向量旋转,再让结果缩放。如果直接写“旋转加缩放”,很多初学者会写成 (R + S),但线性变换的复合用的是乘法:先旋转再缩放,对应的矩阵是 (S R)。注意,旋转矩阵写在左边,缩放矩阵写在右边。
为什么?因为矩阵乘法作用于向量时,从右往左执行。表达式 (S R \mathbf{v}) 的意思是:先把 (\mathbf{v}) 交给 (R),得到旋转后的向量,再把这个结果交给 (S)。所以右边的矩阵先接触输入向量,左边的矩阵后接触。复合变换的顺序和你写字从左到右的顺序正好相反。
这个规律可以类比成排队:右边的人先动。如果某天你看到一行矩阵连乘 (M_3 M_2 M_1),不要慌,先执行的永远是 (M_1),然后才是 (M_2),最后 (M_3)。很多图形学、机器人的代码里,从右往左读变换链,就是这个原因。
1.3 用二维平面实验:旋转与缩放的非交换
为什么矩阵乘法普遍不满足交换律?我们用一个直观例子说明。设 (R) 是逆时针旋转90度的矩阵,(S) 是把水平方向拉伸2倍的矩阵:
[ R = \begin{bmatrix} 0 & -1 \ 1 & 0 \end{bmatrix}, \quad S = \begin{bmatrix} 2 & 0 \ 0 & 1 \end{bmatrix} ]
先让向量 ((1, 0)) 做“先水平拉伸,再旋转90度”。水平拉伸后变成 ((2, 0)),旋转90度后变成 ((0, 2))。对应的矩阵是 (R S)。如果换过来,先旋转90度,再水平拉伸。((1, 0)) 旋转后变成 ((0, 1)),水平拉伸对竖直方向的y坐标没有影响,所以结果还是 ((0, 1))。对应的矩阵是 (S R)。
同样的两个动作,只是换了顺序,最终一个落在 ((0, 2)),一个落在 ((0, 1))。这就是矩阵乘法不交换的几何原因:旋转会改变拉伸的方向,拉伸也会改变旋转后向量的落点,两个动作耦合在一起,先后顺序没法随便换。
所以我一直认为,“矩阵乘法不满足交换律”这句话不该被当成抽象结论背下来,而应该当成“先穿袜子再穿鞋”和“先穿鞋再穿袜子”的区别。穿对了没事,顺序反了,结果就非常别扭。
2. 左乘和右乘的分工:列向量视角与行向量视角
理解了矩阵是动作、乘法顺序从右往左之后,我们就可以正式回答“矩阵的左乘和右乘的几何意义”。这里有一个非常实用的观察角度:矩阵乘法的左乘,主要作用在列向量上;矩阵乘法的右乘,主要作用在行向量上。这个简单区分,能解释绝大多数应用场景。
左乘可以理解为:一个变换矩阵作用到另一个矩阵的每一列上。比如 (A B),结果矩阵的第 (j) 列,就等于 (A) 乘以 (B) 的第 (j) 列。如果 (B) 的每一列都是一个二维或三维点,那么 (A B) 就是对这一组点同时施加同一个线性变换。这是图形学里最常见的“对象变换”模型。
右乘的视角相对隐蔽:(B A) 的结果矩阵,每一列是 (B) 的各列按 (A) 的某一列系数做线性组合的结果;等价地,每一行是 (B) 的对应行向量被 (A) 映射后的结果。如果把 (B) 的列理解为坐标轴方向,那么右乘更像是在“改变坐标系”,而不是直接推动几何对象。下面我把两种视角拆开细讲。
2.1 左乘:对列向量逐个施加变换
设 (A) 是一个 (m \times n) 矩阵,(B) 是 (n \times p) 矩阵。计算 (C = A B) 时,(C) 的第 (j) 列可以写成:
[ C[:, j] = A \cdot B[:, j] ]
这里的冒号表示取列。这个等式说明,左乘 (A) 时,(A) 会依次作用到 (B) 的每一列上。如果 (B) 是多个点的坐标矩阵,比如每一列存一个点的x、y坐标,那么 (A B) 就是把所有点整体搬运到新位置。
举个具体例子。假设平面有一个三角形,三个顶点分别是 ((0,0))、((1,0))、((1,1)),你把这些点按列排成:
[ B = \begin{bmatrix} 0 & 1 & 1 \ 0 & 0 & 1 \end{bmatrix} ]
用旋转矩阵 (R) 左乘 (B),得到 (R B)。因为 (R) 会分别作用到三列上,所以三角形的三个顶点都被旋转了,整个三角形随之旋转。这就是左乘的几何意义:对象在动。
更进一步,矩阵 (A) 的列本身就是标准基向量被 (A) 映射后的结果。所以 (A) 左乘一个单位矩阵 (I),得到的就是 (A) 自己;换句话,左乘相当于把标准基下的坐标,全部替换成 (A) 的各列所代表的新位置。这个理解在后续学习特征值、SVD时特别有用。
2.2 右乘:对行向量(坐标分量)重组
现在看右乘。设 (D = B A),其中 (B) 是 (p \times m),(A) 是 (m \times n)。结果 (D) 的每一行,等于 (B) 的对应行向量乘以 (A)。如果从列的角度看,(D) 的第 (j) 列等于:
[ D[:, j] = B \cdot A[:, j] ]
这个式子表明,右乘矩阵 (A) 时,原矩阵 (B) 的每一列不是被单独旋转或缩放,而是按照 (A) 各列给出的系数重新组合。说得更直白,右乘做的是“列向量的线性混合”。
这个区别非常重要。假设 (B) 的两列分别是两个基向量,比如 ((2,0)) 和 ((0,1))。左乘一个90度旋转矩阵 (R),会把这两个向量各自旋转,基向量还是互相垂直的长度保持的向量。右乘 (R) 则不同,它会产生两个新列,每一列都是原来两列的混合,混合系数来自 (R) 的列。如果 (R) 是旋转矩阵,结果相当于把原始的坐标轴方向重新组合了一遍,几何上更像是在换坐标系。
所以在实际工程里,如果你看到“右乘一个变换矩阵”,通常意味着你在改变基、改变坐标系、改变特征空间,而不是在推动一堆点。当然,这个说法并不是绝对的,因为行向量版本的变换也可以通过转置转换成左乘,但作为直观记忆,“左乘让对象动,右乘让坐标系动”非常好用。
2.3 关键陷阱:行向量左乘需要用转置矩阵
学到这里,一个很常见的坑出现了。有些人把点坐标写成行向量,比如 ((x, y)),然后用变换矩阵 (A) 去乘,就写成:
[ \begin{bmatrix}x & y\end{bmatrix} \cdot A ]
这个写法在数学上是合法的,但它对应的不是“用 (A) 变换这个点”,而是“用 (A^T) 变换这个点的转置版本”。因为列向量变换是:
[ \mathbf{v}' = A \mathbf{v} ]
两边转置,就得到:
[ (\mathbf{v}')^T = \mathbf{v}^T A^T ]
也就是说,若你的点以行向量存储,想让每个点被 (A) 变换,正确写法是 (\mathbf{v}^T A^T),不是 (\mathbf{v}^T A)。
用之前的旋转矩阵验证一下。90度逆时针旋转 (R),行向量 ((1, 0)) 乘以 (R) 得到 ((0, -1)),方向反了;乘以 (R^T) 得到 ((0, 1)),方向才对。很多三维引擎里点坐标用行向量存储时,变换矩阵经常要预先转置,就是这个道理。这不是矩阵左乘右乘本身变了,而是行向量和列向量之间的转置关系在做怪。
2.4 用表格看清三种位置的区别
| 表达式 | 作用对象 | 通俗几何说法 | 典型场景 |
|---|---|---|---|
| (A \mathbf{v}) | 单个列向量 | 对这个向量施加变换 | 最基本的分 |
| (A B) | B的每一列 | 对一组列向量整体变换 | 点云、顶点变换 |
| (B A) | B的每一行 / 列混合 | 改变基向量组合方式 | 坐标系变换、基变换 |
| (A B \mathbf{x}) | 先B后A作用x | 复合变换顺序 | 机械臂、动画层级 |
每次写代码前,先问自己三个问题:我的数据是行向量还是列向量?我要让对象动,还是要换坐标系?我期望的变换顺序是从右往左写,还是从左往右写?想清楚这三个问题,左右乘基本不会再错。
3. 动手实验:用NumPy看左乘右乘的几何差异
光看公式还是有点干,我建议你打开Python,亲手画一画。下面这个实验用NumPy和Matplotlib生成一个正方形,分别用两种不同的矩阵顺序去变换它,看一眼图形就知道左乘和右乘差在哪里。这个过程不超过五分钟,但收获比背十遍定义都大。
3.1 实验设计:一个正方形的两种变换顺序
先定义两个基础变换:90度逆时针旋转矩阵 (R),水平方向拉伸矩阵 (S)。正方形的五个顶点按列排成矩阵 (sq),每个点是一列,最后一个点回到起点,方便画闭合图形。代码如下:
import numpy as np import matplotlib.pyplot as plt theta = np.pi / 2 R = np.array([[np.cos(theta), -np.sin(theta)], [np.sin(theta), np.cos(theta)]]) S = np.array([[2.0, 0.0], [0.0, 1.0]]) # 每个点是列向量,最后一列重复第一列 sq = np.array([[0, 1, 1, 0, 0], [0, 0, 1, 1, 0]])接下来我们要对比:
trans1 = R @ S @ sq # 先水平拉伸 S,再旋转 R trans2 = S @ R @ sq # 先旋转 R,再水平拉伸 S注意Python里@是矩阵乘法,最右边的矩阵先执行。所以R @ S @ sq的真实顺序是:先 (S),再 (R)。S @ R @ sq的真实顺序是:先 (R),再 (S)。
3.2 代码实现与输出解读
把三个图形画在一张图上:
fig, axes = plt.subplots(1, 3, figsize=(12, 4)) names = ["original", "R @ S", "S @ R"] all_data = [sq, trans1, trans2] for ax, data, name in zip(axes, all_data, names): ax.plot(data[0, :], data[1, :], marker="o") ax.set_title(name) ax.set_aspect("equal") ax.grid(True) plt.show()打印一下变换后的坐标:
print("trans1:\n", trans1) print("trans2:\n", trans2)R @ S先拉伸后旋转,正方形的边长从水平方向被拉长,然后整个形状被旋转90度,所以最终是一个竖着的矩形。S @ R先旋转后拉伸,正方形先转90度,边长没有变化,再水平拉伸,所以最终是一个横着的矩形。方向完全不一样。
这个实验直接展现了矩阵乘法非交换的几何本质:交换左乘和右乘,等于交换两个动作的先后顺序。对新手来说,画一次图比盯着公式想半天有用得多。我建议你把角度从90度改成30度、45度,再试试,斜向矩形会看得更清楚。
3.3 右乘一个旋转变换:坐标轴旋转还是图形旋转?
现在我们把问题再推进一步:不左乘旋转矩阵,而是右乘旋转矩阵,结果会怎样?为了能观察到列的组合,我们用一个非单位矩阵 (B) 当“基向量集合”:
[ B = \begin{bmatrix} 2 & 0 \ 0 & 1 \end{bmatrix} ]
分别计算 (R B) 和 (B R)。(R B) 的意思是:把 (B) 的两列 ((2,0)) 和 ((0,1)) 分别旋转90度,得到 ((0,2)) 和 ((-1,0))。图形的两个“方向箭头”都被旋转了,但箭头之间的相对关系保持不变,这是“对象整体旋转”。
(B R) 呢?它的第一列是 (B) 的两列按旋转矩阵第一列的系数组合,第二列是按旋转矩阵第二列的系数组合。计算出来是:
[ B R = \begin{bmatrix} 0 & -2 \ 1 & 0 \end{bmatrix} ]
第一列变成 ((0,1)),第二列变成 ((-2,0))。看起来好像还是旋转后的方向,但仔细看,原来的x轴方向 ((2,0)) 并没有被单独旋转到 ((0,2)),而是被重新分配到了两个新列里。这种效果更像是“坐标系整体换了一套基”,而不是“基向量各自转”。
所以,当你看到右乘一个变换矩阵时,心里要自动翻译成:“原来的向量集合,正在被变换矩阵的各个列线性混合。” 这在信号处理、数据降维里非常常见:你有一组特征向量,右乘一个正交矩阵,得到的是一组新的正交基,而不是简单地把每个特征向量转一下。
3.4 实操心得:什么时候用左乘、右乘
做实际项目时,我一般按下面几个场景来选:
- 如果你有一堆顶点、点云、向量,想让它们在世界坐标系里被同一个变换作用,用左乘。列向量存点,直接 (M P);行向量存点,先转置一下,用 (P M^T)。
- 如果你在做基变换、坐标系变换,比如把某个向量从局部坐标系变换到世界坐标系,通常要把基向量按列排成矩阵 (P),然后右乘一个坐标变换矩阵,或者用 (P^{-1} M P) 这种相似变换形式。
- 如果你在搭复合变换,比如机器人的关节链条,记住“先进行的操作写在右边,后进行的操作写在左边”。从右往左读代码里的矩阵链,你就知道每个组件到底先做了什么。
有一次我帮人调试图形程序,发现物体旋转方向总是反的。查了半天,问题出在他把顶点坐标存成了行向量,却用左乘的方式写了变换矩阵。改正成右乘转置矩阵后,立刻正常。这种问题在实际开发里非常典型,提前养成“先判断行列向量”的习惯,能省很多时间。
4. 更深一层:基变换与相似变换中的左右乘
如果你只是想应付考试,前面两节已经够用了。但如果想真正把左乘右乘用起来,尤其是接触到特征值、主成分分析、振动分析这些内容时,还需要理解一个更完整的图景:同一个线性变换,在不同基底下表示成不同的矩阵。这个过程里,左乘和右乘会同时出现。
我经常举一个例子:你站在一个房间里,看到墙上有一个影子,影子确实存在,但你换个角度去看,影子的形状就变了。线性变换 (A) 就是那个“影子本体”,不管你在哪个坐标系下描述它,它本身不会变。可你观察用的坐标系一变,描述它的矩阵就会变成另一个样子。这个“换成另一个矩阵”的操作,就是相似变换。
4.1 基变换矩阵与坐标向量
设有一组新基,它的各个基向量在旧坐标系下的坐标,按列拼成一个矩阵 (P)。例如新基是把旧基旋转45度得到的,那么 (P) 就是旋转45度的矩阵。如果某个向量在新基下的坐标是 (\mathbf{v}'),那么它在旧基下的坐标是:
[ \mathbf{x} = P \mathbf{v}' ]
这里 (P) 右乘坐标向量 (\mathbf{v}'),意味着什么?它把“新基下的读数”翻译成“旧基下的实际位置”。所以右乘 (P) 在基变换中扮演的角色是:从新坐标到旧坐标的翻译官。
反过来,如果你知道一个向量在旧基下的坐标 (\mathbf{x}),想求它在刚建立的新基下的坐标,就要用:
[ \mathbf{v}' = P^{-1} \mathbf{x} ]
这里 (P^{-1}) 左乘旧坐标,把数据从旧坐标系翻译回新坐标系。一个右乘负责“进入”,一个左乘负责“离开”,基变换中的左右位置一下子就不神秘了。
4.2 (P^{-1} A P) 的几何故事
现在假设在旧基下,有一个线性变换用矩阵 (A) 表示。如果我想知道同一个变换在新基下长什么样,不能直接写 (A),也不能只乘一个 (P)。你需要完整走一遍流程:
- 新基下的坐标 (\mathbf{v}'),先右乘 (P),换算成旧基下的实际位置 (\mathbf{x});
- 在旧基下做变换,(\mathbf{y} = A \mathbf{x});
- 再把变换结果 (\mathbf{y}) 左乘 (P^{-1}),换算回新基坐标。
合并起来就是:
[ \mathbf{w}' = P^{-1} A P \mathbf{v}' ]
这个 (P^{-1} A P) 就是 (A) 在新基下的表示。注意左右乘的分工:右边的 (P) 是“输入翻译”,左边的 (P^{-1}) 是“输出翻译”。两个翻译夹着中间那个真正干活的 (A)。
很多教材直接给这个公式,却不解释为什么右边是 (P) 而不是 (P^{-1})。你只要记住那个三步流程,就不会记反:先右乘进入旧世界,在旧世界发作,再左乘回到新世界。这是我在实际教学中发现最有效的记忆方式。
4.3 具体例子:旋转拉伸在不同基下的表现
拿前面用过的水平拉伸矩阵 (A = \mathrm{diag}(2, 1)) 举例,旧基就是标准基。现在把坐标系整体旋转45度,新基矩阵 (P) 为:
[ P = \begin{bmatrix} \cos 45^\circ & -\sin 45^\circ \ \sin 45^\circ & \cos 45^\circ \end{bmatrix} ]
因为旋转矩阵是正交矩阵,(P^{-1} = P^T)。于是新基下的变换矩阵是:
[ P^{-1} A P = P^T \begin{bmatrix} 2 & 0 \ 0 & 1 \end{bmatrix} P = \begin{bmatrix} 1.5 & -0.5 \ -0.5 & 1.5 \end{bmatrix} ]
这个结果不再是简单的对角拉伸,而是出现了一对反对角元素。但从几何上说,它描述的仍然是同一个“沿旧x轴方向拉长到2倍,沿旧y轴方向保持”的动作。只是坐标系转了45度之后,这个动作看起来变成了“沿着新坐标轴的45度方向拉长,同时沿另一个垂直方向压缩/保持”。
这正好解释了为什么我们在标准坐标系下看一个矩阵,感觉它是旋转带剪切,但换到特征向量坐标系下,它就变成一个纯粹的对角缩放矩阵。矩阵还是那个动作,变的是你看它的角度。
4.4 这解释了为什么特征向量是“不动方向”
特征向量的定义是 (A \mathbf{v} = \lambda \mathbf{v}),几何意思非常直白:存在某些方向,矩阵 (A) 只会把向量拉长或缩短,不会改变它的方向。这些方向就是矩阵的“主轴”。
当我们把这些特征向量按列排成 (P),得到:
[ P^{-1} A P = \Lambda ]
这里的 (\Lambda) 是对角矩阵,对角线上的元素就是特征值。放到前面的三步流程里看:先把坐标翻译到特征向量张成的坐标系,然后在这个坐标系下,变换变成沿每个坐标轴独立缩放,再翻译回原坐标系。整个过程里,左乘右乘正好把复杂的“旋转+拉伸”拆成了“旋转进去、缩放、旋转回来”。
这也是为什么主成分分析要去找协方差矩阵的特征向量:因为只有把坐标系旋转到特征方向,原本复杂的相关性结构才会变成互不相关的独立缩放轴。理解和掌握了 (P^{-1} A P) 的几何画面,再回头看左乘右乘,你已经不是背公式,而是在心里“看”变换过程了。
5. 常见错误与排查思路
代码写得多了,难免会遇到左右乘混用、顺序写反、结果方向不对这类问题。我整理了一份速查表,外加几个高频踩坑细节。如果你正在做图形学、机器人、数据科学相关的东西,建议先收藏,等遇到问题再回来对号入座。
5.1 常见问题速查表
| 症状 | 可能原因 | 解决办法 |
|---|---|---|
| 图形方向反了 | 行向量点直接右乘变换矩阵,忘了转置 | 改为右乘变换矩阵的转置,或用列向量左乘 |
| 复合变换结果和预期不符 | 矩阵连乘顺序和动作顺序反了 | 先执行的动作写在最右边,从右往左读 |
| 左乘右乘算出来差很多 | 把“对象变换”当成了“坐标系变换” | 先想清楚你要让对象动,还是换坐标系 |
| 矩阵能乘但图形看起来奇怪 | 点坐标的存储格式和矩阵维度不匹配 | 确认每个点是列向量还是行向量,统一约定 |
| 结果矩阵维数正确但数值全错 | 把 (P^{-1} A P) 写成了 (P A P^{-1}) | 记住右边进入旧坐标系,左边回到新坐标系 |
这些坑我都踩过,而且踩得很狼狈。尤其是行向量和列向量混用,在C++、Python、Matlab里都有不同的默认约定,稍不注意就会翻车。最好的办法就是在代码开头写清楚注释:“所有点的存储方式为列向量,变换顺序从左到右依次后执行”。
5.2 四个容易踩坑的细节
第一个细节:行向量版本要转置。如果某个库默认点坐标是行向量,那么左乘变换矩阵 (A) 应该写成 (P A^T),而不是 (P A)。这不是矩阵乘法本身变了,而是转置把左右关系调换了一下。
第二个细节:矩阵乘法有结合律,但没有交换律。你可以先算 (A B) 再乘 (\mathbf{v}),也可以先算 (B \mathbf{v}) 再用 (A) 作用,结果一样。但不能把 (A B) 换成 (B A)。结合律给了计算上的便利,交换律不要乱用。
第三个细节:非方阵也有几何意义。(m \times n) 矩阵把 (n) 维空间映到 (m) 维空间,可能降维也可能升维。左乘右乘的规则依然成立,只是这时候“行混合”和“列变换”会伴随维度变化,不能死套“旋转”“拉伸”这种二维直觉。
第四个细节:右乘不一定是“转置”。 (B A) 的每一行是 (B) 的对应行向量被 (A) 映射,但如果想把它改写成列向量左乘,确实要用 (A^T)。所以看到右乘时,脑子里要分两条线:一条是“列向量被线性组合”,一条是“行向量被 (A^T) 变换”。两条线都对,但别混着用。
5.3 给学习者的自检流程
我建议你在学完左右乘之后,做这套五分钟自检:
第一步,画一个简单图形,比如三角形或正方形,把它表示成矩阵。第二步,写下你想要的两个动作,比如“先旋转再拉伸”和“先拉伸再旋转”。第三步,按列向量约定写出对应的矩阵链,左乘到图形上。第四步,用手算或代码画出结果。第五步,把其中一个矩阵从左边挪到右边,再算一遍,观察图形的变化差异。
做完这五步,你不仅会理解左乘和右乘的几何意义,还会发现矩阵乘法的顺序本质上就是“动作发生的顺序”。我在教朋友线性代数时,从来不让大家死记硬背 (AB \ne BA),而是让他们亲手画一幅图,把 (AB) 和 (BA) 两个结果并排放在一起。见过一次之后,这个知识点就再也忘不掉了。
最后再分享一个小技巧:当你不确定该左乘还是右乘时,用一个最简单的情况验证。比如把一个点放在 ((1,0)),把变换矩阵取成 (R),算一遍看看方向是否符合直觉。单位向量、单位矩阵、零矩阵都是很好的“测试用例”。这些不起眼的验证,往往比反复查公式更可靠。