2010-11-13 7 views
64

में पूर्णांक यादृच्छिक सूची बनाएं मैं परीक्षण प्रयोजनों के लिए पूर्णांक यादृच्छिक सूची बनाने के लिए चाहते हैं। संख्याओं का वितरण महत्वपूर्ण नहीं है। गिनती की एकमात्र चीज समय है। मुझे पता है कि यादृच्छिक संख्याएं एक समय लेने वाला कार्य है, लेकिन एक बेहतर तरीका होना चाहिए।अजगर

import random 
import timeit 

# random lists from [0-999] interval 
print [random.randint(0,1000) for r in xrange(10)] # v1 
print [random.choice([i for i in xrange(1000)]) for r in xrange(10)] # v2 

# measurement: 
t1 = timeit.Timer('[random.randint(0,1000) for r in xrange(10000)]','import random') # v1 
t2 = timeit.Timer('random.sample(range(1000), 10000)','import random') # v2 

print t1.timeit(1000)/1000 
print t2.timeit(1000)/1000 

वी 2 v1 की तुलना में तेजी है, लेकिन इस तरह के एक बड़े पैमाने पर काम नहीं कर रहा:

यहाँ मेरे वर्तमान समाधान है। यह निम्न त्रुटि देता है: 'ValueError: नमूना आबादी से भी बड़ा'

आप तीव्र, कुशल समाधान है कि उस पैमाने में काम करता है पता है?

संपादित करें:

एंड्रयू: 0,000290962934494

gnibbler की: 0,0058455221653

KennyTM की: 0,00219276118279

NumPy, आया देखा था, पर विजय प्राप्त की

धन्यवाद!

+4

बेशक यह काम नहीं करता है। 'random.sample()' आबादी को कम करता है, जिससे संख्या कम और कम यादृच्छिक होती है। एक बार पूरी आबादी समाप्त हो जाने के बाद, आगे नमूना असंभव है। –

+0

जब आप कहते हैं कि यह परीक्षण उद्देश्यों के लिए है, परीक्षण कब तक लगेगा? –

+0

