使用SymPy v1.12计算实矩阵特征值异常,是否为精度问题?
问题分析与解决方法
核心原因:浮点数精度误差
你看到的极小虚部(1e-64量级)完全是浮点数数值计算的舍入误差,属于精度问题。因为你创建矩阵时使用了1.0、-0.50这类浮点数(SymPy中对应Float类型),而非精确的有理数表示。当矩阵包含浮点数时,SymPy会切换到数值方法求解特征值,而非符号精确计算,数值过程中不可避免会引入极小的噪声误差,表现为本应不存在的虚部。
实矩阵的特征值必然是实数或共轭复数对,这些极小虚部可以直接视为数值噪声,实际对应严格的实数或共轭对。
解决方法
1. 使用精确有理数创建矩阵
将浮点数替换为SymPy的精确有理数类型,让SymPy用符号方法求解,得到完全符合实矩阵性质的特征值:
from sympy import Matrix, Rational M = Matrix([ [0, Rational(1), 0, Rational(1)], [Rational(1), 0, Rational(-1, 2), 0], [0, Rational(1), 0, Rational(-1)], [Rational(-1, 2), 0, Rational(1), 0] ]) print(M.eigenvals())
输出为精确的共轭对与实数:
{sqrt(5)/2 + sqrt(2)/2: 1, sqrt(5)/2 - sqrt(2)/2: 1, -sqrt(5)/2 + sqrt(2)/2: 1, -sqrt(5)/2 - sqrt(2)/2: 1}
2. 清理数值计算结果
如果必须使用浮点数矩阵,可以用nsimplify函数将结果近似为精确表达式,或手动过滤极小虚部:
from sympy import Matrix, nsimplify M = Matrix( [[0, 1.0, 0, 1.0], [1.0, 0, -0.50, 0], [0, 1.0, 0, -1.0], [-0.50, 0, 1.0, 0]]) eigenvals = M.eigenvals() cleaned_eigenvals = {nsimplify(val): mult for val, mult in eigenvals.items()} print(cleaned_eigenvals)
也可以直接忽略极小虚部,将其视为0:
from sympy import Matrix, re, im, Abs M = Matrix( [[0, 1.0, 0, 1.0], [1.0, 0, -0.50, 0], [0, 1.0, 0, -1.0], [-0.50, 0, 1.0, 0]]) eigenvals = M.eigenvals() cleaned_eigenvals = {} for val, mult in eigenvals.items(): if Abs(im(val)) < 1e-10: cleaned_eigenvals[re(val)] = mult else: cleaned_eigenvals[val] = mult print(cleaned_eigenvals)
总结
- 问题本质是浮点数数值计算的精度误差,与实矩阵的特征值性质无关;
- 优先使用精确有理数矩阵获取严格符合理论的特征值,若用浮点数矩阵,可通过SymPy的符号工具清理结果。
内容的提问来源于stack exchange,提问作者P11P
相关产品推荐
相关产品推荐

