视频加载失败

18.06 第 19 讲:行列式公式与代数余子式

4319 字
22 分钟
18.06 第 19 讲:行列式公式与代数余子式
  1. 118.06 第 1 讲:方程组的行图与列图
  2. 218.06 第 2 讲:用矩阵做消元
  3. 318.06 第 3 讲:矩阵乘法的四种看法与逆矩阵
  4. 418.06 第 4 讲:分解成 A = LU
  5. 518.06 第 5 讲:转置、置换与向量空间
  6. 618.06 第 6 讲:列空间与零空间
  7. 718.06 第 7 讲:解 Ax = 0,主变量与特解
  8. 818.06 第 8 讲:解 Ax = b,行最简形 R
  9. 918.06 第 9 讲:线性无关、基与维数
  10. 1018.06 第 10 讲:四个基本子空间
  11. 1118.06 第 11 讲:矩阵空间、秩 1 矩阵与小世界图
  12. 1218.06 第 12 讲:图、网络与关联矩阵
  13. 1318.06 第 13 讲:第一次测验复习
  14. 1418.06 第 14 讲:正交向量与正交子空间
  15. 1518.06 第 15 讲:投影到子空间
  16. 1618.06 第 16 讲:投影矩阵与最小二乘
  17. 1718.06 第 17 讲:正交矩阵与 Gram-Schmidt
  18. 1818.06 第 18 讲:行列式的性质
  19. 1918.06 第 19 讲:行列式公式与代数余子式本文
  20. 2018.06 第 20 讲:Cramer 法则、逆矩阵与体积
  21. 2118.06 第 21 讲:特征值与特征向量
  22. 2218.06 第 22 讲:对角化与矩阵的幂
  23. 2318.06 第 23 讲:微分方程与 exp(At)
  24. 2418.06 第 24 讲:Markov 矩阵与 Fourier 级数
  25. 2518.06 第 24b 讲:第二次测验复习
  26. 2618.06 第 25 讲:对称矩阵与正定性
  27. 2718.06 第 26 讲:复矩阵与快速 Fourier 变换
  28. 2818.06 第 27 讲:正定矩阵与极小值
  29. 2918.06 第 28 讲:相似矩阵与 Jordan 标准形
  30. 3018.06 第 29 讲:奇异值分解
  31. 3118.06 第 30 讲:线性变换及其矩阵
  32. 3218.06 第 31 讲:基变换与图像压缩
  33. 3318.06 第 32 讲:第三次测验复习
  34. 3418.06 第 33 讲:左逆、右逆与伪逆
  35. 3518.06 第 34 讲:期末复习

上一讲 Strang 用三条性质推出了十条性质,这一讲他把同样的三条性质用到底,得到一个能直接从 aija_{ij} 算出行列式的公式:4 × 4 矩阵有 24 项,6 × 6 有 720 项,每一项都是“每行每列各取一个数”的乘积,再带上正负号。我拿他在黑板上现编的 4 × 4 例子去数,24 项里只有两项不是零,一项 +1+1、一项 −1-1,加起来是 0。之后是第二个公式(余子式展开),以及一个三对角矩阵的行列式:它每六阶重复一次,所以 det⁡A61=1\det A_{61} = 1。

本讲速览

视频:Lecture 19: Determinant formulas and cofactors(OCW 页面与字幕) 教材:《Introduction to Linear Algebra》第 6 版 §5.1 3 by 3 Determinants and Cofactors;§5.2 Computing and Using Determinants 前置:第 18 讲:行列式的性质 一句话:行列式等于 n!n! 项“每行每列各取一个”的带符号乘积(大公式),也等于沿一行的 a1ja_{1j} 乘以各自的代数余子式之和,后者把 nn 阶行列式拆成 n−1n - 1 阶的。

