यह प्रश्न एक संपूर्ण उत्तर के लिए बहुत व्यापक है, लेकिन मुझे कुछ दिलचस्प बिंदुओं को चुनने की अनुमति दें:
क्यों "समान रूप से संभावना"
मान लें कि आपके पास एक सरल यादृच्छिक संख्या जनरेटर है जो 0, 1, ..., 10 को समान संभावना के साथ उत्पन्न करता है (इसे क्लासिक के रूप में सोचें rand()
)। अब आप 0, 1, 2 श्रेणी में एक यादृच्छिक संख्या चाहते हैं, प्रत्येक समान संभावना के साथ। आपकी घुटने की झटका प्रतिक्रिया लेनी होगी rand() % 3
। लेकिन रुको, शेष 0 और 1 शेष 2 की तुलना में अधिक बार होते हैं, इसलिए यह सही नहीं है!
यही कारण है कि हमें उचित वितरण की आवश्यकता है , जो एक समान यादृच्छिक पूर्णांक का एक स्रोत लेते हैं और उन्हें हमारे वांछित वितरण में बदल देते हैं, जैसे Uniform[0,2]
कि उदाहरण में। एक अच्छे पुस्तकालय के लिए इसे छोड़ना सबसे अच्छा है!
इंजन
इस प्रकार सभी यादृच्छिकता के दिल में एक अच्छा छद्म यादृच्छिक संख्या जनरेटर है जो संख्याओं के एक क्रम को उत्पन्न करता है जो समान रूप से एक निश्चित अंतराल पर वितरित किया जाता है, और जो आदर्श रूप से एक बहुत लंबी अवधि है। मानक कार्यान्वयन rand()
अक्सर सबसे अच्छा नहीं होता है, और इस तरह से चुनाव करना अच्छा होता है। रैखिक-बधाई और Mersenne ट्विस्टर दो अच्छे विकल्प हैं (एलजी वास्तव में अक्सर उपयोग किया जाता है rand()
, भी); फिर से, लाइब्रेरी को संभालना अच्छा है।
यह काम किस प्रकार करता है
आसान: सबसे पहले, एक इंजन स्थापित करें और इसे बीज दें। बीज पूरी तरह से "यादृच्छिक" संख्याओं के पूरे अनुक्रम को निर्धारित करता है, इसलिए क /dev/urandom
) हर बार एक अलग (जैसे से लिया गया ) का उपयोग करें और यदि आप यादृच्छिक विकल्पों के अनुक्रम को फिर से बनाना चाहते हैं, तो बीज को स्टोर करें।
#include <random>
typedef std::mt19937 MyRNG; // the Mersenne Twister with a popular choice of parameters
uint32_t seed_val; // populate somehow
MyRNG rng; // e.g. keep one global instance (per thread)
void initialize()
{
rng.seed(seed_val);
}
अब हम वितरण बना सकते हैं:
std::uniform_int_distribution<uint32_t> uint_dist; // by default range [0, MAX]
std::uniform_int_distribution<uint32_t> uint_dist10(0,10); // range [0,10]
std::normal_distribution<double> normal_dist(mean, stddeviation); // N(mean, stddeviation)
... और यादृच्छिक संख्या बनाने के लिए इंजन का उपयोग करें!
while (true)
{
std::cout << uint_dist(rng) << " "
<< uint_dist10(rng) << " "
<< normal_dist(rng) << std::endl;
}
संगामिति
<random>
पारंपरिक पर पसंद करने का एक और महत्वपूर्ण कारण rand()
यह है कि यह अब बहुत स्पष्ट और स्पष्ट है कि यादृच्छिक संख्या पीढ़ी थ्रेडसेफ़ कैसे बनाएं: या तो प्रत्येक थ्रेड को अपने स्वयं के साथ प्रदान करें, थ्रेड-लोकल इंजन, थ्रेड-लोकल सीड पर वरीयता प्राप्त, या एक्सेस को सिंक्रनाइज़ करें इंजन ऑब्जेक्ट के लिए।
विविध
- कोडगुरु पर TR1 यादृच्छिक पर एक दिलचस्प लेख ।
- विकिपीडिया का अच्छा सारांश है (धन्यवाद, @ जस्टिन)।
- सिद्धांत रूप में, प्रत्येक इंजन को टाइप करना चाहिए ए
result_type
, जो कि बीज के लिए उपयोग करने के लिए सही अभिन्न प्रकार है। मुझे लगता है कि मैं एक गाड़ी कार्यान्वयन एक बार जो मुझे मजबूर के लिए बीज के लिए मजबूर करने के लिए किया था std::mt19937
के लिए uint32_t
64 पर, अंत में यह तय किया जाना चाहिए और आप कह सकते हैं MyRNG::result_type seed_val
और इस प्रकार इंजन बहुत आसानी से बदली हैं।
rand
, आपको कुछ बुनियादी आंकड़ों और RNG अवधारणाओं के लिए विकिपीडिया पर एक त्वरित नज़र डालनी चाहिए, अन्यथा आपको<random>
इसके विभिन्न टुकड़ों के औचित्य और उपयोग की व्याख्या करना वास्तव में कठिन होगा ।