2011-12-28 15 views
6

मैं 0 और 1 के बीच सी ++ में समान यादृच्छिक संख्याएं उत्पन्न करना चाहता हूं, जो मानक rand() और srand(time(NULL)) विधि का उपयोग नहीं करता है । इसका कारण यह है कि यदि मैं अपनी घड़ी के एक ही सेकंड के भीतर एक से अधिक बार एप्लिकेशन चलाता हूं, तो बीज बिल्कुल वही होगा और उसी आउटपुट का उत्पादन करेगा।टीआर 1/देव/यादृच्छिक (<1 सेकंड रन के लिए लचीला) का उपयोग कर सी ++ में यादृच्छिक संख्याएं उत्पन्न करना

मैं बूस्ट या ओएस/कंपाइलर विनिर्देशों पर भरोसा नहीं करना चाहता हूं। x86 माना जा सकता है।

ऐसा लगता है कि ऐसा करने का एक वैकल्पिक तरीका TR1 (मेरे पास सी ++ 11 नहीं है) और /dev/random के साथ बीजिंग का उपयोग करना है?

अभी मैं इस किया है, लेकिन यह अभी भी एक बीज जो अच्छी तरह से 1 सेकंड रन के भीतर काम नहीं करेगा के रूप में time(NULL) उपयोग करता है:

#include <iostream> 
#include <tr1/random> 

int main() 
{ 
    std::tr1::mt19937 eng; 
    eng.seed(time(NULL)); 
    std::tr1::uniform_int<int> unif(1, RAND_MAX); 
    int u = unif(eng); 
    std::cout << (float)u/RAND_MAX << std::endl; 
} 
+0

क्या आप ओएस/कंपाइलर-विशिष्ट कार्यों का उपयोग करने के इच्छुक हैं? – Mysticial

+0

मैं इससे बचना चाहता हूं ... मैं इसे विभिन्न प्रणालियों पर तैनात कर दूंगा – gnychis

+0

कितने अलग? क्या वे अभी भी सभी x86 हैं? – Mysticial

उत्तर

7

पोस्टिंग:

यह अभी भी कुछ हद तक संकलक-विशिष्ट है, लेकिन अभी भी लगभग सभी 86-लक्ष्य compilers पर काम करेंगे:

#ifdef _WIN32 

// Windows 
#define rdtsc __rdtsc 

#else 

// For everything else 
unsigned long long rdtsc(){ 
    unsigned int lo,hi; 
    __asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi)); 
    return ((unsigned long long)hi << 32) | lo; 
} 

#endif 

int main() 
{ 
    std::tr1::mt19937 eng; 
    eng.seed(rdtsc()); // Seed with rdtsc. 
    std::tr1::uniform_int<int> unif(1, RAND_MAX); 
    int u = unif(eng); 
    std::cout << (float)u/RAND_MAX << std::endl; 
} 

विचार यहाँ यादृच्छिक बीज के लिए है rdtsc चक्र-काउंटर के साथ संख्या जनरेटर।

कारण यह काम क्यों करता है क्योंकि rdtsc चक्र-काउंटर CPU आवृत्ति के रूप में लगभग (अक्सर वही) गति को पुनरावृत्त करता है। इसलिए, एक ही मूल्य को लौटने के लिए दो कॉलों की संभावना बेहद पतली है - इस प्रकार, यह एक आरएनजी के लिए एक उत्कृष्ट बीज बना रही है।

1

आपकी समस्या जिस तरह से आप यादृच्छिक संख्या जनरेटर बीज से संबंधित है। जाहिर है समय के साथ बीजिंग (एनयूएलएल) बीजिंग के दौरान उस दूसरे के भीतर एक ही पीआरएनजी अनुक्रम का उत्पादन करने जा रहा है। यह बीज रैंड का सबसे आम तरीका है, लेकिन दुर्भाग्य से इस मुद्दे के कारण दुर्भाग्य से खराब अभ्यास है। इतना ही नहीं, मैंने पढ़ा है कि इससे परिणाम में पूर्वाग्रह हो सकता है।

