5

我正在做一个难题,我必须处理 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。

  1. 我该如何处理这种情况?,处理持有这些数字的谜题的最佳方法是什么。(教程/书籍参考将不胜感激)
  2. 为什么 Python 不能在 range()/xrange() 中处理它

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

4

2 回答 2

10

在 Python 2.x 中,range仅限xrange于使用 Clong并且您的大整数太大了。这种限制仅仅是由于 和 的实现range选择xrange

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

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

Python 3的官方更改列表是这样说的:

range()现在表现得像以前一样xrange(),除了它适用于任意大小的值。后者不再存在。


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

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是一个很大的数字,那么这将需要很长时间。根据您的问题,N对于 2 18阶的值,没有任何解决方法。

于 2012-01-23T13:06:06.217 回答
1

您的问题是 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 位)寄存器。我怀疑有更好的方法来解决您的问题,它首先不依赖于范围。

于 2012-01-23T13:12:40.460 回答