बहुत से प्रोग्राम को वास्तविक दुनिया की घटनाओं का अनुकरण करने के लिए (दिखने में) यादृच्छिक वैल्यू चाहिए।
आम और परिचित उदाहरणों में शामिल हैं:
('Heads', 'Tails') में से एक यादृच्छिक वैल्यू।कंप्यूटर से वास्तव में यादृच्छिक वैल्यू बनाना आश्चर्यजनक रूप से कठिन तकनीकी चुनौती है, इसलिए लोग इन परिणामों को "छद्म-यादृच्छिक" भी कहते हैं।
व्यवहार में, Python की मानक लाइब्रेरी के random मॉड्यूल जैसी अच्छी तरह बनाई गई लाइब्रेरी तेज़ और लचीली होती है, और मॉडलिंग, सिम्युलेशन तथा गेम जैसे ज़्यादातर एप्लिकेशन के लिए पर्याप्त अच्छे परिणाम देती है।
इस पेज के बाकी हिस्से में random के कुछ सबसे आम फंक्शन बताए गए हैं।
हम चाहते हैं कि आप random का पूरा डॉक्युमेंटेशन भी देखें, क्योंकि यहाँ बताए गए विकल्पों से कहीं ज़्यादा विकल्प वहाँ मौजूद हैं।
random मॉड्यूल का उपयोग सुरक्षा या क्रिप्टोग्राफ़ी से जुड़े एप्लिकेशन के लिए नहीं करना चाहिए।
इसके बजाय, Python में secrets मॉड्यूल मौजूद है।
यह खास तौर पर क्रिप्टोग्राफ़िक सुरक्षा के लिए अनुकूलित किया गया है।
secrets मॉड्यूल बनाने की वजह और उससे जुड़ी कुछ पुरानी समस्याओं के बारे में PEP 506 में पढ़ सकते हैं।
random मॉड्यूल के टूल इस्तेमाल करने से पहले आपको उसे इम्पोर्ट करना होगा:
>>> import random
# Choose random integer from a range
>>> random.randrange(1000)
360
>>> random.randrange(-1, 500)
228
>>> random.randrange(-10, 11, 2)
-8
# Choose random integer between two values (inclusive)
>>> random.randint(5, 25)
22
मॉड्यूल का नाम बार-बार लिखने से बचने के लिए आप किसी खास फंक्शन को उसके नाम से इम्पोर्ट कर सकते हैं:
>>> from random import choice, choices
# Using choice() to pick Heads or Tails 10 times
>>> tosses = []
... for side in range(10):
... tosses.append(choice(['H', 'T']))
>>> print(tosses)
['H', 'H', 'H', 'H', 'H', 'H', 'H', 'T', 'T', 'H']
# Using choices() to pick Heads or Tails 8 times
>>> picks = []
... picks.extend(choices(['H', 'T'], k=8))
... print(picks)
['T', 'H', 'H', 'T', 'H', 'H', 'T', 'T']
randrange() फंक्शन के तीन रूप हैं, जो range(start, stop, step) में से एक यादृच्छिक वैल्यू चुनते हैं:
randrange(stop) एक ऐसा पूर्णांक n देता है जिसके लिए 0 <= n < stop होता हैrandrange(start, stop) एक ऐसा पूर्णांक n देता है जिसके लिए start <= n < stop होता हैrandrange(start, stop, step) एक ऐसा पूर्णांक n देता है जिसके लिए start <= n < stop होता है और n अनुक्रम start, start + step, start + 2*step... में आता हैजहाँ step == 1 हो (जो आम बात है), वहाँ randint(a, b) फंक्शन ज़्यादा सुविधाजनक और पढ़ने में आसान हो सकता है।
randint() के परिणामों में ऊपरी सीमा भी शामिल होती है, इसलिए randint(a, b) और randrange(a, b+1) एक ही बात हैं:
>>> import random
# Select one number at random from the range 0, 499
>>> random.randrange(500)
219
# Select 10 numbers at random between 0 and 9 two steps apart.
>>> numbers = []
... for integer in range(10):
... numbers.append(random.randrange(0, 10, 2))
>>> print(numbers)
[2, 8, 4, 0, 4, 2, 6, 6, 8, 8]
# roll a die
>>> random.randint(1, 6)
4
इस भाग के फंक्शन यह मानकर चलते हैं कि आप किसी अनुक्रम या किसी दूसरे कंटेनर से शुरुआत कर रहे हैं।
यह आम तौर पर एक list होता है, या कुछ सीमाओं के साथ tuple या set भी हो सकता है (tuple अपरिवर्तनीय होता है, और set का कोई क्रम नहीं होता)।
choice() और choices()
choice() फंक्शन दिए गए अनुक्रम में से यादृच्छिक रूप से चुना गया एक एलिमेंट लौटाता है।
सबसे आसान उदाहरण सिक्का उछालना है:
# This will pick one of the two values in the list at random 5 separate times
>>> [random.choice(['H', 'T']) for _ in range(5)]
['T', 'H', 'H', 'T', 'H']
लगभग यही काम हम choices() फंक्शन से भी कर सकते हैं, बस उसे लंबाई बताने वाला एक कीवर्ड आर्गुमेंट देना होगा:
>>> random.choices(['H', 'T'], k=5)
['T', 'H', 'T', 'H', 'H']
ऊपर के उदाहरणों में हमने माना था कि सिक्का निष्पक्ष है और चित या पट की संभावना बराबर है, लेकिन वज़न भी तय किए जा सकते हैं। उदाहरण के लिए, मान लीजिए एक थैले में 10 लाल गेंदें और 15 हरी गेंदें हैं, और हम उसमें से एक गेंद यादृच्छिक रूप से निकालना चाहते हैं:
>>> random.choices(['red', 'green'], [10, 15])
['red']
sample()ऊपर दिया गया choices() का उदाहरण वही मानता है जिसे सांख्यिकीविद "प्रतिस्थापन सहित प्रतिचयन" कहते हैं।
हर चुनाव का आगे के चुनावों की संभावना पर कोई असर नहीं पड़ता, और संभावित चुनावों का वितरण हर बार एक जैसा बना रहता है।
लाल और हरी गेंदों वाले उदाहरण में: हर चुनाव के बाद हम गेंद को थैले में वापस डाल देते हैं और अगली बार निकालने से पहले थैले को अच्छी तरह हिला देते हैं। इसके उलट वह स्थिति है जिसमें हम लाल गेंद निकालते हैं और वह बाहर ही रहती है। गेंद वापस न डालने का मतलब है कि अब थैले में लाल गेंदें कम हैं, और अगली बार लाल गेंद चुनने की संभावना कम हो जाती है।
इस "प्रतिस्थापन रहित प्रतिचयन" का अनुकरण करने के लिए random मॉड्यूल sample() फंक्शन देता है।
sample() का सिंटैक्स choices() जैसा ही है, बस इसमें counts नाम का एक कीवर्ड पैरामीटर भी जुड़ जाता है:
>>> random.sample(['red', 'green'], counts=[10, 15], k=10)
['green', 'green', 'green', 'green', 'green', 'red', 'red', 'red', 'red', 'green']
नमूने जिस क्रम में चुने गए, उसी क्रम में लौटाए जाते हैं।
shuffle()जब k > 1 होता है, तो choices() और sample() दोनों नए ऐरे लौटाते हैं।
इसके उलट, shuffle() किसी ऐरे का क्रम उसी जगह बदल देता है, और पहला क्रम खो जाता है:
>>> my_list = [1, 2, 3, 4, 5]
>>> random.shuffle(my_list)
>>> my_list
[4, 1, 5, 2, 3]
अब तक हमने उन मामलों पर ध्यान दिया है जिनमें सभी परिणामों की संभावना बराबर होती है।
उदाहरण के लिए, random.randrange(100) से 0 से 99 तक कोई भी पूर्णांक मिलने की संभावना बराबर है।
वास्तविक दुनिया की बहुत सी स्थितियाँ इससे कहीं ज़्यादा जटिल होती हैं।
इसलिए सांख्यिकीविदों ने "वास्तविक दुनिया" के परिणामों को गणितीय रूप से बताने के लिए कई तरह के distributions बनाए हैं।
पूर्णांकों के लिए, जब सभी संभावनाएँ बराबर हों तो randrange() और randint() का उपयोग किया जाता है।
इसे uniform वितरण कहते हैं।
randrange() और randint() के लिए दशमलव संख्या वाले समतुल्य फंक्शन भी हैं।
random() एक ऐसी float वैल्यू x देता है जिसके लिए 0.0 <= x < 1.0 होता है।
uniform(a, b) एक ऐसी x देता है जिसके लिए a <= x <= b होता है।
>>> [round(random.random(), 3) for _ in range(5)]
[0.876, 0.084, 0.483, 0.22, 0.863]
>>> [round(random.uniform(2, 5), 3) for _ in range(5)]
[2.798, 2.539, 3.779, 3.363, 4.33]
इसे "सामान्य" वितरण या "घंटी के आकार" का वक्र भी कहा जाता है। मापी गई वैल्यू में आने वाली अशुद्धि बताने का यह बहुत आम तरीका है।
उदाहरण के लिए, मान लीजिए आपकी फैक्ट्री ने अभी-अभी 10,000 बोल्ट खरीदे हैं, जो एक जैसे होने चाहिए।
आप फैक्ट्री के रोबोट को इन्हें संभालने के लिए तैयार करना चाहते हैं, इसलिए आप 100 बोल्ट का एक नमूना तोलकर देखते हैं और पाते हैं कि उनका औसत (या mean) वज़न 4.731g है।
इसका मतलब यह होना बेहद असंभव है कि इन सबका वज़न ठीक 4.731g है।
शायद आप पाएँ कि वैल्यू 4.627 से 4.794g तक फैली हैं, पर ज़्यादातर 4.731g के आसपास हैं।
यह Gaussian distribution है, जिसमें संभावनाएँ औसत पर सबसे ऊँची होती हैं और दोनों तरफ सममित रूप से घटती जाती हैं (इसीलिए इसे "घंटी के आकार" का कहते हैं)।
सॉफ्टवेयर में इसका अनुकरण करने के लिए हमें वक्र की चौड़ाई बताने का कोई तरीका चाहिए (आम तौर पर सस्ते बोल्टों की तुलना में महँगे बोल्ट औसत के आसपास ज़्यादा करीब होते हैं!)
परंपरा के अनुसार, यह standard deviation से किया जाता है: छोटी वैल्यू से तीखा और पतला वक्र बनता है, और बड़ी वैल्यू से नीचा और चौड़ा वक्र।
गणितज्ञों को यूनानी अक्षर बहुत पसंद हैं, इसलिए हम औसत के लिए μ ('म्यू') और मानक विचलन के लिए σ ('सिग्मा') इस्तेमाल करते हैं।
इसलिए, अगर आप पढ़ें कि "95% वैल्यू μ के 2σ के भीतर होती हैं" या "हिग्स बोसॉन 5-सिग्मा भरोसे के साथ पाया गया है", तो ऐसी बातें मानक विचलन से जुड़ी होती हैं।
>>> mu = 4.731
>>> sigma = 0.316
>>> [round(random.gauss(mu, sigma), 3) for _ in range(5)]
[4.72, 4.957, 4.64, 4.556, 4.968]