配合视频
  • 开头他先用三条性质把 2 × 2 的 ad−bcad - bc 重新推了一遍,只是为了展示方法。这一段值得认真听,后面全是这个套路的重复。
  • 3 × 3 的“幸存者”那段是整讲的核心:把每一行拆开,二十七块里只有每行每列各一个的才活下来,他还逐个判断了正负号。我把它写成了 itertools.permutations,本篇第一个代码块里算过。
  • 现编的 4 × 4 例子(二十四项里二十二项为零)他自己说“以前没算过”,可以认真看他怎么把整个过程走下来。矩阵他写在黑板上,字幕里没有,我按他描述的路径还原了一个。
  • 代数余子式的定义和符号规则(棋盘格)也要看;最后三对角矩阵的例子很短,周期是 6 那里是整讲最有意思的地方,我在最后一个代码块里算过。

把三条性质用到底:大公式#

行列式到底由什么构成? 回忆上一讲的三条性质:det⁡I=1\det I = 1;交换两行,行列式变号;对每一行单独看,行列式是线性的。Strang 先在 2 × 2 上演示怎么用它们算出一个公式。

做法是把第一行 (a,b)(a, b) 拆成 (a,0)+(0,b)(a, 0) + (0, b),再把第二行 (c,d)(c, d) 拆成 (c,0)+(0,d)(c, 0) + (0, d),用性质三(对每一行线性)得到四个行列式:

∣abcd∣=∣a0c0∣+∣a00d∣+∣0bc0∣+∣0b0d∣\begin{aligned} \begin{vmatrix} a & b \\ c & d \end{vmatrix} &= \begin{vmatrix} a & 0 \\ c & 0 \end{vmatrix} + \begin{vmatrix} a & 0 \\ 0 & d \end{vmatrix} \\ &\quad + \begin{vmatrix} 0 & b \\ c & 0 \end{vmatrix} + \begin{vmatrix} 0 & b \\ 0 & d \end{vmatrix} \end{aligned}

第一个和第四个有一整列是 0,是奇异矩阵,行列式为 0,他说“它死了”。第二个是对角矩阵,行列式 adad。第三个要换一次行才变成对角矩阵,行列式是 −bc-bc。四项里两项活下来,ad−bcad - bc 就这么出来了。

重点是方法,不是这个答案。3 × 3 时,第一行拆成三块,第二行再拆成三块,第三行再来一次,一共 33=273^3 = 27 块。我数了一下,4 × 4 是 44=2564^4 = 256 块。这些块里,只要某一列没被任何一行选到,那一列全是零,整块的行列式为 0。

幸存者是谁? 每一行选一个位置,每一列也恰好被选一次的那些块。他的 3 × 3 里有六个幸存者,对应列号 (1,2,3)(1,2,3)、(1,3,2)(1,3,2)、(2,1,3)(2,1,3)、(2,3,1)(2,3,1)、(3,1,2)(3,1,2)、(3,2,1)(3,2,1) 的排列。每一块把选中的数提出来,剩下的是一个只有 0 和 1 的置换矩阵,它的行列式是 ±1\pm 1,由把它换回单位矩阵需要的行交换次数的奇偶决定。(1,3,2)(1,3,2) 要换一次,所以是 −1-1;(2,3,1)(2,3,1) 要换两次,所以是 +1+1。合起来:

det⁡A=a11a22a33−a11a23a32−a12a21a33+a12a23a31+a13a21a32−a13a22a31\begin{aligned} \det A &= a_{11}a_{22}a_{33} - a_{11}a_{23}a_{32} - a_{12}a_{21}a_{33} \\ &\quad + a_{12}a_{23}a_{31} + a_{13}a_{21}a_{32} - a_{13}a_{22}a_{31} \end{aligned}

正号三项沿着“往下”的方向,负号三项沿着“反方向”,这是他口中去迈阿密和洛杉矶的那两条线。他立刻说这个口诀只对 3 × 3 成立:4 × 4 的反对角线(全是 1 的那条)行列式是 +1+1,因为交换第 1、4 行和第 2、3 行共两次就回到单位矩阵。

推广到 nn 阶,就是他书里的大公式(big formula):

det⁡A=∑所有排列 (α,β,…,ω)± a1α a2β⋯anω\det A = \sum_{\text{所有排列 }(\alpha,\beta,\ldots,\omega)} \pm\, a_{1\alpha}\, a_{2\beta} \cdots a_{n\omega}

