C ++ 11 में रैंडम नंबर जेनरेशन: कैसे जेनरेट करें, यह कैसे काम करता है? [बन्द है]


102

मैं हाल ही में C ++ 11 में रैंडम नंबर जेनरेट करने के लिए नए तरीके से आया हूं, लेकिन मैं उसके बारे में पढ़े गए पेपर को पचा नहीं सका (वह इंजन क्या है , मैथ्स टर्म डिस्ट्रीब्यूशन की तरह है , "जहां सभी पूर्णांक समान रूप से निर्मित होते हैं ")।

तो क्या कोई समझा सकता है

  • वे क्या हैं?
  • उनका क्या मतलब है?
  • कैसे उत्पन्न करें?
  • वो कैसे काम करते है?
  • आदि

रैंडम नंबर जनरेशन के बारे में आप इसे एक ही बार में पूछे जा सकते हैं।


6
RNG के बारे में यह पूछे बिना कि वितरण क्या है, अभिव्यक्ति पार्सर के बारे में पूछे बिना यह जानना है कि अभिव्यक्ति क्या है ... C ++ 11 में RNG लाइब्रेरी का उद्देश्य उन लोगों के लिए है जो कुछ आँकड़ों को जानते हैं और उनके द्वारा उत्पादित फ्लैट वितरण की तुलना में अधिक आवश्यकताएं हैं। rand, आपको कुछ बुनियादी आंकड़ों और RNG अवधारणाओं के लिए विकिपीडिया पर एक त्वरित नज़र डालनी चाहिए, अन्यथा आपको <random>इसके विभिन्न टुकड़ों के औचित्य और उपयोग की व्याख्या करना वास्तव में कठिन होगा ।
मट्टियो इटालिया

26
@ मत्ते: मुश्किल से। एक बच्चा इस अवधारणा को समझ सकता है कि मर एक यादृच्छिक संख्या पैदा करता है, बिना यह समझे कि वितरण क्या है।
बेंजामिन लिंडले

3
@ बैंजामिन: और यहीं से उनकी समझ बंद हो जाती है, जो सिर्फ पहला कदम (इंजन) है, और यह भी समझे बिना कि यह महत्वपूर्ण क्यों है कि वे एक फ्लैट वितरण उत्पन्न करते हैं। वितरण और अन्य आँकड़ों की अवधारणाओं को समझे बिना बाकी सभी पुस्तकालय एक रहस्य बने हुए हैं।
मट्टियो इटालिया

जवाबों:


142

यह प्रश्न एक संपूर्ण उत्तर के लिए बहुत व्यापक है, लेकिन मुझे कुछ दिलचस्प बिंदुओं को चुनने की अनुमति दें:

क्यों "समान रूप से संभावना"

मान लें कि आपके पास एक सरल यादृच्छिक संख्या जनरेटर है जो 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_t64 पर, अंत में यह तय किया जाना चाहिए और आप कह सकते हैं MyRNG::result_type seed_valऔर इस प्रकार इंजन बहुत आसानी से बदली हैं।

एक बार फिर, केरेक ने मुझे जिस पर काम कर रहा था, उससे कहीं बेहतर जवाब के साथ पंच को हराया। +1
जस्टिन

@ जस्टिन: मुझे यकीन है कि मैं एक टन चीजों से चूक गया हूं, इस विषय पर और पहलुओं को जोड़ने के लिए स्वतंत्र महसूस कर रहा हूं! :-)
केरेक एसबी

13
"किसी तरह से आबाद" भाग के लिए, मुझे लगता std::random_deviceहै कि इसके बजाय ध्यान देने योग्य है/dev/urandom
क्यूबाई

2
इसका एक उदाहरण यहांstd::random_device पाया जा सकता है
WKS

1
विकिपीडिया लेख में कोड छोटी गाड़ी है। यादृच्छिक और random2 समान हैं। कोड स्निपेट में टिप्पणियों से यह स्पष्ट है कि लेखक को यह समझ में नहीं आता है कि <random> में सुविधाओं का उपयोग कैसे करें।
user515430

3

एक यादृच्छिक संख्या जनरेटर एक समीकरण है जो एक नंबर दिया गया है, जो आपको एक नया नंबर देगा। आमतौर पर आप या तो पहली संख्या प्रदान करते हैं या सिस्टम टाइम जैसी किसी चीज़ से खींचा जाता है।

हर बार जब आप एक नया नंबर मांगते हैं तो यह समीकरण को निष्पादित करने के लिए पिछले नंबर का उपयोग करता है।

एक यादृच्छिक संख्या जनरेटर को बहुत अच्छा नहीं माना जाता है यदि उसमें अन्य संख्याओं की तुलना में अधिक बार एक ही संख्या का उत्पादन करने की प्रवृत्ति होती है। यदि आप एक और 5 के बीच एक यादृच्छिक संख्या चाहते थे और आपके पास संख्याओं का यह वितरण था:

  • 1 1%
  • 2: 80%
  • 3: 5%
  • 4: 5%
  • 5: 9%

2 किसी भी अन्य संख्या की तुलना में अधिक बार एफएआर उत्पन्न होता है, इसलिए यह अन्य संख्याओं की तुलना में उत्पन्न होने की अधिक संभावना है। यदि सभी संख्याएं समान रूप से होती हैं तो आपके पास हर बार प्रत्येक संख्या प्राप्त करने का 20% मौका होगा। इसे दूसरे तरीके से कहने के लिए, उपरोक्त वितरण बहुत असमान है क्योंकि 2 इष्ट है। सभी 20% के साथ एक वितरण भी होगा।

आमतौर पर, यदि आप एक सच्चे यादृच्छिक संख्या चाहते हैं तो आप यादृच्छिक संख्या जनरेटर के बजाय मौसम या किसी अन्य प्राकृतिक स्रोत जैसी चीज़ों से डेटा खींच लेंगे।


8
अधिकांश रैंडम नंबर जेनरेटर अच्छे वितरण भी उत्पन्न करते हैं। वे सिर्फ यादृच्छिक नहीं हैं; समस्या यह है कि उनकी गणना की जाती है और इस प्रकार आप अनुक्रम में पर्याप्त संख्या में दिए गए अगले नंबर का अनुमान लगा सकते हैं (यह तथ्य उन्हें सुरक्षा के लिए बुरा बनाता है जहां सही मायने में यादृच्छिक संख्या की आवश्यकता होती है)। खेल और सामान के लिए आपको ठीक होना चाहिए।
मार्टिन यॉर्क

5
मुझे पूरा यकीन है कि ओपी C ++ <यादृच्छिक> हेडर में दी गई सुविधाओं के बारे में विशिष्ट जानकारी के लिए पूछ रहा है। यह उत्तर प्रोग्रामिंग को संबोधित नहीं करता है अकेले C ++ को जाने दें।
बेंजामिन लिंडले

1
@ मार्टिन: सुरक्षा के लिए वास्तव में यादृच्छिक संख्याओं के स्रोत की आवश्यकता नहीं होती है। काउंटर मोड में AES (एक उदाहरण के लिए) यह नियतात्मक होने के बावजूद भी काफी अच्छा कर सकता है। इसके लिए कुंजी में उचित मात्रा में एन्ट्रॉपी की आवश्यकता होती है, लेकिन किसी भी सच्चे यादृच्छिकता की नहीं।
जेरी कॉफिन

@ बेंजामिन लिंडले: नेवरमाइंड। बस फिर से और महसूस किया कि मैं गलत था।
N_A
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.