NumPy数组中的整数溢出

10 投票
4 回答
9404 浏览
提问于 2025-04-15 17:25
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

撰写回答