第一行有 nn 种选法,选完占掉一列,第二行剩 n−1n - 1 种,依此类推,一共 n!n! 项,一半正一半负。正负号看排列的奇偶。我猜这条公式如果做成棋盘上的游戏,就是在 n×nn \times n 的棋盘上放 nn 个互不攻击的车,每种放法对应一项(这个类比我只用这一次)。

下面把它实现出来。itertools.permutations 给出所有列号排列,符号用逆序对的个数的奇偶判断(相邻两个数交换一次,逆序对数恰好变 1,所以它的奇偶和“交换次数的奇偶”是同一回事)。脚本先打印 3 × 3 的六个排列和符号,再数反对角线的行列式,数 n!n! 的项数,最后在一个 6 × 6 的随机矩阵上对比 np.linalg.det:

import itertools
import numpy as np
def perm_sign(perm: tuple[int, ...]) -> int:
"""数逆序对的个数,奇数个就是奇置换。"""
inversions = sum(
1
for i in range(len(perm))
for j in range(i + 1, len(perm))
if perm[i] > perm[j]
)
return -1 if inversions % 2 else 1
def big_formula(A: np.ndarray) -> float:
"""行列式的大公式:每行每列各取一个数,共 n! 项。"""
n = A.shape[0]
total = 0.0
for perm in itertools.permutations(range(n)):
term = perm_sign(perm)
for row, col in enumerate(perm):
term *= A[row, col]
total += term
return total
def main() -> None:
np.set_printoptions(precision=4, suppress=True)
# 3 x 3 的六项:列号的排列、符号
for perm in itertools.permutations(range(3)):
cols = tuple(c + 1 for c in perm)
print(cols, "符号", f"{perm_sign(perm):+d}")
# 反对角线:4 x 4 是 +1,3 x 3 是 -1
for n in (2, 3, 4):
J = np.fliplr(np.eye(n))
print(n, "阶反对角线的行列式:", round(np.linalg.det(J)))
# 项数:n!
for n in (2, 3, 4, 5, 6):
count = sum(1 for _ in itertools.permutations(range(n)))
print(f"n = {n}:{count} 项")
rng = np.random.default_rng(1806)
A = rng.standard_normal((6, 6))
print(f"大公式:{big_formula(A):.6f}")
print(f"np.linalg.det:{np.linalg.det(A):.6f}")
print("一致:", np.isclose(big_formula(A), np.linalg.det(A)))
if __name__ == "__main__":
main()
(1, 2, 3) 符号 +1
(1, 3, 2) 符号 -1
(2, 1, 3) 符号 -1
(2, 3, 1) 符号 +1
(3, 1, 2) 符号 +1
(3, 2, 1) 符号 -1
2 阶反对角线的行列式: -1
3 阶反对角线的行列式: -1
4 阶反对角线的行列式: 1
n = 2:2 项
n = 3:6 项
n = 4:24 项
n = 5:120 项
n = 6:720 项
大公式:-7.439860
np.linalg.det:-7.439860
一致: True

六个排列里三正三负,和他黑板上写的一致;反对角线单位矩阵的行列式是 2 阶 −1-1、3 阶 −1-1、4 阶 +1+1,确认了“口诀只对 3 × 3 成立”。6 × 6 矩阵用 720 项算出的 −7.439860-7.439860 和 np.linalg.det 完全对上。

他还指出,大公式可以反推所有性质:A=IA = I 时,只有 a11a22⋯anna_{11}a_{22}\cdots a_{nn} 这一项(排列是 1,2,…,n1,2,\ldots,n,符号为正)不为零,所以 det⁡I=1\det I = 1。同样可以看出 det⁡A=det⁡AT\det A = \det A^{\mathsf{T}},因为转置只是把“行选列”换成“列选行”。至于 det⁡AB=det⁡Adet⁡B\det AB = \det A \det B,他说从这条公式出发证明会弄到“下个星期还在做”,大概就是不会再提了。

一个例子:二十四项里只有两项活着#

