为什么python不能在所有区域处理非常大的数字?

时间:2012-01-23 12:59:05

标签: python largenumber

我正在做一个难题,我必须处理10 ^ 18的订单数量。但是,我发现python无法在所有区域处理非常大的数字。

具体来说,如果我们分配一个= 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。

  1. 我该如何处理这类案件?什么是处理持有此类号码的谜题的最佳方式。 (教育/书籍参考将不胜感激)
  2. 为什么Python无法在range()/ xrange()
  3. 中处理它

    我想在python 2.7中使用inbuild函数来完成它。这不可能吗?

2 个答案:

答案 0 :(得分:10)

在Python 2.x中,rangexrange仅限于使用C long,而您的大整数对此来说太大了。此限制仅仅是由于rangexrange的实施选择。

在Python 3.x中,限制已被删除,您可以使用非常大的整数执行range()

>>> range(2**128)
range(0, 340282366920938463463374607431768211456)

official list of changes for Python 3有这样说:

  

range()现在的行为类似于xrange(),但它适用于任意大小的值。后者不再存在。


在Python 2.x中,range()函数返回了一个列表。显然,没有希望为非常大范围的所有元素分配内存。 xrange()函数返回xrange个对象。 documentation将其描述为“一个不透明的序列类型,它产生与相应列表相同的值,而不是实际同时存储它们”。文档继续这样说:

  

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

这解释了Python 2.x中的限制。


我不太清楚你可以用非常大范围的新Python 3支持做些什么。例如,我不建议你试试这个:

2**128 in range(2**128)

这将持续很长时间。


您在评论中指出您正在编写代码以计算大量数字。您可以使用以下代码在Python中轻松完成此任务:

i = 0
while i<N:
    doSomething(i)
    i += 1

但你会发现如果N是一个很大的数字,那么这将需要很长时间。根据您的问题,对于2 18 N值,没有任何解决方法。

答案 1 :(得分:1)

你的问题是Python 2.7中的range()构造了一个范围内每个值的显式列表 - 你根本没有足够的资源来构建这样的列表。

Python 3纠正了这种行为 - 并且只根据需要计算值......就像生成器表达式一样。

Python 2 xrange()函数不会对你有所帮助,因为它被约束为注册值...这对Python 2来说是一种妥协,以避免任何非平凡数字的范围()的巨大开销小。

一种方法可能是定义自己的生成器,它迭代任意整数 - 类似于:

def genrange(min,max,stride=1):
    val=min
    while val<max:
        yield val
        val+=stride

然而,我怀疑这可能是更大的方案中的错误 - 因为你不可能有足够的处理资源来迭代32位整数中的每个值 - 更不用说整数范围更大了而不是(32位)寄存器。我怀疑有一种更好的方法可以解决你的问题,而不是首先取决于范围。