Python - 大数

Python - large numbers

有没有 运行 范围超过 13 个字符的 for 循环? 例如:

for i in range (1000000000000):

我知道这行不通,但有什么办法吗?

对于python 2.7,使用xrange(它使用生成器而不是初始化一个大列表)代替:

for i in xrange(1000000000000):

使用 xrange 也会给您带来 Python int too large to convert to C long 错误,因为数字必须适合 C 长。要克服此问题,请使用 itertools.count 创建您自己的范围:

  from itertools import count

def myx_range(start, end):
    return iter(count(start).next, end)

如果您想使用与 python 3 相同的逻辑:

from itertools import count

def myx_range(start, end):
    cn = count(start)
    return iter(lambda: next(cn), end)

while循环:

from itertools import count

def myx_range(start, end):
    while start < end:
        yield start
        start += 1

多头是 windows 上的 32bit,所以您将使用 xrange 和这么大的数字来达到极限。

参见 what-is-the-bit-size-of-long-on-64-bit-windows

请记住,存储在处理器寄存器中的最小值和最大值是有限制的。这意味着并非所有模块都可以接收大数字作为参数。

如果bounds和step在[-sys.maxsize-1,sys.maxsize)范围内,元素总数为<= sys.maxsize,则xrange你了解了吗

如果没有,itertools 提供您需要的部分来完全重新实现 xrange(而且效率也很高,将所有工作推到 CPython 中的 C 层)以达到目的生成(xrange 是一个真实的对象,可以一遍又一遍地生成并支持一些其他功能;这只生成,每次调用只生成一次):

from itertools import count, islice

def myxrange(stop, *args):
    '''Replacement for xrange to generate ranges of arbitrarily large numbers efficiently
    '''
    start, step = 0, 1  # Defaults when only one argument passed
    if args:
        if len(args) > 2:
            raise TypeError("myxrange expected at most 3 arguments, got {}".format(len(args)))
        start = stop  # When 2+ args passed, stop is really start
        stop, step = (args + (1,))[:2]  # Use step if given, otherwise 1
    # islice slices x items, we need to calculate the number to slice
    # from the bounds given
    numitems = (stop - start + (step - (1 if step > 0 else -1))) // step
    return islice(count(start, step), numitems)

上面的处理方式显然有点矫枉过正 steps 而不是默认值 1;如果不需要 step 支持,它可以大大简化。

在 CPython(参考解释器)中,这应该 运行 比使用 Python 级代码(需要重复执行字节代码)更有效;一旦初始化,islicecount 在 C 层完成所有工作,这可以显着提高性能。例如,与其他答案中基于 while 的循环相比,在 ipython 运行ning on Python 2.7 在我的机器上:

>>> %timeit -r5 list(xrange(10, 2000))
100000 loops, best of 5: 15.2 μs per loop
>>> %timeit -r5 list(myxrange(10, 2000)) # Version in my answer
10000 loops, best of 5: 24.9 μs per loop
>>> %timeit -r5 list(myxrange2(10, 2000)) # Version using while from Padraig's answer
1000 loops, best of 5: 173 μs per loop

# Padraig's count based version takes 124 μs, though it could be optimized
# down to ~59 μs by changing it to the C layer version (though either
# version breaks if start > stop):
def myxrange(start, stop):
    return iter(count(start).next, end)

即使有模仿 xrange 非标准参数原型的开销,count+islice 代码的开销也仅比 xrange 高出 50% ,考虑到它实际上可以处理 xrange 不能处理的情况,这还算不错。