Strang 现场编了一个 4 × 4 的 0-1 矩阵,说“我不知道它的行列式,数学正在你们眼前第一次被做出来”。字幕里没有写出矩阵,只有他的走法:第一条路取出排列 (4,3,2,1)(4,3,2,1),交换两次回到 (1,2,3,4)(1,2,3,4),是 +1+1;第二条路是 (3,2,1,4)(3,2,1,4),只要交换 1 和 3 一次,是 −1-1;从别的位置出发都走不通。两条路加起来是 0,所以奇异。他接着发现第一行加第三行是全 1 的行,第二行加第四行也是,所以“行一减行二加行三减行四”是零行。

我按这些线索还原了一个满足所有描述的矩阵(我的版本可能没有他的那么有戏剧性):

A=[0011011011001001]A = \begin{bmatrix} 0 & 0 & 1 & 1 \\ 0 & 1 & 1 & 0 \\ 1 & 1 & 0 & 0 \\ 1 & 0 & 0 & 1 \end{bmatrix}

把 24 个排列都过一遍,看有哪些乘积不为零:

import itertools
import numpy as np
def perm_sign(perm: tuple[int, ...]) -> int:
inversions = sum(
1
for i in range(len(perm))
for j in range(i + 1, len(perm))
if perm[i] > perm[j]
)
return -1 if inversions % 2 else 1
def main() -> None:
np.set_printoptions(precision=4, suppress=True)
# 字幕里没有写出矩阵,这是我按他的两条路径还原的 0-1 矩阵
A = np.array(
[
[0, 0, 1, 1],
[0, 1, 1, 0],
[1, 1, 0, 0],
[1, 0, 0, 1],
],
dtype=float,
)
survivors = []
for perm in itertools.permutations(range(4)):
term = np.prod([A[row, col] for row, col in enumerate(perm)])
if term != 0:
survivors.append((tuple(c + 1 for c in perm), perm_sign(perm)))
print("24 项里不为零的:", survivors)
total = sum(sign for _, sign in survivors)
print("它们的和:", total)
print("np.linalg.det:", round(np.linalg.det(A), 10) + 0.0)
# 奇异的另一个证据:行的组合给出零行,列的组合给出零向量
print("行一 - 行二 + 行三 - 行四:", A[0] - A[1] + A[2] - A[3])
print("列一 - 列二 + 列三 - 列四:", A[:, 0] - A[:, 1] + A[:, 2] - A[:, 3])
print("秩:", np.linalg.matrix_rank(A))
if __name__ == "__main__":
main()
24 项里不为零的: [((3, 2, 1, 4), -1), ((4, 3, 2, 1), 1)]
它们的和: 0
np.linalg.det: 0.0
行一 - 行二 + 行三 - 行四: [0. 0. 0. 0.]
列一 - 列二 + 列三 - 列四: [0. 0. 0. 0.]
秩: 3

24 项里恰好两项不为零,列号 (3,2,1,4)(3,2,1,4) 带 −1-1,(4,3,2,1)(4,3,2,1) 带 +1+1,和他的说法一致。和为 0,np.linalg.det 也给出 0.0,秩是 3。行组合和列组合都能凑出零,所以零空间和左零空间各有一个非零向量。这就是“零多的矩阵可以直接用大公式”的好处:一眼看出来的结构,比消元更快。

代数余子式:把 nn 阶拆成 n−1n - 1 阶#

怎样把大公式拆开? 还是从 3 × 3 开始。把含有 a11a_{11} 的两项合并:

a11(a22a33−a23a32)a_{11}\left(a_{22}a_{33} - a_{23}a_{32}\right)

括号里正好是划掉第 1 行第 1 列之后剩下的 2 × 2 矩阵的行列式。含 a12a_{12} 的两项是 −a12(a21a33−a23a31)-a_{12}(a_{21}a_{33} - a_{23}a_{31}),括号里同样是划掉第 1 行第 2 列后的 2 × 2 行列式,但前面多了一个负号。含 a13a_{13} 的是 +a13(a21a32−a22a31)+a_{13}(a_{21}a_{32} - a_{22}a_{31})。

Strang 把“划掉后剩下的子矩阵行列式”连同这个符号一起叫作 aija_{ij} 的代数余子式(cofactor):

Cij=(−1)i+jdet⁡MijC_{ij} = (-1)^{i + j} \det M_{ij}

