简介:这份资源面向学习MATLAB数值计算与线性代数的学生及工程人员,聚焦矩阵处理这一核心主题,帮助读者掌握特征值、特征向量求解与矩阵对角化的实际操作方法。压缩包内为1个doc文档,大小约98KB,以实验讲义形式组织内容,围绕特征值与特征向量、若当标准形展开,涵盖特征多项式的poly与poly2str表示、eig函数求特征值与特征向量、balance函数提高计算精度、实对称矩阵的正交对角化以及jordan函数求若当标准形等知识点,并配有可直接运行的示例代码与运算结果对照。文档还整理了trace、sum、prod、cdf2rdf等相关函数的用法说明,便于读者在实验中随时查阅。目前已有727人学习下载,适合作为课堂实验配套材料或自学矩阵分析的参考,帮助读者理解D=V⁻¹AV等关系式的验证过程,快速上手MATLAB矩阵运算与矩阵分析。
1. 特征值算完就完事?先看清这份 MATLAB 矩阵处理实验包到底给什么
很多人拿到「matlab矩阵处理」这类实验包,第一反应是打开 MATLAB 把eig(A)敲一遍,看到输出一堆数字就以为掌握了。真到用的时候才发现:特征向量矩阵 V 的列顺序和 D 对不上、复特征值转实块不知道用哪个函数、若当标准形算出来和手算差一个转置——这些都不是eig本身的问题,而是实验包里那些「说明」段落没被当回事。这份实验六的资料围绕特征值与特征向量、若当标准形两条主线展开,覆盖poly、eig、jordan、balance、cdf2rdf、trace、sum、prod等命令,配了四个例题的完整代码和运算结果。它适合正在学线性代数配套实验的本科生,也适合需要把矩阵对角化、若当分解落到 MATLAB 代码里的工程从业者——尤其是那些被复数特征值和对角化验证折腾过的人。
2. 特征多项式与 eig 的三种调用:从定义出发把特征值算对
2.1 poly 与符号推导:两条路算同一个特征多项式
实验包给的第一条路是数值路线:poly(A)返回特征多项式系数的行向量,从最高次到常数项排列。以 2 阶矩阵为例,A=[1 0;2 3]得到p=[1 -4 3],对应 x²-4x+3。这里有个容易忽略的细节:poly返回的是系数向量,不是符号表达式,想变成可读形式得再走一步poly2str(p,'x')。第二条路是符号路线,用syms x加det(x*eye(n)-A)直接得到因式分解后的表达式。两条路结果一致,但用途不同——数值路线快、适合后续roots求根;符号路线适合教学演示和精确推导。
我一般会这样把两条路并排跑一遍,确认系数和符号结果对得上:
A = [1 0; 2 3]; p = poly(A); % 数值系数向量,降幂排列 f_num = poly2str(p, 'x'); % 转成可读字符串 syms x E = eye(size(A)); f_sym = det(x*E - A); % 符号特征多项式,通常已因式分解 f_sym = expand(f_sym); % 展开成标准多项式形式便于比对poly(A)的输入必须是方阵,非方阵会直接报错;poly2str的第二个参数是自变量名,换成't'或'lambda'都行,只影响显示。符号路线里eye(size(A))比手写eye(2)更稳,矩阵阶数一变不用改代码。expand那一步不是必须的,但做系数比对时展开后更容易和p逐项对照。实验包里例 6-1 的解二就是走poly加roots这条路,解三走符号加solve,两条路给出的特征值都是 5、-1、-1,互相印证。
2.2 eig 的三种返回形式与 V、D 的对应关系
eig的调用形式看着多,实际按「要什么给什么」分三类。d=eig(A)只返回特征值列向量,最省事但拿不到特征向量;[V,D]=eig(A)返回特征向量矩阵 V 和对角矩阵 D,满足A*V = V*D,等价于D = V^-1*A*V;[V,D]=eigs(A)在实验包里被描述为「按大小次序」返回,这里要留个心眼——eigs在标准 MATLAB 里是稀疏矩阵的部分特征值求解器,和eig不是一回事,实验包这段描述更接近教学简化,实际用的时候优先信eig。另外eig(A,B)形式解的是广义特征值问题A*x = lambda*B*x,实验包里把它写成「复数矩阵 A+Bi」是不准确的,别被带偏。
验证对角化是否成立,最直接的办法是把V^-1*A*V算出来看是不是 D:
A = [0 1 0 0; 1 0 0 0; 0 0 0 1; 0 0 1 0]; [V, D] = eig(A); err = norm(V^-1*A*V - D); % 数值误差,应接近机器精度 V_sym = sym(V); % 转符号形式看精确值 check = V_sym^-1 * sym(A) * V_sym;norm(...)那行是判断「对角化到底成没成」的硬指标,误差在 1e-12 量级以内就算通过。sym(V)把浮点特征向量转成根式形式,实验包里V^-1*A*V输出精确对角阵就是靠这一步。要注意V的列顺序和D对角线顺序严格一一对应:第 i 列是第 i 个对角元对应的特征向量,实验包说明(2)里「特征值 -1 对应 V 中第 1、2 列」就是这个对应关系。重特征值情况下 V 的列不唯一,任何一组线性无关的特征向量都合法,所以别拿自己的结果和实验包逐位比对,比V^-1*A*V是否等于 D 才有意义。
2.3 从零验证一个 3 阶矩阵的对角化
拿实验包例 6-1 的矩阵走一遍完整流程,重点看「可对角化」这个结论怎么用代码确认,而不是靠肉眼:
A = [1 2 2; 2 1 2; 2 2 1]; [V, D] = eig(A); disp(diag(D)') % 特征值:5, -1, -1 resid = norm(A*V - V*D); % 残差,验证 A*V = V*D condV = cond(V); % 特征向量矩阵条件数diag(D)'把对角元转成行向量显示,比看整个 D 清爽。resid是A*V = V*D的直接残差,比重算V^-1*A*V少一次求逆,数值上更稳。condV是很多人会漏的一步:条件数大说明特征向量矩阵接近奇异,即便理论上可对角化,数值上V^-1也会放大误差。这个矩阵的condV在个位数到几十量级,属于健康范围;如果遇到条件数上万的情况,V^-1*A*V算出来一堆非对角小量,不是代码写错,是矩阵本身数值病态。实验包解一里inv(V)*A*V输出-0.0000这种量,就是浮点误差的正常表现,别当成 bug 去改。
3. 实对称矩阵与复特征值:对角化的两条分支怎么走
3.1 实对称矩阵用 eig 直接正交对角化
实对称矩阵有个好性质:特征值全实、特征向量可以选成正交的,所以[P,D]=eig(A)出来的 P 直接就是正交阵,满足P'*P = I、D = P'*A*P。实验包里那个 3 阶实对称矩阵[2 2 -2; 2 5 -4; -2 -4 5]就是标准例子,特征值 1、1、10。这里的关键不是会敲eig,而是知道为什么 P 能当正交变换矩阵用——因为对称矩阵的不同特征值对应特征向量自动正交,重特征值对应的子空间里再做一次正交化就行,eig内部已经处理了。
验证正交性要单独做一步,别只看 D 对不对:
A = [2 2 -2; 2 5 -4; -2 -4 5]; [P, D] = eig(A); orth_err = norm(P'*P - eye(3)); % 正交性误差 diag_err = norm(P'*A*P - D); % 对角化误差两个误差都应该在 1e-14 量级。P'*P而不是P^-1*P,因为对称矩阵场景下转置就是逆,用转置更快也更稳。如果orth_err明显偏大,先检查 A 是不是真的对称——issymmetric(A)一行就能确认,很多时候是输入时某个元素符号写反了。实验包这段只给了[P,D]=eig(A)和一句「P 为正交阵」,实际做二次型标准化时,变换矩阵就是这里的 P,标准形系数就是 D 的对角元,这个对应关系要记牢。
3.2 复特征值用 cdf2rdf 转实块对角
实矩阵也可能出复特征值,而且必然成共轭对出现。实验包例 6-2 的矩阵[0 2 1; -2 0 3; -1 -3 0]特征值是 0 和 ±3.7417i,eig给出的 D 是对角线上带复数的矩阵。想让结果留在实数域,用cdf2rdf把共轭对换成 2×2 实块:
A = [0 2 1; -2 0 3; -1 -3 0]; [V, D] = eig(A); [Vr, Dr] = cdf2rdf(V, D); % 复对角转实块对角 blk_err = norm(A*Vr - Vr*Dr); % 验证实形式下的特征关系cdf2rdf的输入必须是eig出来的(V,D)对,顺序不能反。输出的Dr对角线上,原来的共轭对a±bi变成一个 2×2 块[a b; -b a],这就是实验包说的「用 2×2 实数块代替共轭复数对」。blk_err验证的是A*Vr = Vr*Dr,注意这里Dr不是对角阵而是块对角阵,所以不能用diag去取特征值。实验包还演示了从 V 的列还原复特征向量:V2 + V3*i和V2 - V3*i是一对共轭向量,这个关系在需要显式复特征向量时用得上。踩过的坑是有人把cdf2rdf的输出再喂给eig,结果当然不对——它已经是实块形式,不再是标准特征分解的输入格式。
3.3 迹与行列式的交叉验证
实验包例 6-3 用trace和det做特征值的和与积校验,这是最便宜的自检手段:特征值之和等于迹,之积等于行列式。代码很短但值得养成习惯:
A = [1 2 2; 2 1 2; 2 2 1]; d = eig(A); trace_err = abs(trace(A) - sum(d)); % 和校验 det_err = abs(det(A) - prod(d)); % 积校验sum(d)对列向量默认按列求和,等价于sum(d,1);prod(d)同理。两个误差都应在 1e-10 以内。这里sum和prod的dim参数在实验包里专门讲了:dim=1按列、dim=2按行,对矩阵整体求和要sum(sum(A,1),2)或直接sum(A(:))。我一般用A(:)展平再求和,少一层嵌套不容易写错维度。这个校验在调试eig结果异常时特别有用——如果和或积对不上,八成是矩阵输错了或者用了错误的求解函数,而不是eig本身出问题。
4. 若当标准形:jordan 的块结构和对角化的边界
4.1 jordan 的输出结构与上三角约定
jordan(A)返回 A 的若当标准形 J,实验包特别标注「若当块按上三角形定义」。这句话是理解输出的钥匙:标准教材里若当块常写成下三角(1 在次对角线),MATLAB 给的是上三角(1 在超对角线)。例 6-4 的矩阵[-1 -2 6; -1 0 3; -1 -1 4]输出 J 是主对角全 1、右上角一个 1 的 3×3 块,说明这个矩阵只有一个特征值 1 且几何重数小于代数重数,不可对角化。
A = [-1 -2 6; -1 0 3; -1 -1 4]; J = jordan(A); [V, Js] = jordan(A); % 同时拿广义特征向量矩阵 similar_err = norm(V^-1*A*V - Js);[V,J]=jordan(A)这个双输出形式实验包没展开,但实际很有用:V 的列是广义特征向量,满足A*V = V*J。similar_err验证相似关系,注意jordan内部可能做符号运算,大矩阵上会明显变慢。单输出J=jordan(A)只给标准形不给变换矩阵,做相似变换验证时不够用。另一个边界是:jordan对数值矩阵的判定依赖容差,接近亏损的矩阵可能因为浮点误差被判成可对角化或反之,这时候转符号输入jordan(sym(A))能得到精确结果,代价是速度。
4.2 可对角化与不可对角化的判定路径
判断一个矩阵能不能对角化,实验包给了三条路:eig看 V 是否满秩、poly加roots看是否有重根且对应特征向量不足、符号null求基础解系看维数。最工程化的做法是先算eig再看rank(V):
A = [1 2 2; 2 1 2; 2 2 1]; [V, D] = eig(A); n = size(A, 1); is_diag = (rank(V) == n); % 特征向量满秩才可对角化rank(V)==n是充要条件:V 满秩意味着有 n 个线性无关特征向量,能张成整个空间。重特征值场景下eig可能返回近似线性相关的列,rank会如实反映。实验包例 6-1 的解三用null(B)求(lambda*E-A)X=0的基础解系,这是从定义出发的精确路线,适合符号推导;工程上rank(V)更快。两条路结论应一致,不一致时优先信符号路线,因为数值rank有容差。不可对角化的典型信号是rank(V) < n且jordan输出里出现超对角线 1,这时候别再硬套V^-1*A*V,改用若当分解。
4.3 balance 预处理对特征值精度的影响
balance(A)做的是相似变换下的行列平衡,把矩阵元素量级拉近,减少eig的数值误差。实验包只给了格式没给例子,实际用法是:
A = [1e-8 1; 1 1e8]; % 量级悬殊的矩阵 [T, B] = balance(A); eig_raw = eig(A); eig_bal = eig(B); % 平衡后矩阵的特征值B = T^-1*A*T,特征值和 A 相同但数值条件更好。eig_bal和eig_raw理论上相等,量级悬殊时前者更可信。注意balance不改变特征值只改善计算过程,所以别指望它「修正」错误结果。对已经良态的矩阵,balance收益很小,不必无脑加。我一般在矩阵元素跨好几个数量级时才用它,普通教学矩阵直接eig就够。
5. 避坑与排查:这五处翻车点我踩过
5.1 现象:V^-1AV 算出来非对角元一堆小量
原因:矩阵本身数值病态,特征向量矩阵条件数大,求逆放大误差;或者矩阵根本不可对角化,eig返回的 V 不满秩。解决:先算cond(V)和rank(V),条件数过大时改用balance预处理或转符号计算;rank(V)<n时改用jordan,别硬做对角化验证。
5.2 现象:cdf2rdf 报错或输出维度不对
原因:输入顺序写反成cdf2rdf(D,V),或者把已经转过的实块矩阵再喂进去。解决:严格按[Vr,Dr]=cdf2rdf(V,D)的顺序,输入必须是eig的原始双输出;转完一次就够,别重复调用。
5.3 现象:jordan 结果和手算差一个转置
原因:MATLAB 若当块按上三角定义,手算教材多用下三角。解决:比对时把 J 转置再和手算结果对照,或者统一按「超对角线为 1」的约定理解。这不是算错,是约定差异。
5.4 现象:eigs 和 eig 结果对不上
原因:eigs是部分特征值求解器,默认只返回模最大的几个,且对输入矩阵类型有要求;实验包把它描述成「按大小次序返回全部特征值」是教学简化。解决:要全部特征值就用eig,要部分大特征值才用eigs,并显式指定个数eigs(A,k)。
5.5 现象:符号计算 solve 求出的根顺序和 eig 不一致
原因:solve按符号求解顺序输出,eig按数值算法顺序输出,两者都不保证和教材顺序一致。解决:别依赖顺序做逐位比对,用sort统一排序,或者用trace/det做和与积的交叉校验,比顺序更可靠。
6. 把实验包变成可复用脚本:一个自动校验模板
实验包的代码是分散的,真正干活时我习惯把它们收进一个带自检的脚本模板,每次换矩阵只改第一行。核心思路是:算完特征分解后强制走一遍残差、迹、行列式三重校验,任何一项超阈值就报警,而不是靠肉眼看输出。
function check_eig(A) % A: 待分析方阵;输出特征值、对角化可行性、三重校验误差 n = size(A, 1); [V, D] = eig(A); d = diag(D); resid = norm(A*V - V*D) / max(1, norm(A)); % 相对残差 tr_err = abs(trace(A) - sum(d)) / max(1, abs(trace(A))); dt_err = abs(det(A) - prod(d)) / max(1, abs(det(A))); fprintf('特征值: %s\n', mat2str(d', 4)); fprintf('rank(V)=%d / n=%d, 可对角化: %d\n', rank(V), n, rank(V)==n); fprintf('相对残差 %.2e, 迹误差 %.2e, 行列式误差 %.2e\n', resid, tr_err, dt_err); if rank(V) < n fprintf('不可对角化,若当形:\n'); disp(jordan(A)); end endresid用相对残差而不是绝对残差,矩阵元素量级大时绝对残差天然偏大,相对值才有可比性。max(1, ...)防止分母为零。rank(V)==n那行直接给出可对角化判定,不可对角化时自动补打若当形,省得再手动跑一次。mat2str(d',4)控制显示 4 位有效数字,输出不刷屏。这个模板对实对称、复特征值、亏损矩阵都适用,唯一要补的是复特征值场景下加一行cdf2rdf分支。
进阶一点的做法是把校验阈值做成参数,批量跑一组矩阵时收集误差分布,比单个矩阵看输出更能发现系统性问题。比如某批矩阵残差普遍在 1e-8 而不是 1e-14,说明这批数据本身条件数偏高,后续做对角化相关的数值计算要提前降精度预期。这个习惯是从一次批量处理里养成的:当时几十个矩阵里混进一个接近亏损的,单看每个都「差不多对」,批量统计残差才把它揪出来。从那以后我每次做特征分解相关的脚本,都强制走一遍残差加迹与行列式的三重校验,再决定结果能不能直接往下游传。希望帮到你。
本文还有配套的精品资源,点击获取