NumPy数组中的整数溢出
import numpy as np
a = np.arange(1000000).reshape(1000,1000)
print(a**2)
用这段代码我得到了这个结果。为什么会出现负值呢?
[[ 0 1 4 ..., 994009 996004 998001]
[ 1000000 1002001 1004004 ..., 3988009 3992004 3996001]
[ 4000000 4004001 4008004 ..., 8982009 8988004 8994001]
...,
[1871554624 1873548625 1875542628 ..., -434400663 -432404668 -430408671]
[-428412672 -426416671 -424420668 ..., 1562593337 1564591332 1566589329]
[1568587328 1570585329 1572583332 ..., -733379959 -731379964 -729379967]]
4 个回答
2
numpy中的整数类型是固定宽度的,这意味着它们能表示的数字范围是有限的。当你尝试使用超出这个范围的数字时,就会出现整数溢出的问题。
9
Python中的整数没有这个问题,因为当它们超出范围时,会自动变成Python的长整数。
所以如果你真的把int64的范围超出了,解决办法之一就是在numpy数组中使用Python的整数:
import numpy
a=numpy.arange(1000,dtype=object)
a**20
22
在你的平台上,np.arange 返回的是一种数据类型为 'int32' 的数组:
In [1]: np.arange(1000000).dtype
Out[1]: dtype('int32')
这个数组里的每个元素都是一个 32 位的整数。当你对这些整数进行平方运算时,结果会超出 32 位整数的范围。结果被截断到 32 位,但仍然被当作 32 位整数来处理,这就是为什么你会看到负数的原因。
补充:在这种情况下,你可以通过在平方之前先创建一个数据类型为 'int64' 的数组来避免整数溢出:
a=np.arange(1000000,dtype='int64').reshape(1000,1000)
请注意,你发现的问题是使用 numpy 时固有的风险。你需要仔细选择数据类型,并提前知道你的代码不会导致算术溢出。为了提高速度,numpy 在发生这种情况时不会给你任何警告。
有关此问题的讨论,请查看 http://mail.scipy.org/pipermail/numpy-discussion/2009-April/041691.html。