ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

MATLAB矩阵对角化实战:特征值、若当标准形与符号运算避坑指南

MATLAB矩阵对角化实战:特征值、若当标准形与符号运算避坑指南

简介:这份资源面向学习MATLAB数值计算与线性代数的学生和工程人员,聚焦矩阵处理中的特征值、特征向量与对角化等核心问题,适合作为课堂实验或自学练习的配套材料。压缩包内共1个doc文档,约98KB,内容以实验讲义形式组织,涵盖特征多项式求解、eig函数求特征值与特征向量、实对称矩阵的正交对角化、balance函数提高计算精度以及jordan函数求若当标准形等知识点,并配有可直接运行的MATLAB代码示例与运算结果。文档还整理了trace、sum、prod、cdf2rdf等常用矩阵函数的用法说明,便于读者对照实验步骤复现结果、理解矩阵分析的基本流程。目前已有727人学习下载,适合需要系统梳理MATLAB矩阵运算命令、完成相关实验报告或查漏补缺的读者参考使用。

1. 从一次翻车的对角化说起:这套 MATLAB 矩阵处理实验到底值不值得跑

带过几届做数值计算方向的学生之后,我发现一个规律:凡是自称"学过线性代数"的人,第一次用 MATLAB 处理特征值问题,十有八九会在对角化验证那一步翻车。不是概念不懂,而是从纸面推导到工程实现之间隔着一层东西——数值精度、符号运算、若当块的排列方向,每一个都能让结果对不上。这份实验六的资料,恰好就是冲着这层隔阂来的。它围绕特征值、特征向量、若当标准形这几个矩阵分析里的硬骨头,把 MATLAB 里poly、eig、jordan、balance、cdf2rdf这些函数串成了一条完整的操作链。适合谁?正在做线性代数实验、需要把矩阵对角化落到代码上的学生,以及工作中偶尔要处理模态分析、系统稳定性判据、二次型标准化的工程师。它不教你线性代数,它教你怎么让 MATLAB 把线性代数算对。

2. 特征多项式与特征值:poly、eig 和符号求解三条路怎么选

2.1 特征多项式:poly 的向量表示和 poly2str 的可读化

MATLAB 里求特征多项式最直接的是poly(A),它返回的是多项式系数的行向量,按降幂排列。这个向量本身不好读,得配合poly2str转成人类能看的字符串形式。

% 定义方阵 A A = [1 0; 2 3]; % poly 返回特征多项式的系数向量,按降幂排列 p = poly(A) % 把系数向量转成可读的多项式字符串 f = poly2str(p, 'x')

运行后p是[1 -4 3],对应x^2 - 4x + 3。这里有个容易忽略的点:poly(A)返回的系数向量长度是 n+1,首项系数恒为 1(因为特征多项式是首一的)。如果你拿这个向量去做roots,得到的就是特征值。参数上没什么可调的,poly只接受方阵,非方阵会直接报错。

另一种路子是从定义出发,用符号变量硬算行列式:

A = [1 0; 2 3]; E = eye(2); % 2 阶单位阵 syms x % 声明符号变量 f = det(x*E - A) % 直接按定义算特征多项式

这条路的好处是结果以符号形式呈现,(x-1)*(x-3)一眼就能看出根。代价是符号运算慢,矩阵一大就卡。我一般只在矩阵阶数小于 5 且需要精确表达式时才用符号法,其余情况一律走poly加roots。

2.2 eig 的四种调用形式与特征向量的归一化问题

eig是这套流程的核心。它至少有四种调用形式,每种返回的东西不一样,混用是新手最常见的翻车点。

A = [0 1 0 0; 1 0 0 0; 0 0 0 1; 0 0 1 0]; % 形式一:只返回特征值列向量 d = eig(A) % 形式二:返回特征向量矩阵 V 和特征值对角阵 D,满足 A*V = V*D [V, D] = eig(A) % 形式三:eigs 按大小次序返回,适合大型稀疏矩阵 [V, D] = eigs(A) % 形式四:广义特征值问题 A*x = lambda*B*x % [V, D] = eig(A, B)

形式二里有个关键细节:D的主对角线元素是特征值,但顺序不保证按大小排。上面这个例子里D的对角线是-1, -1, 1, 1,特征值 -1 是二重的,对应V的第 1、2 列。这里V的列向量是归一化的,模长为 1,但符号可能和你手算的不一样——这是数值算法的正常行为,不是错误。

验证对角化是否成立,标准操作是:

% 用符号形式输出 V,避免浮点误差干扰判断 V_sym = sym(V) % 验证 V^-1 * A * V 是否等于 D V_sym^-1 * A * V_sym

结果应该是一个对角阵,对角线上就是特征值。如果这里算出来非对角元有微小数值,别慌,那是浮点误差,用sym转成符号再算就干净了。

2.3 提高精度:balance 什么时候该用

balance这个函数很多人没用过,但它在特征值计算精度上确实能救场。原理是对矩阵做相似变换,把行范数和列范数拉到接近的量级,减少数值计算中的舍入误差。

