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)
上面的处理方式显然有点矫枉过正 step
s 而不是默认值 1;如果不需要 step
支持,它可以大大简化。
在 CPython(参考解释器)中,这应该 运行 比使用 Python 级代码(需要重复执行字节代码)更有效;一旦初始化,islice
和 count
在 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
不能处理的情况,这还算不错。
有没有 运行 范围超过 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)
上面的处理方式显然有点矫枉过正 step
s 而不是默认值 1;如果不需要 step
支持,它可以大大简化。
在 CPython(参考解释器)中,这应该 运行 比使用 Python 级代码(需要重复执行字节代码)更有效;一旦初始化,islice
和 count
在 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
不能处理的情况,这还算不错。