迭代到大范围时的Python内存错误

时间:2016-04-30 15:52:10

标签: python python-2.7

sum = 0
x = 2**32
for i in range(x):
     sum=sum+i;
print sum 

我在循环到MemoryError范围时获得2**32。有没有办法在不耗尽内存的情况下进行迭代?

3 个答案:

答案 0 :(得分:3)

  1. range在内存中创建一个列表。使用xrange获取一个生成器对象,该对象在一段时间内为您提供一个数字。

  2. 有更好的方法可以将1n之间的一系列数字相加,例如(n(n+1))/2

答案 1 :(得分:2)

对于蛮力方法,请尝试以下方法:

x = sum(i for i in xrange(2**32))

以上将更有效率,因为它使用xrange来懒惰地生成数字,并且它还使用带有sum()的生成器表达式来避免生成立即丢弃的临时数据。

但这仍需要一些时间,因为2**32是一个很大的数字。解决这个问题的聪明方法是使用@DeepSpace建议的公式:

n = 2**32 - 1
x = (n * (n + 1)) / 2

答案 2 :(得分:2)

当您尝试创建包含前2 ^ 32个非负整数的列表(我在Windows 10系统上使用Python 2.7.11)时会发生这种情况:

>>> for i in range(2**32): pass
... 
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
OverflowError: range() result has too many items

有人可能会认为,如果问题是在内存中同时存在如此大量的项目,那么解决方案可能是通过生成器一次处理一个项目......但它不是:

>>> for i in xrange(2**32): pass
... 
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
OverflowError: Python int too large to convert to C long

xrange()内置函数的文档解释了出现此错误的原因:

  

CPython实现细节:xrange()旨在简单快速。实现可能会对此实施限制。 Python的C实现将所有参数限制为本机C long(“短”Python整数),并且还要求元素的数量适合本机C long。

问题是2 ^ 32不能作为输入参数传递给xrange,因为该数字大于Python中最大“短”整数。试着这样说服自己:

>>> import sys
>>> sys.maxint       # 2^31-1
2147483647
>>> sys.maxint + 1   # 2^31 is automatically converted to "long" int
2147483648L
>>> 2**31
2147483648L

如果需要重复执行超过2 ^ 31次的计算(在以下示例中为2 ^ 34次),则可以使用嵌套for循环:

>>> loops = 0
>>> for i in xrange(2**4):
...    for j in xrange(2**30):
...        # do stuff
...        loops += 1
...
>>> loops
17179869184L
>>> 2**34
17179869184L

上面的代码是一个相当天真的解决方法。 while 循环似乎是一个更加充分的解决方案:

>>> loops = 0
>>> while loops < 2**34:
...    # do stuff
...    loops += 1
...
>>> loops
17179869184L