MijM_{ij} 是划掉第 ii 行第 jj 列后的 (n−1)×(n−1)(n-1) \times (n-1) 矩阵。符号由 i+ji + j 的奇偶决定,是一张棋盘格,左上角是加号。不带符号的 det⁡Mij\det M_{ij} 叫余子式(minor),他说那个词他不在乎,直接把符号收进去叫代数余子式。沿第一行展开:

det⁡A=a11C11+a12C12+⋯+a1nC1n\det A = a_{11}C_{11} + a_{12}C_{12} + \cdots + a_{1n}C_{1n}

沿第 ii 行同理,只是把下标 1 换成 ii。2 × 2 的例子最小:aa 的余子式是 dd,bb 的余子式是 cc,加上符号后是 −c-c,所以 det⁡=a⋅d+b⋅(−c)=ad−bc\det = a \cdot d + b \cdot (-c) = ad - bc。

他还提到,既然余子式能把 nn 阶拆成 n−1n - 1 阶,再拆成 n−2n - 2 阶,一路拆到 1 × 1,那么整门行列式的课完全可以从这个公式开始讲,有人就是这么讲的。他选择先讲性质,原因我猜是性质更容易看出行列式“为什么”这样。

他接着把三种算法的位置交代清楚:主元的乘积把所有繁琐的东西已经折进了消元里,效率最高;大公式把所有繁琐的东西摊开写出来;余子式公式介于两者之间,“容易的东西乘以可怕的东西”,它的用处是把大行列式拆成小行列式。

下面是余子式展开的递归实现。det_cofactor 沿指定的一行展开,每次调用时全局的计数器加一,用来数递归调用次数;我还对 6 × 6 矩阵每一行都展开一次,确认结果相同,并和 np.linalg.det 对照:

import numpy as np
calls = 0
def minor(A: np.ndarray, i: int, j: int) -> np.ndarray:
"""划掉第 i 行第 j 列。"""
return np.delete(np.delete(A, i, axis=0), j, axis=1)
def cofactor(A: np.ndarray, i: int, j: int) -> float:
"""代数余子式 C_ij = (-1)^(i+j) det(M_ij)。"""
return (-1) ** (i + j) * det_cofactor(minor(A, i, j))
def det_cofactor(A: np.ndarray, row: int = 0) -> float:
"""沿第 row 行做余子式展开。"""
global calls
calls += 1
n = A.shape[0]
if n == 1:
return A[0, 0]
return sum(A[row, j] * cofactor(A, row, j) for j in range(n))
def main() -> None:
global calls
np.set_printoptions(precision=4, suppress=True)
# 符号是棋盘格
signs = np.array([[(-1) ** (i + j) for j in range(5)] for i in range(5)])
print(signs)
# 2 x 2:a * d + b * (-c)
B = np.array([[3.0, 5.0], [2.0, 7.0]])
print("2 x 2:", det_cofactor(B), ",np.linalg.det:", np.linalg.det(B))
# 沿任意一行展开,结果相同
rng = np.random.default_rng(1806)
A = rng.standard_normal((6, 6))
for row in range(6):
print(f"沿第 {row + 1} 行:{det_cofactor(A, row):.6f}")
print(f"np.linalg.det:{np.linalg.det(A):.6f}")
# 递归调用次数,对比 n!
print("n 调用次数")
for n in (3, 4, 5, 6, 7, 8):
calls = 0
det_cofactor(rng.standard_normal((n, n)))
print(f"{n} {calls}")
if __name__ == "__main__":
main()
[[ 1 -1 1 -1 1]
[-1 1 -1 1 -1]
[ 1 -1 1 -1 1]
[-1 1 -1 1 -1]
[ 1 -1 1 -1 1]]
2 x 2: 11.0 ,np.linalg.det: 11.000000000000002
沿第 1 行:-7.439860
沿第 2 行:-7.439860
沿第 3 行:-7.439860
沿第 4 行:-7.439860
沿第 5 行:-7.439860
沿第 6 行:-7.439860
np.linalg.det:-7.439860
n 调用次数
3 10
4 41
5 206
6 1237
7 8660
8 69281

