numpy.sum()在大型数组上给出奇怪的结果

rog*_*osh 4 python numpy python-2.7

我似乎找到了一个陷阱,使用.sum()numpy数组,但我无法找到一个解释.从本质上讲,如果我尝试总结大阵,然后我开始变得无厘头的答案,但这种情况发生默默,我不能使输出足够好,谷歌的事业感.

例如,这与预期完全一样:

a = sum(xrange(2000)) 
print('a is {}'.format(a))

b = np.arange(2000).sum()
print('b is {}'.format(b))
Run Code Online (Sandbox Code Playgroud)

为两者提供相同的输出:

a is 1999000
b is 1999000
Run Code Online (Sandbox Code Playgroud)

但是,这不起作用:

c = sum(xrange(200000)) 
print('c is {}'.format(c))

d = np.arange(200000).sum()
print('d is {}'.format(d))
Run Code Online (Sandbox Code Playgroud)

给出以下输出:

c is 19999900000
d is -1474936480
Run Code Online (Sandbox Code Playgroud)

在更大的阵列上,可以获得积极的结果.这更加阴险,因为我可能不会发现一些不寻常的事情正在发生.例如:

e = sum(xrange(100000000))
print('e is {}'.format(e))

f = np.arange(100000000).sum()
print('f is {}'.format(f))
Run Code Online (Sandbox Code Playgroud)

给出这个:

e is 4999999950000000
f is 887459712
Run Code Online (Sandbox Code Playgroud)

这是与数据类型有关,甚至使用python float似乎解决了这个问题:

e = sum(xrange(100000000))
print('e is {}'.format(e))

f = np.arange(100000000, dtype=float).sum()
print('f is {}'.format(f))
Run Code Online (Sandbox Code Playgroud)

赠送:

e is 4999999950000000
f is 4.99999995e+15
Run Code Online (Sandbox Code Playgroud)

我没有Comp的背景.科学.并发现自己卡住了(也许这是一个骗局).我试过的事情:

  1. numpy数组具有固定的大小.不; 似乎表明我应该先打一局MemoryError.
  2. 我可能会以某种方式安装32位(可能不相关); 不,我跟着这个并确认我有64位.
  3. 奇怪sum行为的其他例子; nope()我发现了这个,但我看不出它是如何适用的.

有人可以简要解释一下我缺少的东西并告诉我需要阅读的内容吗?此外,除了记住dtype每次定义,有没有办法阻止这种情况发生或发出警告?

可能相关:

Windows 7的

numpy 1.11.3

在Python 2.7.9上耗尽了Enthought Canopy

wim*_*wim 6

这显然是numpy的整数类型溢出32位。通常,您可以使用以下命令将 numpy 配置为在这种情况下失败np.seterr

>>> import numpy as np
>>> np.seterr(over='raise')
{'divide': 'warn', 'invalid': 'warn', 'over': 'warn', 'under': 'ignore'}
>>> np.int8(127) + np.int8(2)
FloatingPointError: overflow encountered in byte_scalars
Run Code Online (Sandbox Code Playgroud)

但是,sum明确记录了行为“溢出时不会引发错误”,因此您可能会运气不好。使用 numpy 通常是为了方便而牺牲性能!

但是,您可以手动指定累加器的数据类型,如下所示:

>>> a = np.ones(129)
>>> a.sum(dtype=np.int8)  # will overflow
-127
>>> a.sum(dtype=np.int64)  # no overflow
129
Run Code Online (Sandbox Code Playgroud)

请观看票证#593,因为这是一个悬而未决的问题,有时 numpy 开发人员可能会修复它。


Mik*_*ler 5

在Windows上(在64位系统上),如果从Python int转换的默认整数NumPy使用的是32位.在Linux和Mac上它是64位.

指定一个64位整数,它将起作用:

d = np.arange(200000, dtype=np.int64).sum()
print('d is {}'.format(d))
Run Code Online (Sandbox Code Playgroud)

输出:

c is 19999900000
d is 19999900000
Run Code Online (Sandbox Code Playgroud)

虽然不是最优雅,但你可以做一些猴子修补,使用functools.partial:

from functools import partial

np.arange = partial(np.arange, dtype=np.int64)
Run Code Online (Sandbox Code Playgroud)

从现在开始np.arange,默认情况下使用64位整数.