numpy矩阵求幂给出负值
问题内容:
我想NumPy
在斐波那契问题中使用它,因为它在矩阵乘法中非常有效。您知道有一种用矩阵求斐波那契数的方法[[1, 1], [1, 0]]
。
我写了一些非常简单的代码,但是增加后n
,矩阵开始给出负数。
import numpy
def fib(n):
return (numpy.matrix("1 1; 1 0")**n).item(1)
print fib(90)
# Gives -1581614984
这可能是什么原因?
注意: linalg.matrix_power
也给出负值。
注意2: 我尝试了从0到100的数字。它在47之后开始给出负值。这是否是一个大整数问题,因为NumPy是用C编码的?如果是这样,我该如何解决?
编辑:
使用常规pythonlist
矩阵linalg.matrix_power
也给出了负面结果。还让我补充一下,并非所有结果在47之后都是负数,而是随机发生的。
Edit2: 我尝试使用建议的方法@ AlbertoGarcia-
Raboso。它解决了负数问题,但是出现了另一个问题。它给出了-5.168070885485832e+19
我需要的答案-51680708854858323072L
。因此,我尝试使用int()
,将其转换为L
,但是现在由于精度下降似乎答案不正确。
问题答案:
您看到出现负值的原因是因为NumPy默认将np.int32
dtype用于矩阵。
此dtype可以表示的最大正整数是2 31
-1,它是2147483647。不幸的是,这比第47个斐波那契数(2971215073)要少。结果溢出导致出现负数:
>>> np.int32(2971215073)
-1323752223
使用更大的整数类型(如np.int64
)可以解决此问题,但这只是暂时的:如果继续要求越来越大的斐波那契数,您仍然会遇到问题。
唯一确定的解决方法是使用无限制大小的整数类型,例如Python的int
类型。为此,将矩阵修改为以下np.object
类型:
def fib_2(n):
return (np.matrix("1 1; 1 0", dtype=np.object)**n).item(1)
该np.object
类型允许矩阵或数组容纳本机Python类型的任何混合。本质上,矩阵现在不再像保存机器类型那样运行,就像Python列表一样,仅由指向内存中整数对象的指针组成。Python整数现在将用于计算斐波那契数,并且溢出不是问题。
>>> fib_2(300)
222232244629420445529739893461909967206666939096499764990979600
这种灵活性是以降低性能为代价的:NumPy的速度源于整数/浮点类型的直接存储,可以由您的硬件操纵。