跳轉到

2.4 行列式的幾何意義:面積縮放比#

本節目標#

  • 建立核心直覺:** \(\det(A)\) 是單位方格(面積 1)被變換後的面積** —— 面積縮放比
  • 從 \(\mathbf{e_1}, \mathbf{e_2}\) 的像構成的平行四邊形,推導 \(2\times2\) 公式 \(ad - bc\)
  • 會用 np.linalg.det,並理解 \(\det < 0\) (翻轉定向)與 \(\det = 0\) (壓扁成直線)
  • 把行列式推廣到 3D:體積比
  • 做一個實驗:隨機矩陣的 det 值與網格面積 實測對照

2.4.1 直覺: \(\det\) 是「面積的匯率」#

線性變換會動整個平面,那 面積 呢?

  • 剪切 \(\begin{bmatrix} 1 & 1 \\ 0 & 1 \end{bmatrix}\) :方格被推歪但底×高不變 —— 面積不變, \(\det = 1\)
  • 縮放 \(\mathrm{diag}(3, 2)\) :每格面積變 \(3 \times 2 = 6\) —— \(\det = 6\)
  • 鏡射 \(\mathrm{diag}(1, -1)\) :面積不變但「翻面」—— \(\det = -1\) (負號記錄翻面)
  • 旋轉:面積完全不變 —— \(\det = 1\)

** \(\det(A) =\) 變換後單位面積 ÷ 變換前單位面積。** 圖形上任何區域的面積,變換後都是原來的 \(|\det(A)|\) 倍。

關鍵在於 線性:整個平面由無數單位方格鋪成,變換把它們 等比 地縮放(雖然每格都歪成不同形狀的平行四邊形,但面積全相同),所以一個格子的縮放比就是全平面的縮放比。

2.4.2 推導 \(ad - bc\) :平行四邊形面積#

設 \(A = \begin{bmatrix} a & c \\ b & d \end{bmatrix}\) (第一行 \((a,b)\) 、第二行 \((c,d)\) )。

由 2.1:變換後的單位方格,四個角是 \(\mathbf{0}\) 、 \(A\mathbf{e_1} = (a,b)\) 、 \(A\mathbf{e_2} = (c,d)\) 、 \((a+c,\ b+d)\) —— 一個 平行四邊形,兩條邊就是矩陣的兩行。

平面幾何:底為 \((a, b)\) 、另一邊 \((c, d)\) 的平行四邊形面積 \(=\) 底邊長 \(\times\) 高。用高中「底 × 高」拆一下(或直接用叉積)可得:

\[ \text{面積} = |ad - bc| \]

所以我們 定義:

\[ \det\begin{bmatrix} a & c \\ b & d \end{bmatrix} = ad - bc \]

不需要背 —— 它就是「兩個行向量張出的平行四邊形有向面積」。

import numpy as np
import matplotlib.pyplot as plt
from linalg_viz import setup_axes, draw_grid_transform

A = np.array([[3., 1.],
              [1., 2.]])     # det = 3*2 - 1*1 = 5

fig, ax = plt.subplots(figsize=(6, 6))
setup_axes(ax, xlim=(-1, 5), ylim=(-1, 4))
draw_grid_transform(ax, A, xlim=(-1, 5), ylim=(-1, 4))
# 單位方格變成的平行四邊形:頂點 0, Ae1, Ae1+Ae2, Ae2
e1, e2 = A @ np.array([1., 0.]), A @ np.array([0., 1.])
quad = np.array([[0, 0], e1, e1 + e2, e2])
ax.fill(quad[:, 0], quad[:, 1], alpha=0.25, color="C1")
ax.set_title(rf"$\det = {np.linalg.det(A):.1f}$")
plt.show()

2.4.3 NumPy 實測:np.linalg.det#

import numpy as np

cases = {
    "單位 I":  np.eye(2),
    "剪切":    np.array([[1., 1.], [0., 1.]]),
    "縮放(3,2)": np.diag([3., 2.]),
    "旋轉30°": None,   # 稍後填
    "鏡射x":   np.diag([1., -1.]),
}
th = np.deg2rad(30)
cases["旋轉30°"] = np.array([[np.cos(th), -np.sin(th)],
                             [np.sin(th),  np.cos(th)]])
for name, M in cases.items():
    print(f"{name:12s} det = {np.linalg.det(M):+.3f}")
# 單位 I       det = +1.000
# 剪切         det = +1.000
# 縮放(3,2)    det = +6.000
# 旋轉30°      det = +1.000
# 鏡射x        det = -1.000

每一項都和幾何直覺吻合:不變、不變、6 倍、不變、翻面。

2.4.4 \(\det < 0\) :翻轉定向#

面積不可能是負的,那負號是什麼?是 定向(orientation):

  • \(\det > 0\) :保持「 \(\mathbf{e_1}\) 轉向 \(\mathbf{e_2}\) 是逆時針」的約定
  • \(\det < 0\) :平面被 翻面 —— 像鏡子,順時針變逆時針

觀察:鏡射把 \(\mathbf{e_2} \to -\mathbf{e_2}\) ,兩行向量從「逆時針排列」變成「順時針排列」—— 方向感反了,所以是負的。這在 3D 對應「右手系變左手系」。

2.4.5 \(\det = 0\) :壓扁成直線(奇異矩陣預告)#

