2013-05-04 65 views
0
val = long(raw_input("Please enter the maximum value of the range:")) + 1 
start_time = time.time() 
numbers = range(0, val) 
shuffle(numbers) 

我找不到一个简单的方法来使这项工作具有非常大的输入 - 任何人都可以提供帮助吗?Python:数字范围非常大?

我看到一个这样的问题 - 但我无法实现他们描述的范围函数与洗牌工作。谢谢。

+4

有多大?根据答案,这是微不足道的。 – 2013-05-04 22:59:41

+1

怎么回事?你的投入有多大? – 2013-05-04 22:59:53

+1

你想用'shuffle'的结果做什么? – Eric 2013-05-04 23:08:49

回答

4

以内存有效的方式获得范围[0, n)的随机置换;你可以使用numpy.random.permutation()

import numpy as np 

numbers = np.random.permutation(n) 

如果您只需要在范围如值的小部分,从[0, n)范围得到k随机值:

import random 
from functools import partial 

def sample(n, k): 
    # assume n is much larger than k 
    randbelow = partial(random.randrange, n) 
    # from random.py 
    result = [None] * k 
    selected = set() 
    selected_add = selected.add 
    for i in range(k): 
     j = randbelow() 
     while j in selected: 
      j = randbelow() 
     selected_add(j) 
     result[i] = j 
    return result 


print(sample(10**100, 10)) 
+0

真的不需要非标准模块NumPy,在这里:标准'array'模块(请参阅我的答案)使数字列表具有与NumPy相同的内存占用空间。 – EOL 2013-05-05 06:21:29

+0

我删除了不必要的索引使用和无列表初始化。我还将'random.randint()'简化为更合适的'random.randrange()',它是为这种情况明确设计的。我也给函数一个适当的文档字符串。 – EOL 2013-05-05 06:43:47

+0

@EOL:我改变了'randrange()',但其余的可能不合适。 – jfs 2013-05-05 06:57:46

0

要注意的重要一点是,它会是不可能对于计算机如果它大于几十亿个元素,则具有存储器中的数字列表:其存储器占用空间变得比典型的RAM大小大(因为它需要大约4GB十亿个32位数字)。

在的问题,vallong整数,这似乎表明,你确实使用超过十亿整数比较多,所以这不能在内存中方便地进行(即,洗牌将是缓慢的,因为操作系统会交换)。

这就是说,如果要素的数量是足够小(比方说小于0.5十亿),那么元素的列表可以在内存中感谢适合由array模块提供的紧凑表示,并进行改组。这可以通过标准模块array来完成:

import array, random 
numbers = array.array('I', xrange(10**8)) # or 'L', if the number of bytes per item (numbers.itemsize) is too small with 'I' 
random.shuffle(numbers) 
+0

为什么选择投票? – EOL 2017-05-03 10:48:04

3

如果您不需要号码的完整列表(如果你得到数十亿美元,其很难想象你为什么会需要他们所有的),你可能最好是采取random.sample你的号码范围,而不是洗牌。在Python 3中,random.sample也可以在range对象上工作,因此您的内存使用可能非常适中。例如,下面的代码将从一个范围内采样一万个随机数,直到您指定的任何最大值。它应该只需要超过10000个结果值相对较小容量的内存,即使你的最大值是(你想或任何数量巨大)×100十亿:

import random 

def get10kRandomNumbers(maximum): 
    pop = range(1, maximum+1) # this is memory efficient in Python 3 
    sample = random.sample(pop, 10000) 
    return sample 

唉,这不很好地为在Python工作2,因为xrange对象不允许大于系统的整数类型的最大值可以容纳。

+0

+1:但它不能在Python 3上运行:'OverflowError:Python int太大而无法转换为C ssize_t'(由于'sample()'中的'len(人口)'调用) – jfs 2013-05-05 03:59:08

+0

@JFSebastian:嗯,它适用于Python 3.3.0。哪一个版本你得到这个错误?我在Python 2.7中用'xrange'得到了这个,但是Python 3的'range'已经得到了一些增强。 – Blckknght 2013-05-05 05:20:33

+0

啊,这个限制取决于你是否在64位操作系统上,并且使用64位的Python。所以'ssize_t'在某些系统上是64位的,而其他的则是32位。我在64位Windows 7操作系统上使用64位Python,我的测试使用的范围仅为100或者38比特(1e11)。 'range'在1e19(我的一个! – Blckknght 2013-05-05 05:33:50