Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

第二十九 行列式(Determinant)

行列式(Determinant)是线性代数中最重要的概念之一。它是一个可以从方阵中计算得到的标量值,记作 $\det(A)$ 或 $|A|$。行列式不仅具有重要的代数意义,还有深刻的几何意义:$n$ 阶方阵的行列式表示该矩阵所对应的线性变换对 $n$ 维空间体积的缩放倍数。


一、行列式的定义

1.1 一阶行列式

$$|A| = a_{11}$$

1.2 二阶行列式

$$|A| = \begin{vmatrix} a_{11} & a_{12} \ a_{21} & a_{22} \end{vmatrix} = a_{11}a_{22} - a_{12}a_{21}$$

对角线法则:

  • 主对角线(左上到右下):$a_{11}a_{22}$,取正号
  • 副对角线(右上到左下):$a_{12}a_{21}$,取负号
fn det2(a11: f64, a12: f64, a21: f64, a22: f64) -> f64 {
    a11 * a22 - a12 * a21
}

fn main() {
    // | 1  2 |
    // | 3  4 |
    let det = det2(1.0, 2.0, 3.0, 4.0);
    println!("二阶行列式 = {}", det);  // 1*4 - 2*3 = -2
}

1.3 三阶行列式

$$|A| = \begin{vmatrix} a_{11} & a_{12} & a_{13} \ a_{21} & a_{22} & a_{23} \ a_{31} & a_{32} & a_{33} \end{vmatrix}$$

$$= a_{11}a_{22}a_{33} + a_{12}a_{23}a_{31} + a_{13}a_{21}a_{32} - a_{13}a_{22}a_{31} - a_{12}a_{21}a_{33} - a_{11}a_{23}a_{32}$$

记忆口诀: 三条主对角线方向乘积之和减去三条副对角线方向乘积之和(萨吕法则)。

fn det3(a: [[f64; 3]; 3]) -> f64 {
    a[0][0] * a[1][1] * a[2][2]
        + a[0][1] * a[1][2] * a[2][0]
        + a[0][2] * a[1][0] * a[2][1]
        - a[0][2] * a[1][1] * a[2][0]
        - a[0][1] * a[1][0] * a[2][2]
        - a[0][0] * a[1][2] * a[2][1]
}

fn main() {
    let a = [[1.0, 2.0, 3.0],
             [4.0, 5.0, 6.0],
             [7.0, 8.0, 9.0]];
    println!("三阶行列式 = {}", det3(a));  // 0
}

1.4 n 阶行列式的完全展开式

$$\det(A) = \sum_{\sigma \in S_n} \text{sgn}(\sigma) \cdot a_{1,\sigma(1)} \cdot a_{2,\sigma(2)} \cdots a_{n,\sigma(n)}$$

其中 $S_n$ 表示所有 $n$ 个元素的排列,$\text{sgn}(\sigma)$ 是排列 $\sigma$ 的符号(偶排列为 $+1$,奇排列为 $-1$)。

对于 $n$ 阶矩阵,展开式共有 $n!$ 项。当 $n$ 较大时,直接展开计算效率极低。


二、排列与逆序数

2.1 排列

$n$ 个不同元素的全排列共有 $n!$ 种。

2.2 逆序数

在一个排列中,如果一对数的前后位置与大小顺序相反(即前面的数大于后面的数),则称这对数构成一个逆序。一个排列中逆序的总数称为逆序数

$$I(\sigma) = \sum_{i=1}^{n} \sum_{j=i+1}^{n} \begin{cases} 1 & \text{if } \sigma_i > \sigma_j \ 0 & \text{otherwise} \end{cases}$$

  • 偶排列:逆序数为偶数,符号为 $+1$
  • 奇排列:逆序数为奇数,符号为 $-1$
fn inversion_count(perm: &[usize]) -> usize {
    let mut count = 0;
    for i in 0..perm.len() {
        for j in (i + 1)..perm.len() {
            if perm[i] > perm[j] {
                count += 1;
            }
        }
    }
    count
}

fn main() {
    let perm = [3, 1, 4, 2];
    let inv = inversion_count(&perm);
    println!("排列 {:?} 的逆序数 = {}", perm, inv);  // 4
    println!("符号 = {}", if inv % 2 == 0 { "+1" } else { "-1" });
}

2.3 对换

对换:一个排列中的任意两个元素位置对调,其余元素不动。