ध्यान दें कि प्रत्येक पीआरएनजी एक ही परिणाम का उत्पादन करेगा यदि समान मूल्य के साथ बीजित किया गया हो। तो आपकी समस्या जनरेटर से संबंधित नहीं है, और बीजिंग के लिए अधिक है।

मैंने यहां कुछ हफ्ते पहले बीजिंग के बारे में एक प्रश्न पूछा और निम्नलिखित लेख का एक लिंक दिया गया जिसे आप उपयोगी भी पा सकते हैं। Good Practice in (Pseudo) Random Number Generation for Bioinformatics Applications जेनरेटर को बीजिंग या वार्मिंग पर अनुभाग देखें।

रैंड() सबसे अच्छा यादृच्छिक संख्या जनरेटर नहीं है, लेकिन कई मामलों में उपयुक्त है बशर्ते यह उचित रूप से बीजित हो। यदि आप कुछ बेहतर चाहते हैं जहां दोहराना अनुक्रम बहुत बड़ा है तो उस लिंक में कुछ प्रदान किए गए हैं। या TR1 आधारित वाले का उपयोग करें। निजी तौर पर, मैं अधिक पोर्टेबल सी ++ 03 आधारित कोड के साथ जाऊंगा और टीआर 1 से साफ़ हो जाऊंगा।

वैकल्पिक पीआरएनजी एल्गोरिदम के रूप में Multiply with carry पर भी विचार करें। ओपी के अनुरोध पर

4

TR1 [tr.rand.device] में TR1 एक random_device वर्ग निर्दिष्ट करता है जो कार्यान्वयन-निर्भर स्रोत से हस्ताक्षरित इनट उत्पन्न करता है। तो निम्नलिखित काम करना चाहिए, हालांकि मैं यह संकलित नहीं किया है अपने आप को:

int main() { 
    std::tr1::random_device dev_random; 
    std::tr1::mt19937 eng(dev_random()); 
    ... 

TR1 में, बुला यह काम करता है और अधिक बेतरतीब ढंग से eng के राज्य initializes बिना सीधे dev_random गुजर, लेकिन सी ++ 11 में आप बीज रैप करने के लिए है एक और वर्ग में तर्क।चूंकि तर्क दोनों पुस्तकालयों में काम करता है, इसलिए मैं इसे बनाए रखने के लिए करता हूं, जब तक कि आपके पास अधिक मांग की आवश्यकता न हो।

+0

ध्यान दें कि 'random_device()' कन्स्ट्रक्टर से प्राप्त _which_ यादृच्छिक डिवाइस के बारे में कोई गारंटी नहीं है। यह '/ dev/random',' dev/urandom', 'rdtsc'-based, http://en.wikipedia.org/wiki/RdRand, या यहां तक ​​कि एक और छद्म-आरएनजी भी हो सकता है। कार्यान्वयन कन्स्ट्रक्टर को एक स्ट्रिंग तर्क परिभाषित कर सकते हैं जो विकल्पों के बीच चयन करता है, लेकिन डिफ़ॉल्ट को सभ्य माना जाता है। –

+1

random_device एक फ़ंक्शन ऑब्जेक्ट है, इसलिए 'eng (dev_random()) ' – Cubbi

+0

@ कब्बी: नहीं: इंजन दोनों में एक पूर्णांक लेने वाला एक कन्स्ट्रक्टर होता है, और एक कन्स्ट्रक्टर फ़ंक्शन ऑब्जेक्ट लेता है:" एक्स (जी) '- एक बनाता है 'जी' के लगातार आविष्कार के परिणामों द्वारा दिए गए प्रारंभिक आंतरिक राज्य के साथ इंजन। " - [tr.rand.req] तालिका 16. यह उन्हें केवल अपने पहले शब्द की बजाय अपने पूरे राज्य को भरने की अनुमति देता है। (बेशक, यह संभव है कि किसी दिए गए कार्यान्वयन ने पूरे spec को लागू नहीं किया है।) –