为什么Python在所有领域不处理非常大的数字?
我正在做一个难题,需要处理10的18次方这么大的数字。不过,我发现Python在某些地方处理非常大的数字时有点问题。
具体来说,如果我把a设为1000000000000000000(也就是10的18次方),然后进行基本的加减乘除运算,它是可以正常工作的。但是,当我在range()函数中使用这个数字时,就会出现OverflowError的错误。
>>> a = 1000000000000000000
>>> a/2
500000000000000000L
>>> a*2
2000000000000000000L
>>> a+a
2000000000000000000L
>>> a*a
1000000000000000000000000000000000000L
>>> range(a)
Traceback (most recent call last):
File "<pyshell#5>", line 1, in <module>
range(a)
OverflowError: range() result has too many items
>>> xrange(a)
Traceback (most recent call last):
File "<pyshell#6>", line 1, in <module>
xrange(a)
OverflowError: Python int too large to convert to C long
我使用的是Python 2.7。
- 我该如何处理这种情况呢?有什么好的方法来解决包含这样大数字的难题吗?(如果能推荐一些教程或书籍就更好了)
- 为什么Python在range()/xrange()中处理不了这么大的数字呢?
我希望能在Python 2.7中使用内置函数来实现这个功能。这不是不可能吧?
2 个回答
你的问题在于,Python 2.7中的range()函数会生成一个包含范围内每个值的完整列表——这需要的资源太多了,你的设备可能承受不了。
Python 3对此进行了改进,它只在需要的时候计算值,就像使用生成器表达式一样。
Python 2中的xrange()函数也帮不了你,因为它只能记录一些值……这是Python 2为了避免range()在处理较大数字时消耗过多资源而做出的妥协。
一种解决方法是自己定义一个生成器,可以遍历任意整数,像这样:
def genrange(min,max,stride=1):
val=min
while val<max:
yield val
val+=stride
不过我怀疑,这可能在更大的问题上是个错误——因为你不太可能有足够的处理资源去遍历所有32位整数的每个值,更不用说超过32位寄存器的整数范围了。我觉得还有更好的方法来解决你的问题,而不需要依赖于范围。
在Python 2.x中,range
和xrange
的使用受到限制,只能处理C语言中的long
类型,而你的大整数可能超出了这个范围。这种限制是因为range
和xrange
的实现方式所决定的。
而在Python 3.x中,这个限制被取消了,你可以使用range()
来处理非常大的整数。
>>> range(2**128)
range(0, 340282366920938463463374607431768211456)
关于Python 3的变化,官方文档是这么说的:
range()
现在的表现就像以前的xrange()
,不过它可以处理任意大小的值。而xrange()
已经不再存在了。
在Python 2.x中,range()
函数返回的是一个列表。显然,对于非常大的范围,分配内存来存储所有元素是不现实的。xrange()
函数返回的是一个xrange
对象。文档中将其描述为“一个不透明的序列类型,它产生与对应列表相同的值,但并不同时存储所有这些值”。文档还提到:
xrange()
的设计目标是简单和快速。实现可能会施加一些限制来达到这个目标。Python的C语言实现限制所有参数为本地的C长整型(“短”Python整数),并且要求元素的数量也要适合本地的C长整型。
这就解释了Python 2.x中的限制。
我不太确定在Python 3中对非常大范围的支持可以用来做什么有用的事情。例如,我不建议你尝试这样做:
2**128 in range(2**128)
这会运行很长时间。
你在评论中提到你正在写代码来计算一个大数字。你可以用这样的代码轻松实现:
i = 0
while i<N:
doSomething(i)
i += 1
但是你会发现,如果N
是一个很大的数字,那么这会花费很长时间。对于像你提问中提到的218这样的N
值,这是无法避免的。