सिमुलेशन के लिए, जहां समय एक आवश्यकता है (लेकिन क्रिप्टो और सुरक्षा नहीं है), फिर एक [रैखिक संगठनात्मक जनरेटर (एलसीजी)] (https://en.wikipedia.org/wiki/Linear_congruential_generator) अक्सर उपयोग किया जाता है। मेरा मानना ​​है कि [मेर्सन ट्विस्टर] (https://en.wikipedia.org/wiki/Mersenne_Twister) तेज़ है (लेकिन एलसीजी से धीमा), और यदि मैं सही ढंग से याद करता हूं, तो यह एक समान वितरण प्रदान करता है। – jww

उत्तर

56

नहीं पूरी तरह से स्पष्ट आप क्या चाहते हैं, लेकिन मैं numpy.random.randint का प्रयोग करेंगे:

import numpy.random as nprnd 
import timeit 

t1 = timeit.Timer('[random.randint(0,1000) for r in xrange(10000)]','import random') # v1 
### change v2 so that it picks numbers in (0,10000) and thus runs... 
t2 = timeit.Timer('random.sample(range(10000), 10000)','import random') # v2 
t3 = timeit.Timer('nprnd.randint(1000, size=10000)','import numpy.random as nprnd') # v3 

print t1.timeit(1000)/1000 
print t2.timeit(1000)/1000 
print t3.timeit(1000)/1000 

जो मेरे मशीन पर देता है

0.0233682730198 
0.00781716918945 
0.000147947072983 

ध्यान दें कि randint random.sample से बहुत अलग है (में अपने मामले में काम करने के लिए आदेश देने के लिए मुझे 1,000 से 10,000 को बदलना पड़ा क्योंकि टिप्पणीकारों में से एक ने बताया - यदि आप वास्तव में उन्हें 0 से 1,000 तक चाहते हैं तो आप 10 से विभाजित हो सकते हैं)। और अगर आप वास्तव में परवाह नहीं है तो क्या वितरण आप तो हो रही है यह संभव है कि आप या तो बहुत अच्छी तरह से यादृच्छिक संख्या आपकी समस्या को समझ में नहीं आता, या - क्षमा याचना के साथ कि अगर असभ्य लगता है ...

+3

+1 के लिए +1, अगर स्टिगो को इस कई यादृच्छिक संख्याओं की आवश्यकता है तो शायद यह –

+0

एंड्रयू के लिए numpy इंस्टॉल करने लायक है, आप बिल्कुल वितरण के बारे में सही हैं। लेकिन यह एक असली बात नहीं है। दोस्तों के बीच बस एक चुनौती। : डी चीयर्स! – Stiggo

30

सभी यादृच्छिक तरीकों अंत random.random() बुला तो सबसे अच्छा तरीका यह सीधे

[int(1000*random.random()) for i in xrange(10000)] 

जैसे कॉल करने के लिए है।

random.randint कॉल random.randrange
random.randrange लौटने istart + istep*int(self.random() * n)

संपादित से पहले सीमा की जांच करने के लिए भूमि के ऊपर का एक समूह है: numpy बहुत तेजी से अभी भी निश्चित रूप से

+0

+1 मैं बस इससे पहले खोद रहा था और सोच रहा था कि 'रेंडरेंज' ने आखिरकार 'गेट्रैंडबिट' को फोन करने का आह्वान किया। मुझे याद आया कि व्यवहार के लिए आपको 'SystemRandom' को तुरंत चालू करना होगा। मुझे और अधिक बारीकी से देखने के लिए धन्यवाद। – aaronasterling

+0

आपने मेरा संस्करण हराया है, लेकिन एंड्रयू का समाधान स्पष्ट रूप से विजेता है। – Stiggo

+1

@Stiggo, निश्चित रूप से, एकमात्र कारण मैं सोच सकता हूं कि numpy का उपयोग न करने के लिए अगर आपके प्लेटफ़ॉर्म पर numpy समर्थित नहीं है। जैसे। Python3 में google app engine –

2

सबसे पहले, आपको randrange(0,1000) या randint(0,999), नहीं randint(0,1000) का उपयोग करना चाहिए है । randint की ऊपरी सीमा समावेशी है।

कुशलता के लिए, randint बस जो random कॉल randrange का एक आवरण है, तो आप सिर्फ random उपयोग करना चाहिए।इसके अलावा, का उपयोग sample पर तर्क के रूप में करें, range पर नहीं।

आप

[a for a in sample(xrange(1000),1000) for _ in range(10000/1000)] 

रेंज में 10,000 संख्या sample 10 बार का उपयोग कर उत्पन्न करने के लिए इस्तेमाल कर सकते हैं।

(बेशक इस NumPy हरा नहीं।)

$ python2.7 -m timeit -s 'from random import randrange' '[randrange(1000) for _ in xrange(10000)]' 
10 loops, best of 3: 26.1 msec per loop 

$ python2.7 -m timeit -s 'from random import sample' '[a%1000 for a in sample(xrange(10000),10000)]' 
100 loops, best of 3: 18.4 msec per loop 

$ python2.7 -m timeit -s 'from random import random' '[int(1000*random()) for _ in xrange(10000)]' 
100 loops, best of 3: 9.24 msec per loop 

$ python2.7 -m timeit -s 'from random import sample' '[a for a in sample(xrange(1000),1000) for _ in range(10000/1000)]' 
100 loops, best of 3: 3.79 msec per loop 

$ python2.7 -m timeit -s 'from random import shuffle 
> def samplefull(x): 
> a = range(x) 
> shuffle(a) 
> return a' '[a for a in samplefull(1000) for _ in xrange(10000/1000)]' 
100 loops, best of 3: 3.16 msec per loop 

$ python2.7 -m timeit -s 'from numpy.random import randint' 'randint(1000, size=10000)' 
1000 loops, best of 3: 363 usec per loop 

लेकिन जब से तुम संख्या के वितरण के बारे में परवाह नहीं है, यही कारण है कि अभी प्रयोग नहीं:

range(1000)*(10000/1000) 

?

+0

'randrange (1000) 'मेरे कंप्यूटर पर' 1000 * int (यादृच्छिक())' से दोगुनी से अधिक समय लेता है –

5

प्रदर्शन के बारे में आपका प्रश्न म्यूट है - दोनों कार्य बहुत तेज हैं। आपके कोड की गति यादृच्छिक संख्याओं के साथ द्वारा निर्धारित की जाएगी।

हालांकि यह महत्वपूर्ण है कि आप उन दो कार्यों के व्यवहार में अंतर को समझें। एक प्रतिस्थापन के साथ यादृच्छिक नमूना करता है, दूसरा प्रतिस्थापन के बिना यादृच्छिक नमूना करता है।