给定分数矩阵时,为什么 numpy 行列式 return 不是分数?
Why doesn't numpy determinant return a Fraction when given a Fraction matrix?
我想对有理矩阵进行运算。我使用模块 numpy
和 fractions
.
这是我的代码:
import numpy as np
from fractions import Fraction
m=np.matrix([[Fraction(1, 6), Fraction(8, 7)], [Fraction(1, 2), Fraction(3, 2)]])
print(np.linalg.det(m))
# Gives -0.321428571429
print(m[0,0]*m[1,1] - m[0,1]*m[1,0])
# Gives -9/28
由于计算行列式只需要用高斯方法进行有理运算,所以有理矩阵的行列式是有理的。
所以我的问题是:为什么 numpy return 是浮点数而不是分数?我怎样才能得到有理行列式?
请注意,对该矩阵的其他操作给出了合理的输出(例如 m.trace()
)。
NumPy 通过 LAPACK 中的下上分解例程计算矩阵的行列式。此例程只能处理浮点数。
在计算矩阵的行列式之前,linalg.det
检查其值的类型,然后通过调用名为 _commonType()
。此函数会将循环设置为 运行,用于双精度或复双精度值。
这是处理检查的函数 linalg.det
的 Python 部分:
def det(a):
a = asarray(a) # convert matrix to NumPy array
_assertNoEmpty2d(a)
_assertRankAtLeast2(a)
_assertNdSquareness(a)
t, result_t = _commonType(a) # input/output types established here
signature = 'D->D' if isComplexType(t) else 'd->d' # signature 'float->float' chosen
return _umath_linalg.det(a, signature=signature).astype(result_t)
在 运行ning 检查矩阵的形状并确定类型后,return
行将数组中的值传递给下-上分解的 LAPACK 实现,浮点数是return编辑。
尝试使用我们自己的类型签名绕过此类型检查会引发错误,指出没有为对象类型定义此类循环:
>>> np.linalg._umath_linalg.det(a, signature='O->O') # 'O' is 'object'
TypeError: No loop matching the specified signature was found for ufunc det
这意味着在使用 det
.
时无法将 Fraction
类型保留为 return 类型
trace()
等其他函数不执行与 det
相同的类型检查,对象类型可能会持续存在。 trace
只是通过调用 Fraction
对象的 __add__
方法对对角线求和,因此 Fraction
对象可以保持为 return 类型。
如果您想将行列式计算为有理数,可以研究 SymPy。记录了计算行列式等矩阵运算 here。
在我看来,这不是一个容易解决的问题,而且可能是 np.linalg
的大部分操作都依赖于 lapack 这一事实的限制。查看 numpy.linalg
的源代码,似乎在调用任何 lapack 例程之前调用了一个名为 _commonType
的例程。这会尝试为输入数组中包含的数据找到合适的类型,但如果无法确定类型,则假定类型为 double
。该数组在传递给 lapack 例程之前转换为结果类型。这很可能已经完成,因为几乎不可能处理所有可以传递的类型。
我从未使用过 Fraction
包,因此我无法为您提供返回 Fraction
对象矩阵的可行解决方案。我本来打算建议打电话给 m.astype(Fraction)
,但这似乎也行不通。
- 列表项
我想对有理矩阵进行运算。我使用模块 numpy
和 fractions
.
这是我的代码:
import numpy as np
from fractions import Fraction
m=np.matrix([[Fraction(1, 6), Fraction(8, 7)], [Fraction(1, 2), Fraction(3, 2)]])
print(np.linalg.det(m))
# Gives -0.321428571429
print(m[0,0]*m[1,1] - m[0,1]*m[1,0])
# Gives -9/28
由于计算行列式只需要用高斯方法进行有理运算,所以有理矩阵的行列式是有理的。
所以我的问题是:为什么 numpy return 是浮点数而不是分数?我怎样才能得到有理行列式?
请注意,对该矩阵的其他操作给出了合理的输出(例如 m.trace()
)。
NumPy 通过 LAPACK 中的下上分解例程计算矩阵的行列式。此例程只能处理浮点数。
在计算矩阵的行列式之前,linalg.det
检查其值的类型,然后通过调用名为 _commonType()
。此函数会将循环设置为 运行,用于双精度或复双精度值。
这是处理检查的函数 linalg.det
的 Python 部分:
def det(a):
a = asarray(a) # convert matrix to NumPy array
_assertNoEmpty2d(a)
_assertRankAtLeast2(a)
_assertNdSquareness(a)
t, result_t = _commonType(a) # input/output types established here
signature = 'D->D' if isComplexType(t) else 'd->d' # signature 'float->float' chosen
return _umath_linalg.det(a, signature=signature).astype(result_t)
在 运行ning 检查矩阵的形状并确定类型后,return
行将数组中的值传递给下-上分解的 LAPACK 实现,浮点数是return编辑。
尝试使用我们自己的类型签名绕过此类型检查会引发错误,指出没有为对象类型定义此类循环:
>>> np.linalg._umath_linalg.det(a, signature='O->O') # 'O' is 'object'
TypeError: No loop matching the specified signature was found for ufunc det
这意味着在使用 det
.
Fraction
类型保留为 return 类型
trace()
等其他函数不执行与 det
相同的类型检查,对象类型可能会持续存在。 trace
只是通过调用 Fraction
对象的 __add__
方法对对角线求和,因此 Fraction
对象可以保持为 return 类型。
如果您想将行列式计算为有理数,可以研究 SymPy。记录了计算行列式等矩阵运算 here。
在我看来,这不是一个容易解决的问题,而且可能是 np.linalg
的大部分操作都依赖于 lapack 这一事实的限制。查看 numpy.linalg
的源代码,似乎在调用任何 lapack 例程之前调用了一个名为 _commonType
的例程。这会尝试为输入数组中包含的数据找到合适的类型,但如果无法确定类型,则假定类型为 double
。该数组在传递给 lapack 例程之前转换为结果类型。这很可能已经完成,因为几乎不可能处理所有可以传递的类型。
我从未使用过 Fraction
包,因此我无法为您提供返回 Fraction
对象矩阵的可行解决方案。我本来打算建议打电话给 m.astype(Fraction)
,但这似乎也行不通。
- 列表项