第 9 章 行列式
学习目标
- 掌握二阶行列式的公式,并理解它等于平行四边形的(有向)面积
- 掌握三阶行列式的公式与代数余子式展开
- 掌握行列式的基本性质,并能解释每条性质的几何含义
- 理解「行列式 ≠ 0」与「可逆 / 线性无关 / 唯一解」的关系
- 会用 NumPy 与 PyTorch 计算行列式
9.1 二阶行列式:从面积出发
第 5 章里,两个不共线向量张成一个平行四边形。现在问:这个平行四边形的面积是多少?
设两个向量
把它们排成矩阵 (第 1 列是 ,第 2 列是 )。
行列式定义(二阶):

为什么是 ?用「大矩形减去四个角上的三角形」来推导。假设 都是正数,以 为邻边的平行四边形,外接矩形边长是 和 ,面积为 。平行四边形以外的部分由四个直角三角形拼成,面积正好是 。于是平行四边形面积:
import matplotlib.pyplot as plt
from matplotlib import font_manager
for f in font_manager.findSystemFonts():
if any(k in f for k in ("NotoSansCJK", "NotoSansSC", "wqy", "SimHei", "msyh", "PingFang")):
font_manager.fontManager.addfont(f)
plt.rcParams["font.sans-serif"] = ["Noto Sans CJK SC", "WenQuanYi Zen Hei", "SimHei", "Microsoft YaHei", "PingFang SC"]
plt.rcParams["axes.unicode_minus"] = False
import numpy as np
v1 = np.array([3.0, 1.0])
v2 = np.array([1.0, 2.0])
fig, ax = plt.subplots(figsize=(6, 6))
ax.axhline(0, color="black", linewidth=1)
ax.axvline(0, color="black", linewidth=1)
ax.grid(True, linestyle=":", alpha=0.5)
ax.set_xlim(-0.5, 5)
ax.set_ylim(-0.5, 4)
ax.set_aspect("equal")
# 平行四边形:v1、v2 为邻边
pts = np.array([[0.0, 0.0], v1, v1 + v2, v2, [0.0, 0.0]])
ax.fill(pts[:, 0], pts[:, 1], color="tab:orange", alpha=0.25)
ax.plot(pts[:, 0], pts[:, 1], color="tab:orange", linewidth=2)
# 外接矩形
ax.plot([0, v1[0] + v2[0], v1[0] + v2[0], 0, 0],
[0, 0, v1[1] + v2[1], v1[1] + v2[1], 0],
color="gray", linestyle="--", linewidth=1)
for v, c, label in [(v1, "tab:red", "v1"), (v2, "tab:blue", "v2")]:
ax.quiver(0, 0, v[0], v[1], angles="xy", scale_units="xy", scale=1,
color=c, width=0.018)
ax.annotate(label, v / 2, textcoords="offset points", xytext=(8, 6), color=c, fontsize=13)
det = np.linalg.det(np.column_stack([v1, v2]))
ax.set_title(f"行列式 = 有向面积 = {det:.0f}")
fig.savefig("book/public/figs/fig09-det_area.png", dpi=120, bbox_inches="tight")
plt.close(fig)例:
- :单位正方形的面积是 1。
- : 矩形的面积是 6。
- :两个向量共线,平行四边形「压扁」成线段,面积为 0——这正是第 5 章预告的「相关 ⟺ 行列式为 0」。
行列式可能是负数(比如交换两列),所以准确地说,它是有向面积:行列式取绝对值才是面积,符号表示「方向」。这解释了下面性质 1 的几何意义。
import numpy as np
examples = [
np.array([[1.0, 0.0], [0.0, 1.0]]),
np.array([[3.0, 0.0], [0.0, 2.0]]),
np.array([[1.0, 2.0], [2.0, 4.0]]),
np.array([[1.0, 3.0], [2.0, 1.0]]),
]
for A in examples:
print(A.tolist(), "-> det =", np.linalg.det(A))运行输出:
[[1.0, 0.0], [0.0, 1.0]] -> det = 1.0
[[3.0, 0.0], [0.0, 2.0]] -> det = 6.0
[[1.0, 2.0], [2.0, 4.0]] -> det = 0.0
[[1.0, 3.0], [2.0, 1.0]] -> det = -5.0000000000000019.2 三阶行列式:体积与公式
三阶行列式对应平行六面体的有向体积。它的展开公式(用代数余子式沿第一行展开,9.4 推导):
例:
import numpy as np
A = np.array([[1.0, 2.0, 3.0],
[4.0, 5.0, 6.0],
[7.0, 8.0, 10.0]])
print("det =", np.linalg.det(A))运行输出:
det = -2.9999999999999996实际运行得到 ;浮点误差让结果差一点点,精确值是 。
9.3 行列式的基本性质
四条最重要的性质(全部可以从「有向面积」的角度理解,也都可以逐元素验证):
- 交换两行,行列式变号。交换两列相当于翻转平行四边形,有向面积反号。
- 一行乘以 ,行列式乘以 。把一条边拉长 倍,面积放大 倍。
- 一行加上另一行的倍数,行列式不变。沿底边「滑动」顶点,平行四边形的底和高都不变,面积不变。
- 。先做变换 再做 ,面积放大倍数等于两次放大倍数的乘积。
用代码验证:
import numpy as np
A = np.array([[1.0, 2.0],
[3.0, 4.0]])
B = np.array([[0.0, 1.0],
[1.0, 0.0]])
print("det(A) =", np.linalg.det(A))
B2 = B.copy()
B2[0], B2[1] = B2[1], B2[0].copy() # 交换两行
print("交换两行后:", np.linalg.det(B2), "(原 det(B) =", np.linalg.det(B), ")")
print("det(A @ B) =", np.linalg.det(A @ B))
print("det(A) * det(B) =", np.linalg.det(A) * np.linalg.det(B))运行输出:
det(A) = -2.0000000000000004
交换两行后: 1.0 (原 det(B) = -1.0 )
det(A @ B) = 2.0
det(A) * det(B) = 2.0000000000000004本身就是「交换单位矩阵两行」得到的,所以 ;再交换一次回到单位矩阵,行列式变回 ——两次验证了「交换两行变号」。同时 ✓。
还有一个重要性质:(转置不改变行列式)。所以「按行展开」和「按列展开」结果一样。
9.4 代数余子式:任意阶行列式的通用算法
对 阶矩阵,把元素 所在的第 行、第 列划掉,剩下的 阶矩阵的行列式叫余子式,记 。带符号的
叫代数余子式。沿第 行展开:
符号 排成棋盘格:
拿三阶公式对照:沿第一行()展开,
与 9.2 的公式完全一致。注意中间一项是减号——因为 。这就是「代数余子式展开」:把 阶行列式递归地拆成 阶行列式,直到二阶。这个算法可以直接写成代码:
import numpy as np
def det_recursive(A):
"""用代数余子式展开计算方阵的行列式(递归实现,适合教学,不适合大矩阵)"""
A = np.array(A, dtype=float)
n = A.shape[0]
if n == 1:
return A[0, 0]
if n == 2:
return A[0, 0] * A[1, 1] - A[0, 1] * A[1, 0]
total = 0.0
for j in range(n):
# 划掉第 0 行、第 j 列
minor = np.delete(np.delete(A, 0, axis=0), j, axis=1)
total += ((-1) ** j) * A[0, j] * det_recursive(minor)
return total
A = np.array([[1.0, 2.0, 3.0],
[4.0, 5.0, 6.0],
[7.0, 8.0, 10.0]])
print("递归实现:", det_recursive(A))
print("np.linalg.det:", np.linalg.det(A))运行输出:
递归实现: -3.0
np.linalg.det: -2.9999999999999996PyTorch 计算行列式:
import torch
A = torch.tensor([[1.0, 2.0, 3.0],
[4.0, 5.0, 6.0],
[7.0, 8.0, 10.0]])
print("torch det:", torch.linalg.det(A))运行输出:
torch det: tensor(-3.0000)9.5 行列式与可逆性
把第 5、8 章的结论串起来,得到线性代数最重要的一条「等价链」:对 阶方阵 ,下列说法等价——
- ;
- 的列线性无关;
- 对任意 都有唯一解;
- 可逆(存在 ,第 10 章);
- 高斯消元不需要「自由变量」,主元个数 。
几何直觉:行列式是「体积放大倍数」。倍数是 0,说明变换把 维空间压扁到低维(列相关),信息丢失,无法还原,自然不可逆。
动手实践
- 计算 、、,并说出第二个、第三个的几何含义。
- 画出向量 与 张成的平行四边形,用行列式算面积,再数格子验证(近似即可)。
- 用代数余子式沿第二行展开计算 9.2 的三阶行列式,确认与沿第一行展开的结果相同。
- 用 NumPy 验证 ,任选一个 3×3 矩阵。
- 修改 9.4 的递归函数,让它同时支持 (空矩阵,行列式约定为 1)。
常见错误
| 错误写法/理解 | 原因 |
|---|---|
| 把二阶行列式记成 | 公式是 ;可以靠「面积」记忆:斜线方向不同,一加一减 |
| 三阶展开中间项忘记变号 | 代数余子式带符号 ,第一行第二列是 |
| 认为行列式是矩阵的「值」,随便换行换列都不变 | 交换两行变号,数乘行要乘数;只有「一行加另一行倍数」不变 |
| 认为 | 行列式对加法不线性;只有 |
| 用展开公式算大矩阵 | 递归展开复杂度是 ,10 阶就几乎跑不动;大矩阵用库的消元算法 |
章末练习
基础
- 计算:
- 用代码验证上面三个结果。
- 说出 的几何意义(二维)与代数意义(列向量)。
提高
- 计算三阶行列式(用公式与代码各算一遍):
- 已知 、,求 、、(若 是 )。
挑战
- 用几何论证(不展开):为什么「一行加上另一行的倍数」不改变行列式?提示:以该行为一条边,另一行是底边,滑动顶点时底和高都不变。
- 证明:含一行全 0 的矩阵,行列式为 0;两行相同的矩阵,行列式为 0(用性质 1 和性质 2 推理)。
章末自测
- A.
- B.
- C.
- D.
- 二阶行列式的几何意义是?
- A. 两列向量张成平行四边形的有向面积
- B. 矩阵的行数
- C. 两行向量的点积
- D. 矩阵的迹
- 说明?
- A. 可逆
- B. 的列线性相关
- C. 是对称矩阵
- D. 是单位矩阵
- 交换方阵的两行,行列式?
- A. 不变
- B. 变号
- C. 变为 0
- D. 翻倍
- 一行乘以 3,行列式?
- A. 不变
- B. 乘以 3
- C. 除以 3
- D. 变为 0
- A.
- B.
- C.
- D.
- 三阶行列式沿第一行展开时,第二项的符号是?
- A.
- B.
- C. 与元素大小有关
- D. 任意
- A.
- B.
- C.
- D.
- 代数余子式展开法适合?
- A. 任意阶矩阵快速计算
- B. 小矩阵与教学推导
- C. 只能算二阶
- D. 只能算三阶
- A.
- B.
- C.
- D.