C = np.array([[1., 2.],
              [2., 4.]])          # 第二行 = 2 × 第一行
print(np.linalg.det(C))           # 0.0(數值上可能是極小的數)

\(C\) 的兩行 \((1,2)\) 、 \((2,4)\) 平行 —— 單位方格被壓成 一條線段,面積 \(0\) 。整個二維平面被壓扁到一維:資訊永久丟失(多個點擠到同一個像),所以 沒有反矩陣。

這種 \(\det = 0\) 的矩陣叫 奇異矩陣(singular)。第 3 章解 \(A\mathbf{x} = \mathbf{b}\) 的三種命運(唯一解/無解/無限多解),分界線就在這裡: \(\det \neq 0\) 才可能唯一解。

flowchart LR
    det["det(A)"] -->|"+, 面積放大/縮小"| big["空間保持 2D"]
    det -->|"0"| flat["壓扁成直線/點:奇異"]
    det -->|"−"| flip["翻轉定向(鏡射類)"]
    flat --> ch3["第3章:解不唯一或不存在"]

2.4.6 3D:行列式是體積比#

同樣的邏輯升一維: \(3\times3\) 矩陣的三行是 \(\mathbf{e_1}, \mathbf{e_2}, \mathbf{e_3}\) 的像,張出一個 平行六面體, \(\det\) 就是體積比。

M = np.array([[2., 0., 0.],
              [0., 3., 0.],
              [0., 0., 4.]])
print(np.linalg.det(M))    # 24.0:2×3×4,體積縮放 24 倍

F3 = np.diag([1., 1., -1.])          # 對 xy 平面鏡射
print(np.linalg.det(F3))             # -1.0:右手系 → 左手系
Rz = np.array([[0., -1., 0.],
               [1.,  0., 0.],
               [0.,  0., 1.]])       # 繞 z 軸轉 90°
print(np.linalg.det(Rz))             # 1.0:旋轉不變體積

\(|\det| = 1\) 的變換「保體積」;這在物理(座標變換的 Jacobian)、機率(隨機變數變換的密度縮放)到處出現。

2.4.7 實驗:隨機矩陣的 det vs 實測面積#

不做「相信課本」的讀者 —— 我們實際量測。做法:把單位方格切成 \(N\times N\) 個小格,全部變換,用鞋帶公式算總面積,和 \(\det\) 對照:

import numpy as np
import matplotlib.pyplot as plt
from linalg_viz import setup_axes, draw_grid_transform

rng = np.random.default_rng(42)
A = rng.uniform(-2, 2, size=(2, 2))
print(f"np.linalg.det(A) = {np.linalg.det(A):.4f}")

# 實測:單位方格 [0,1]x[0,1] 切 50x50 個小格,全部變換後量總面積
N = 50
edge = 1.0 / N                     # 每個小格的邊長
# 小格兩邊向量經 A 變換後的像(每格變成近似同形的平行四邊形)
d1, d2 = A @ np.array([edge, 0.]), A @ np.array([0., edge])
cell_area = abs(d1[0]*d2[1] - d1[1]*d2[0])   # 一格的變換後面積(鞋帶公式)
area = cell_area * N * N                     # 全部 N×N 格加總
print(f"實測總面積       = {area:.4f}")

fig, ax = plt.subplots(figsize=(6, 6))
setup_axes(ax, xlim=(-3, 3), ylim=(-3, 3))
draw_grid_transform(ax, A, xlim=(-3, 3), ylim=(-3, 3))
ax.set_title(f"det = {np.linalg.det(A):.3f}")
plt.show()

兩個數字會高度吻合(取樣誤差內)—— 行列式不是代數把戲,是你真的能量出來的面積。

小結與練習#

本節重點

  • \(\det(A)\) :單位面積經 \(A\) 變換後的面積(縮放比); \(2\times2\) 公式 \(ad - bc\) 來自行向量的平行四邊形面積
  • \(\det < 0\) :翻轉定向(鏡射的指紋); \(\det = 0\) :壓扁降維 —— 奇異矩陣,無反矩陣(第 3 章)
  • 3D: \(\det\) 是體積比; \(|\det| = 1\) 表示保體積
  • np.linalg.det 一行程式;也可以用取樣 實測 面積驗證

練習

  1. 手算 \(\det\begin{bmatrix} 2 & 1 \\ 5 & 3 \end{bmatrix}\) ,並用「兩行張的平行四邊形」畫圖估出面積。
  2. 對 2.3 的五種積木矩陣逐一算 det,對照你的網格圖解釋每個符號與數值。
  3. 驗證乘法性質:對隨機矩陣 \(\det(AB) = \det(A)\det(B)\) (幾何上為什麼理所當然?提示:縮放比相乘)。
  4. 構造三個 \(\det = 0\) 但 形狀不同 的 \(2\times2\) 矩陣,畫網格圖觀察壓扁的方向由什麼決定(提示:非零的那一行的方向)。
  5. 挑戰:用 np.linalg.det 掃描剪切矩陣 \(\begin{bmatrix} 1 & k \\ 0 & 1 \end{bmatrix}\) , \(k\) 從 \(-3\) 到 \(3\) :det 恆為 1。這說明剪切再怎麼歪都不改變面積 —— 用網格圖驗證一次。