You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何避免使用NumPy进行线性代数运算时出现不精确结果?

矩阵代数运算的浮点精度问题与精确计算方案

问题详情

执行以下矩阵运算代码:

import numpy as np
from numpy import linalg

A = np.array([[1,2],[1,-1],[1,1]])
b = np.array([[1],[-1],[5]])

r = linalg.inv(A.transpose()@A)@A.transpose()@b

print(r)

输出结果为:

[[1.]
[1.]]

手动计算的预期结果是严格整数形式的[[1],[1]],但使用该浮点结果进行后续运算(如A@r)时,得到:

[[3.00000000e+00]
 [3.33066907e-16]
 [2.00000000e+00]]

而非预期的[[3],[0],[2]],需要找到避免浮点精度误差的方法,比如用分数运算替代浮点求逆。

解决方案

1. 利用fractions模块实现精确有理数运算

使用Python标准库的Fraction类型存储矩阵元素,所有运算都会以精确分数形式进行,彻底避免浮点误差:

from fractions import Fraction
import numpy as np

# 初始化分数类型的矩阵
A = np.array([[Fraction(1), Fraction(2)],
              [Fraction(1), Fraction(-1)],
              [Fraction(1), Fraction(1)]])
b = np.array([[Fraction(1)], [Fraction(-1)], [Fraction(5)]])

# 计算正规方程的精确解
A_T = A.transpose()
A_T_A = A_T @ A
# 手动计算2x2矩阵的逆(小矩阵可直接通过行列式精确求解)
det = A_T_A[0,0] * A_T_A[1,1] - A_T_A[0,1] * A_T_A[1,0]
A_T_A_inv = np.array([[A_T_A[1,1]/det, -A_T_A[0,1]/det],
                      [-A_T_A[1,0]/det, A_T_A[0,0]/det]])
r = A_T_A_inv @ A_T @ b

print(r)

运行后输出精确的整数结果:

[[1]
 [1]]

后续执行A@r会得到完全符合预期的[[3], [0], [2]]。

2. 结合numpy.linalg.lstsq与分数类型

使用numpy的最小二乘函数直接求解,同时指定元素类型为object存储分数,实现精确计算:

import numpy as np
from fractions import Fraction

# 初始化矩阵并转换为分数类型
A = np.array([[1,2],[1,-1],[1,1]], dtype=object)
b = np.array([[1],[-1],[5]], dtype=object)
A = np.vectorize(Fraction)(A)
b = np.vectorize(Fraction)(b)

# 最小二乘求解
r, _, _, _ = np.linalg.lstsq(A, b, rcond=None)

print(r)

该方法同样能输出精确的整数结果,避免浮点精度问题。

3. 对浮点结果进行舍入处理

如果不需要严格的分数精度,仅需后续运算结果符合预期,可以对浮点解进行合理舍入:

import numpy as np
from numpy import linalg

A = np.array([[1,2],[1,-1],[1,1]])
b = np.array([[1],[-1],[5]])

r = linalg.inv(A.transpose()@A)@A.transpose()@b
# 因预期结果为整数,直接取整
r = np.round(r).astype(int)

print(r)
# 后续计算验证
print(A@r)

运行后输出:

[[1]
 [1]]
[[3]
 [0]
 [2]]

内容的提问来源于stack exchange,提问作者shintuku

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 03:10:16