问题描述
我想对有理矩阵执行运算.我使用模块numpy
和fractions
.
I want to perform operations on rational matrices. I use the modules numpy
and 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
由于计算行列式只需要使用高斯方法进行有理运算,因此有理矩阵的行列式是有理的.
Since computing the determinant only require rational operations with the Gauss' method, the determinant of a rational matrix is rational.
所以我的问题是:为什么numpy返回浮点数而不是分数?如何获得一个合理的行列式?
So my questions are: why does numpy return a float and not a Fraction? How can I get a rational determinant?
请注意,此矩阵上的其他运算会给出合理的输出(例如m.trace()
).
Note that other operations on this matrix give a rational output (for instance m.trace()
).
推荐答案
NumPy通过LAPACK中较低的上层分解例程来计算矩阵的行列式.此例程只能处理浮点数.
NumPy computes the determinant of the matrix by a lower upper decomposition routine in LAPACK. This routine can only handle floating point numbers.
在计算矩阵的行列式之前,linalg.det
检查其具有的值的类型,然后通过调用名为_commonType()
的函数来建立应运行的内部循环的类型.此功能将循环设置为运行double值或复数double值.
Before calculating the determinant of the matrix, linalg.det
checks the types of values it has and then establishes the type of internal loop that should be run using a call to a function named _commonType()
. This function will set the loop to run for either double or complex-double values.
这是函数的Python部分linalg.det
处理检查:
Here is the Python part of the function linalg.det
that handles the checking:
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)
对矩阵的形状进行检查并确定类型后,return
行将数组中的值传递给下-上分解的LAPACK实现,并返回浮点数.
After running checks on the shape of the matrix and determining types, the return
line passes the values in the array to the LAPACK implementation of the lower-upper decomposition and a float is returned.
尝试使用我们自己的类型签名绕过此类型检查会引发错误,指出没有为对象类型定义这样的循环:
Trying to bypass this type checking with a type signature of our own raises an error saying that no such loop is defined for object types:
>>> 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
类型保留为返回类型.
This implies than it is not possible to keep the Fraction
type as the return type when using det
.
其他功能,例如 不会执行与det
相同的类型检查,并且对象类型可能会持续存在. trace
通过调用Fraction
对象的__add__
方法简单地将对角线求和,因此可以将Fraction
对象保留为返回类型.
Other functions such as trace()
do not do the same type checking as det
and the object type may persist. trace
simply sums the diagonal by calling the Fraction
object's __add__
method, so a Fraction
object can be kept as the return type.
如果要将行列式计算为有理数,则可以调查SymPy. 此处
If you want to calculate the determinant as a rational number, you could investigate SymPy. Matrix operations such as calculating determinants are documented here.
这篇关于给定分数矩阵时,为什么numpy行列式不返回分数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!