棋盘格的符号和他说的一样(第二行从减号开始)。沿六行中任意一行展开都得到 −7.439860-7.439860,与 np.linalg.det 一致,也与上一节用大公式算出的同一个矩阵的值一致。

代价是另一回事:3 阶调用 10 次,8 阶调用 69281 次。这个调用次数已经比 8!=403208! = 40320 大了 1.7 倍,因为余子式展开除了叶子还有中间层。这是稠密矩阵的情形;到 20 阶,20!20! 约 2.4×10182.4 \times 10^{18},而消元只需要大约 203/3≈266720^3/3 \approx 2667 次乘法(见第 4 讲)。所以在实际计算里算行列式用消元,大公式和余子式的价值在于它们给出了结构:零很多的时候可以一眼读出结论,符号规则也是后面逆矩阵公式的基础。

三对角矩阵:行列式每六阶重复一次#

零很多的时候,余子式能做出什么? Strang 的最后一个例子是对角线和两条副对角线全是 1 的 nn 阶矩阵 AnA_n,4 阶是

A4=[1100111001110011]A_4 = \begin{bmatrix} 1 & 1 & 0 & 0 \\ 1 & 1 & 1 & 0 \\ 0 & 1 & 1 & 1 \\ 0 & 0 & 1 & 1 \end{bmatrix}

小的先算:det⁡A1=1\det A_1 = 1,det⁡A2=1⋅1−1⋅1=0\det A_2 = 1 \cdot 1 - 1 \cdot 1 = 0。A3A_3 的大公式有六项,其中三项非零,+1+1、−1-1、−1-1,和是 −1-1;也可以先用第二行减第三行,再沿新的行展开,得到 −1-1。

到 A4A_4,沿第一行展开,只有两个非零元素。a11=1a_{11} = 1 的余子式是 A3A_3 的行列式,符号为正。a12=1a_{12} = 1 在 (1,2)(1,2) 位置,符号为负,划掉第一行第二列后的 3 × 3 矩阵的第一列是 (1,0,0)T(1, 0, 0)^{\mathsf{T}},对这一列再展开一次(转置规则允许按列展开),剩下的是 A2A_2,符号是正。所以 det⁡A4=det⁡A3−det⁡A2\det A_4 = \det A_3 - \det A_2。这个论证对任何 nn 都成立:

det⁡An=det⁡An−1−det⁡An−2\det A_n = \det A_{n-1} - \det A_{n-2}

他说这些数你大概猜不到,然后一路往下算:1、0、−1-1、−1-1、0、1、1、……,到这里又开始重复,周期是 6(A5A_5 是 0,A6A_6 和 A7A_7 都是 1)。所以 det⁡A61=det⁡A1=1\det A_{61} = \det A_1 = 1(61=6×10+161 = 6 \times 10 + 1)。

我把递推写成循环,从 1 阶到 12 阶与 np.linalg.det 逐个对照,再算 61 阶:

import numpy as np
def tridiagonal_ones(n: int) -> np.ndarray:
"""对角线与两条副对角线全是 1 的 n 阶矩阵。"""
return np.eye(n) + np.eye(n, k=1) + np.eye(n, k=-1)
def det_recurrence(n: int) -> int:
"""D_n = D_{n-1} - D_{n-2},D_0 = 1,D_1 = 1。"""
prev, curr = 1, 1
if n == 0:
return prev
for _ in range(n - 1):
prev, curr = curr, curr - prev
return curr
def main() -> None:
np.set_printoptions(precision=4, suppress=True)
print(tridiagonal_ones(4))
print("n 递推 np.linalg.det")
for n in range(1, 13):
D = round(np.linalg.det(tridiagonal_ones(n)))
print(f"{n:<3d} {det_recurrence(n):>3d} {D:>3d}")
n = 61
exact = det_recurrence(n)
numeric = np.linalg.det(tridiagonal_ones(n))
print(f"n = {n}:递推 = {exact},np.linalg.det = {numeric:.6f}")
if __name__ == "__main__":
main()
[[1. 1. 0. 0.]
[1. 1. 1. 0.]
[0. 1. 1. 1.]
[0. 0. 1. 1.]]
n 递推 np.linalg.det
1 1 1
2 0 0
3 -1 -1
4 -1 -1
5 0 0
6 1 1
7 1 1
8 0 0
9 -1 -1
10 -1 -1
11 0 0
12 1 1
n = 61:递推 = 1,np.linalg.det = 1.000000

