2013-05-04 99 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