% 返回相似变换矩阵 T 和平衡矩阵 B,满足 B = T^-1 * A * T [T, B] = balance(A); % 只要平衡矩阵 B = balance(A);

什么时候该用?当你发现eig算出来的特征值对扰动特别敏感,或者矩阵元素量级差异很大(比如有的元素是 1e-8,有的是 1e8),先balance一下再求特征值,精度会明显改善。注意balance不改变特征值,只改变矩阵的数值条件。我一般在对精度有要求且矩阵条件数偏大时才会加这一步,日常小矩阵直接eig就够了。

3. 对角化实战:实对称矩阵、复对角转实对角与若当标准形

3.1 实对称矩阵的对角化:eig 直接给出正交阵

实对称矩阵有个漂亮性质:一定可以对角化,而且特征向量可以选成正交的。MATLAB 的eig对实对称矩阵会自动返回正交矩阵P,满足P' * A * P = D。

A = [2 2 -2; 2 5 -4; -2 -4 5]; % 实对称矩阵 [P, D] = eig(A) % P 是正交阵,D 是对角阵 % 验证正交性:P' * P 应该是单位阵 P' * P % 验证对角化:P' * A * P 应该等于 D P' * A * P

运行后D的对角线是1, 1, 10,P的列向量两两正交且模长为 1。这里P' * P会得到一个接近单位阵的结果,非对角元是 1e-16 量级的浮点噪声。如果你在做二次型标准化,P就是变换矩阵,D就是标准形系数。注意实对称矩阵不会出现复特征值,所以不需要cdf2rdf处理。

3.2 复对角矩阵转实对角:cdf2rdf 的 2x2 实数块

非对称实矩阵的特征值可能是复数,而且成共轭对出现。eig返回的D是对角阵,但对角线上是复数。如果你需要实数形式的块对角阵,就得用cdf2rdf。

A = [0 2 1; -2 0 3; -1 -3 0]; [v, d] = eig(A) % v 和 d 都是复数形式 [V, D] = cdf2rdf(v, d) % 转成实数块对角形式

转换后D不再是对角阵,而是在对角线上用 2x2 实数块代替共轭复数对。上面这个例子里,D会变成一个 3x3 的块对角阵,其中有一个 2x2 块对应特征值0 ± 3.7417i。这个函数在控制系统里做模态分析时特别有用,因为实矩阵形式更方便后续计算。参数上cdf2rdf要求输入的v和d必须是eig输出的复数形式,不能先手动取实部。

3.3 若当标准形:jordan 函数与上三角块的排列规则

若当标准形是矩阵相似理论的终极形式,MATLAB 里用jordan求。

A = [-1 -2 6; -1 0 3; -1 -1 4]; J = jordan(A) % 返回 A 的若当标准形

运行结果是:

J = 1 1 0 0 1 0 0 0 1

这里有个必须记住的坑:MATLAB 的若当块是按上三角形定义的,也就是说非对角元 1 出现在对角元的上方。这和某些教材里下三角的定义相反。如果你拿教材上的结果直接对比,发现 1 的位置不对,先确认定义方向。另外jordan对数值矩阵的鲁棒性一般,矩阵接近亏损时结果可能不稳定,符号矩阵会好很多。

3.4 迹与行列式的验证:trace、sum、prod 的配合

特征值有两个基本恒等式:所有特征值之和等于矩阵的迹,所有特征值之积等于矩阵的行列式。用 MATLAB 验证这两个性质,能快速判断特征值算得对不对。

A = [1 2 2; 2 1 2; 2 2 1]; a = trace(A) % 矩阵的迹 d = eig(A) % 特征值 b = sum(d, 1) % 特征值求和,dim=1 按列求和 e = det(A) % 矩阵行列式 f = prod(d, 1) % 特征值求积,dim=1 按列求积

sum和prod的dim参数容易搞混:dim=1按列操作,dim=2按行操作。对于列向量d,sum(d, 1)和sum(d, 2)结果一样,但习惯上求全部元素和用sum(sum(A, 1), 2)更稳妥。验证通过的标准是a和b相等、e和f相等,浮点误差在 1e-10 量级以内都算正常。

4. 避坑与排查:特征值计算里那些让人怀疑人生的报错

4.1 现象:eig 返回的特征向量验证不通过,V^-1AV 不是对角阵

原因通常有两个。一是矩阵本身不可对角化(亏损矩阵),特征向量不够 n 个线性无关的,这时候V是奇异的,V^-1根本不存在或者数值上极不稳定。二是浮点误差累积,尤其是矩阵条件数很大时,V^-1 * A * V的非对角元可能跑到 1e-8 量级,看起来不像对角阵。

解决办法:先用rank(V)检查特征向量矩阵是否满秩。如果不满秩,说明矩阵亏损,得走若当标准形路线。如果是浮点误差,把V转成符号形式sym(V)再算V^-1 * A * V,结果就干净了。我一般会在验证前加一句format short控制显示精度,避免被一堆小数位干扰判断。

4.2 现象:jordan 函数报错或返回结果和教材对不上