定理:一个排列中的任意两个元素对换,排列的奇偶性改变。

推论:奇排列对换成标准排列的对换次数为奇数,偶排列对换成标准排列的对换次数为偶数。


三、行列式的性质

行列式具有以下重要性质:

性质说明
转置不变性$\det(A^T) = \det(A)$
行交换变号交换两行,行列式变号
行相等为零若两行(列)相等,行列式为 0
行成比例为零若两行(列)成比例,行列式为 0
数乘一行某行乘以 $k$,行列式变为 $k$ 倍
行倍加不变某行的 $k$ 倍加到另一行,行列式不变
行列可加性某行元素为两数之和,可拆分为两个行列式之和
乘积性质$\det(AB) = \det(A) \cdot \det(B)$
幂性质$\det(A^m) = (\det(A))^m$
数乘矩阵$\det(kA) = k^n \det(A)$($n$ 为阶数)
fn det2(a11: f64, a12: f64, a21: f64, a22: f64) -> f64 {
    a11 * a22 - a12 * a21
}

fn main() {
    // 验证转置不变性
    let det_a = det2(1.0, 2.0, 3.0, 4.0);
    let det_at = det2(1.0, 3.0, 2.0, 4.0);  // 转置
    println!("det(A) = {}, det(A^T) = {}", det_a, det_at);
    assert_eq!(det_a, det_at);  // 两者相等

    // 验证交换两行变号
    let det_swapped = det2(3.0, 4.0, 1.0, 2.0);
    println!("det(A) = {}, det(交换行) = {}", det_a, det_swapped);
    assert_eq!(det_a, -det_swapped);  // 互为相反数
}

四、余子式与代数余子式

4.1 余子式

余子式 $M_{ij}$:划去第 $i$ 行和第 $j$ 列后,剩下的 $(n-1)$ 阶矩阵的行列式。

4.2 代数余子式

代数余子式 $C_{ij}$:

$$C_{ij} = (-1)^{i+j} M_{ij}$$

4.3 拉普拉斯展开(按行/列展开)

行列式可以按任意一行或一列展开:

$$\det(A) = \sum_{j=1}^{n} a_{ij} C_{ij} \quad \text{(按第 } i \text{ 行展开)}$$

$$\det(A) = \sum_{i=1}^{n} a_{ij} C_{ij} \quad \text{(按第 } j \text{ 列展开)}$$

// 递归计算 n 阶行列式(拉普拉斯展开)
fn determinant(matrix: &Vec<Vec<f64>>) -> f64 {
    let n = matrix.len();
    if n == 1 {
        return matrix[0][0];
    }
    if n == 2 {
        return matrix[0][0] * matrix[1][1] - matrix[0][1] * matrix[1][0];
    }

    let mut det = 0.0;
    for j in 0..n {
        // 计算余子式
        let mut minor = Vec::new();
        for i in 1..n {
            let mut row = Vec::new();
            for k in 0..n {
                if k != j {
                    row.push(matrix[i][k]);
                }
            }
            minor.push(row);
        }

        let sign = if j % 2 == 0 { 1.0 } else { -1.0 };
        det += sign * matrix[0][j] * determinant(&minor);
    }
    det
}

fn main() {
    let a = vec![
        vec![1.0, 2.0, 3.0],
        vec![0.0, 4.0, 5.0],
        vec![0.0, 0.0, 6.0],
    ];
    println!("行列式 = {}", determinant(&a));  // 1*4*6 = 24
}

五、特殊行列式

5.1 上三角/下三角行列式

上三角或下三角矩阵的行列式等于主对角线元素的乘积:

$$\begin{vmatrix} a_{11} & a_{12} & \cdots & a_{1n} \ 0 & a_{22} & \cdots & a_{2n} \ \vdots & \vdots & \ddots & \vdots \ 0 & 0 & \cdots & a_{nn} \end{vmatrix} = a_{11} \cdot a_{22} \cdots a_{nn}$$

这是计算行列式最常用的方法:通过初等行变换将矩阵化为上三角形式,然后求对角线元素的乘积。

5.2 范德蒙行列式

$$V_n = \begin{vmatrix} 1 & 1 & \cdots & 1 \ x_1 & x_2 & \cdots & x_n \ x_1^2 & x_2^2 & \cdots & x_n^2 \ \vdots & \vdots & \ddots & \vdots \ x_1^{n-1} & x_2^{n-1} & \cdots & x_n^{n-1} \end{vmatrix} = \prod_{1 \le i < j \le n} (x_j - x_i)$$