12 阶以内每一阶的递推值和数值行列式都一致:1、0、−1-1、−1-1、0、1,然后 1、0、−1-1、−1-1、0、1。61 阶的 61×6161 \times 61 矩阵让 np.linalg.det 也给出 1.000000,和递推相同。注意 A2A_2 的行列式是 0,说明直接消元的话第二个主元会出问题,需要换行;NumPy 内部是带行交换的 LU,所以不受影响。

这个例子我觉得挺漂亮的:一个看起来只能一阶一阶硬算的行列式,因为余子式的递推,变成了一个周期为 6 的数列。余子式在这里比消元好用,是因为矩阵的零恰好让每次展开只剩两项。

下一讲是行列式的最后一讲,他会用余子式给出逆矩阵的公式,再把 Cramer 法则和体积放进来:Cramer 法则、逆矩阵与体积。

支持与分享

如果这篇文章对你有帮助,欢迎分享给更多人或打赏支持!

打赏
18.06 第 19 讲:行列式公式与代数余子式
https://bfmhno3.github.io/posts/linear-algebra-19-determinant-formulas-cofactors/
作者
bfmhno3
发布于
2026-10-18
许可协议
CC BY-NC-SA 4.0
相关文章智能推荐
1
18.06 第 18 讲:行列式的性质
NoteMIT 18.06 第 18 讲的配套笔记:我用 Python 3.13 和 NumPy 2.4 逐条验证了 Strang 的十条行列式性质,又手写消元求主元乘积,算 100 × 100 随机矩阵的行列式,和 np.linalg.det 的相对差只有 9.99e-13。
2
18.06 第 20 讲:Cramer 法则、逆矩阵与体积
NoteMIT 18.06 第 20 讲的配套笔记:我用 Python 3.13 和 NumPy 2.4 验证了余子式求逆、Cramer 法则和 |det| 等于面积与体积,并数了一下:解 10 阶方程组,Cramer 法则(用余子式算行列式)要 68588300 次乘法,消元大约 333 次,差了 205971 倍。
3
18.06 第 23 讲:微分方程与 exp(At)
NoteMIT 18.06 第 23 讲的配套笔记:我用 Python 3.13 和 NumPy 2.4 把 du/dt = Au 的解 exp(At)u(0) 用特征分解、Taylor 级数和缩放平方各算了一遍,t = 20 时 60 项 Taylor 的误差是 3.11e+24,缩放平方是 1.05e-15。
4
18.06 第 21 讲:特征值与特征向量
NoteMIT 18.06 第 21 讲的配套笔记:我用 Python 3.13 和 NumPy 2.4 算了投影、置换、旋转和三角矩阵的特征值,90 度旋转矩阵的特征值是 ±i,而 [[3, 1], [0, 3]] 的特征向量矩阵条件数高达 3.00e+15。
5
18.06 第 6 讲:列空间与零空间
NoteMIT 18.06 第 6 讲的配套笔记:我用 Python 3.13 和 NumPy 2.4 对 Strang 的 4 × 3 矩阵用最小二乘残差判断右端项在不在列空间,再用 SVD 求零空间,1000 个随机右端项里没有一个落在列空间里,而 Ax = b 的全部解是一条到原点距离 0.8165 的直线。
随机文章随机推荐

评论区

Profile Image of the Author
bfmhno3
Hello, I'm bfmhno3.
公告
本站曾使用 Jekyll + Minimal Mistakes 主题,现已迁移至 Astro + Firefly。博客内容未变,但文章链接有所调整,请自行查找需要的文章。
分类
标签
最新动态
站点统计
文章
123
分类
2
标签
239
总字数
753,253
运行时长
0 天
最后活动
0 天前
站点信息
构建平台
GitHub Actions
博客版本
Firefly v6.16.8
文章许可
CC BY-NC-SA 4.0
文章目录