jordan对数值矩阵的容差很敏感。如果矩阵元素是浮点数且接近亏损,MATLAB 可能判定为非亏损,返回一个对角阵而不是带若当块的矩阵。另外前面提过,若当块的方向是上三角,教材可能是下三角。

解决办法:把矩阵转成符号形式再调jordan,jordan(sym(A))会走精确运算,结果稳定得多。方向问题只能靠对照定义解决,记住 MATLAB 是上三角块。如果矩阵规模大且必须用数值方法,考虑先用balance改善条件数再算。

4.3 现象:cdf2rdf 报错说输入维度不匹配

cdf2rdf要求输入的v和d必须来自eig的复数输出,且d必须是对角阵形式。如果你手动构造了一个实数矩阵传进去,或者d不是对角阵,就会报错。

解决办法:确保调用链是[v, d] = eig(A)之后直接[V, D] = cdf2rdf(v, d),中间不要对v或d做任何修改。如果A是实对称矩阵,eig返回的本来就是实数,不需要cdf2rdf,强行调用反而会出错。

4.4 现象:符号运算 solve 求特征值结果里有 root 表达式或复数

用solve(f)求符号多项式的根时,如果多项式次数大于 4,MATLAB 可能返回root形式的符号解,或者带复数。这不是错误,是代数基本定理的必然结果——五次以上没有通用根式解。

解决办法:对高次多项式,直接用roots求数值解,或者用vpa把符号解转成高精度数值。如果只关心实特征值,用real取实部后再判断虚部是否可忽略。我一般对超过 4 阶的矩阵直接走eig,不碰符号求解,省得跟root表达式较劲。

4.5 现象:balance 之后特征值变了

balance做的是相似变换,理论上不改变特征值。如果你发现变了,大概率是变换后的矩阵条件数改善,数值计算更准了,所以结果和没平衡之前有微小差异。这不是 bug,是精度提升的表现。

解决办法:把balance前后的特征值都算出来对比,差异应该在合理范围内。如果差异巨大,检查T矩阵是否可逆,balance返回的T在极端情况下可能接近奇异。我一般只在确认矩阵条件数很差时才用balance,日常计算不加这一步。

5. 进阶技巧:用符号工具箱做精确对角化与二次型标准化

前面几章走的是数值路线,快但有浮点误差。如果你需要精确结果——比如做二次型标准化、推导变换矩阵的解析形式——符号工具箱是更好的选择。下面这套流程是我在需要"干净"结果时的固定操作。

先看一个完整的符号对角化例子:

A = [1 2 2; 2 1 2; 2 2 1]; E = eye(3); syms x f = det(x*E - A) % 特征多项式,符号形式 eigenvalues = solve(f) % 精确特征值

f会返回x^3 - 3*x^2 - 9*x - 5,solve给出5, -1, -1。接下来对每个特征值求特征向量:

% 特征值 5 对应的特征向量 y = 5; B = y*E - A; b1 = sym(null(B)) % 基础解系,符号形式 % 特征值 -1 对应的特征向量 y = -1; B = y*E - A; b2 = sym(null(B)) % 返回两个基向量

null(B)返回的是齐次方程组B*Z = 0的基础解系。对于二重特征值 -1,b2是一个 3x2 的矩阵,两列分别是两个线性无关的特征向量。把b1和b2拼起来得到变换矩阵T:

T = [b1, b2] % 所有特征向量拼成的矩阵 D = T^-1 * A * T % 验证对角化,结果应该是精确对角阵

D会返回一个精确的对角阵,对角线上是5, -1, -1,非对角元严格为零。这就是符号运算的价值——没有浮点噪声,结果可以直接写进推导过程。

再看二次型标准化的场景。给定二次型矩阵A,要把它化成标准形,步骤是:

步骤操作对应代码
1确认矩阵对称isequal(A, A')
2求特征值和正交特征向量[P, D] = eig(A)
3构造正交变换x = P * y
4代入二次型得到标准形y' * D * y
5验证变换矩阵正交性P' * P接近单位阵

这套流程的关键在第 2 步:实对称矩阵的eig返回的P一定是正交阵,所以P^-1就是P',不用真的求逆。如果你拿到的P不正交,检查矩阵是否真的对称——数值上A - A'的范数应该在 1e-12 以下才算对称。

最后一个技巧是关于精度控制的。当你需要高精度数值结果时,vpa配合eig的符号输出能派上用场:

A = [1 2 2; 2 1 2; 2 2 1]; [V, D] = eig(sym(A)); % 符号形式求特征值 V_num = double(V); % 转回双精度 D_num = double(D); % 需要更高精度时用 vpa V_high = vpa(V, 32); % 32 位有效数字

vpa的第二个参数控制有效数字位数,默认是 32。位数越高计算越慢,一般 32 位足够工程使用。我通常在验证理论推导时才用vpa,日常计算double就够了。

从那以后我每次做对角化验证,都强制走一遍"符号转数值再对比"的流程——先用sym算精确结果,再用double转回来对比数值解,差异超过 1e-10 就回头查矩阵条件数。这个习惯帮我逮住过好几次隐藏的亏损矩阵问题。希望帮到你。

本文还有配套的精品资源,点击获取

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进