fn vandermonde_determinant(x: &[f64]) -> f64 {
    let n = x.len();
    let mut det = 1.0;
    for i in 0..n {
        for j in (i + 1)..n {
            det *= x[j] - x[i];
        }
    }
    det
}

fn main() {
    let x = vec![1.0, 2.0, 3.0];
    println!("范德蒙行列式 = {}", vandermonde_determinant(&x));
    // (2-1)(3-1)(3-2) = 2
}

5.3 反对称行列式

若矩阵满足 $a_{ij} = -a_{ji}$(主对角线元素全为 0,对称位置元素互为相反数),则称为反对称矩阵

定理:$n$ 阶反对称行列式,当 $n$ 为奇数时,行列式的值为 0。


六、克莱姆法则

克莱姆法则(Cramer’s Rule)是利用行列式求解线性方程组的方法。

对于 $n$ 元线性方程组 $Ax = b$,若系数矩阵 $A$ 的行列式 $|A| \neq 0$,则方程组有唯一解:

$$x_i = \frac{|A_i|}{|A|}$$

其中 $A_i$ 是将 $A$ 的第 $i$ 列替换为 $b$ 后得到的矩阵。

// 用克莱姆法则解二元线性方程组
// a11*x + a12*y = b1
// a21*x + a22*y = b2
fn cramer2(a11: f64, a12: f64, a21: f64, a22: f64, b1: f64, b2: f64) -> Option<(f64, f64)> {
    let det_a = det2(a11, a12, a21, a22);
    if det_a == 0.0 {
        return None;  // 无解或无穷多解
    }

    let det_x = det2(b1, a12, b2, a22);
    let det_y = det2(a11, b1, a21, b2);

    Some((det_x / det_a, det_y / det_a))
}

fn main() {
    // 鸡兔同笼问题:
    // 头共 35 个,脚共 94 只
    // x + y = 35
    // 2x + 4y = 94
    match cramer2(1.0, 1.0, 2.0, 4.0, 35.0, 94.0) {
        Some((x, y)) => println!("鸡: {} 只, 兔: {} 只", x, y),  // 鸡 23, 兔 12
        None => println!("方程组无解或有无穷多解"),
    }
}

七、行列式的几何意义

维度几何意义
2 阶平行四边形的面积
3 阶平行六面体的体积
n 阶n 维平行多面体的“体积“

行列式的符号表示定向:

  • 正值:保持空间的定向(右手系)
  • 负值:反转空间的定向(左手系)
  • 零值:矩阵将空间压缩到低维(不可逆)
fn parallelogram_area(x1: f64, y1: f64, x2: f64, y2: f64) -> f64 {
    det2(x1, y1, x2, y2).abs()
}

fn main() {
    // 由向量 (3, 0) 和 (0, 4) 张成的平行四边形
    let area = parallelogram_area(3.0, 0.0, 0.0, 4.0);
    println!("平行四边形面积 = {}", area);  // 12
}

八、使用 nalgebra 计算行列式

use nalgebra::Matrix3;

fn main() {
    let a = Matrix3::new(
        1.0, 2.0, 3.0,
        4.0, 5.0, 6.0,
        7.0, 8.0, 10.0,
    );

    let det = a.determinant();
    println!("行列式 = {}", det);  // -3
}

九、总结

概念要点
二阶行列式$a_{11}a_{22} - a_{12}a_{21}$
三阶行列式萨吕法则(对角线法则)
逆序数排列中逆序对的总数,决定符号
余子式划去一行一列后的子矩阵行列式
代数余子式$(-1)^{i+j} M_{ij}$
拉普拉斯展开按行/列展开为低阶行列式之和
三角行列式等于主对角线元素乘积
范德蒙行列式所有 $(x_j - x_i)$ 的乘积
克莱姆法则$x_i =
几何意义面积/体积的缩放倍数

行列式是判断矩阵是否可逆的关键指标:$|A| \neq 0$ 当且仅当 $A$ 可逆。它在求解线性方程组、计算特征值、判断线性相关性等方面都有重要应用。

练习建议:

  1. 实现一个通用的 $n$ 阶行列式计算函数(使用拉普拉斯展开)
  2. 验证行列式的各种性质
  3. 用克莱姆法则求解三元线性方程组