2010-04-14 12 views
6

के लिए एक अच्छा यादृच्छिक बीज उत्पन्न करता है मैं एक psudo-random संख्या जनरेटर के लिए एक अच्छा यादृच्छिक बीज उत्पन्न करने की कोशिश कर रहा हूं। मैंने सोचा कि मुझे विशेषज्ञ की राय मिल जाएगी। अगर मुझे यह करने का एक बुरा तरीका है या यदि बेहतर तरीके हैं तो मुझे बताएं।सी ++ psudo यादृच्छिक संख्या जेनरेटर

#include <iostream> 
#include <cstdlib> 
#include <fstream> 
#include <ctime> 

unsigned int good_seed() 
{ 
    unsigned int random_seed, random_seed_a, random_seed_b; 
    std::ifstream file ("/dev/random", std::ios::binary); 
    if (file.is_open()) 
    { 
     char * memblock; 
     int size = sizeof(int); 
     memblock = new char [size]; 
     file.read (memblock, size); 
     file.close(); 
     random_seed_a = int(memblock); 
     delete[] memblock; 
    }// end if 
    else 
    { 
     random_seed_a = 0; 
    } 
    random_seed_b = std::time(0); 
    random_seed = random_seed_a xor random_seed_b; 
    return random_seed; 
} // end good_seed() 
+0

इसके साथ पासा और XOR रोल करने के लिए मत भूलना;) – Andrey

+2

अगर आपके प्रक्रिया फ़ाइल हैंडल से बाहर चलाता है और नहीं खोल सकता '/ dev/random' क्या होगा? –

उत्तर

0

अच्छा परिभाषित करें। :-)

क्या बीज जल्दी से खोजना महत्वपूर्ण है, या बीज जितना संभव हो उतना यादृच्छिक हो सकता है इससे कोई फर्क नहीं पड़ता कि यह कितना समय लगता है?

एक संतुलन के लिए - निश्चित रूप से सबसे यादृच्छिक नहीं, निश्चित रूप से नहीं सबसे तेजी से ...

  • जब वह पहली बार कहा जाता है, मिलीसेकेंड में, प्रणाली समय लगता है।
  • एक हैश फ़ंक्शन के माध्यम से चलाएं, जैसे SHA-1।
  • परिणाम बीज का उपयोग करें।

जो आपको अधिकतर यादृच्छिक 160 बिट्स देना चाहिए, जो 10^50 वां या भिन्नता है। हैश दौड़ने के लिए एक अलग दूसरा ले जाएगा, इसलिए यह बिजली तेज नहीं है, लेकिन मेरे लिए अतीत में एक अच्छा संतुलन रहा है।

+0

मैं अपने आवेदन के लिए जितना संभव हो उतना यादृच्छिक करना चाहता हूं, लेकिन मुझे एक तेज़ समाधान में दिलचस्पी होगी। – posop

+3

@ डीनजे हैश जरूरी है। सिस्टम समय के साथ बस बीज। जो आप हैश के साथ पूरा करने की कोशिश कर रहे हैं वह है (एक अच्छा) छद्म यादृच्छिक संख्या जनरेटर पहले से * * बेहतर (करता है)। –

+0

जॉन-एरिक 100% सही है; दूसरी ओर, मुझे खराब यादृच्छिक संख्या जेनरेटर के साथ काम करने के लिए उपयोग किया जाता है, एक बुरे से अच्छा नहीं बता सकता, और (त्वरित) ओवरकिल के साथ चिपकने लगता है। –

1

परंपरागत रूप से, हमने अपने मूल्यों को बीज के लिए पहले या दूसरे उपयोगकर्ता इनपुट का उपयोग किया है (मिलीसेकंड रेंज के लिए टिकटें) जितनी बार उन्हें जवाब देने में लगती है वह काफी परिवर्तनीय है।

5

कोड जो/dev/random से पढ़ता है वह गलत लगता है: आप सी-शैली को अपने चरित्र बफर का पता यादृच्छिक_seed_a (सी ++ के लिए प्लग यहां) में डालते हैं और जो भी आप वास्तव में/dev/random से पढ़ते हैं उसे अनदेखा करते हैं (*reinterpret_cast<int*>(memblock) का प्रयास करें।

/dev/random यादृच्छिक पहले से ही एक अच्छा एंट्रॉपी स्रोत होना चाहिए, इसलिए यदि यह उपलब्ध है तो संभवतः किसी भी अन्य डेटा के साथ मूल्य को खराब न करें और इसे सीधे बीज के रूप में उपयोग करें। यदि पर्याप्त डेटा नहीं है/dev/random में मैं बस उस समय वापस आऊंगा और इसे किसी चीज़ के साथ xor'ing करने के बजाय स्वयं का उपयोग करूँगा।

+1

मेरे अध्ययनों के अनुसार एक गैर-निर्धारिती यादृच्छिक चर "dev/urandom" xor-ed एक यादृच्छिक परिवर्तनीय समय (0) के साथ अभी भी एक गैर-निर्धारक यादृच्छिक चर होगा। – posop

2

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

सिस्टम समय का उपयोग सीधे (और सामान्य) है। /dev/random का उपयोग करना भी ठीक है।

यदि आपका छद्म-यादृच्छिक संख्या जनरेटर अच्छा नहीं है, तो भी "अच्छा" बीज चुनने से मदद नहीं मिलेगी। अगर आप कर सकते हैं इसे बदलें।

सुझाव: Mersenne twister एक बहुत अच्छी तरह से माना जाता है। Here's एक अग्रदूत जो सबसे सीमित सिस्टम पर भी चलाएगा।

+3

उद्देश्य के आधार पर, एक छद्म-यादृच्छिक संख्या जेनरेटर को अप्रत्याशित बीज की आवश्यकता हो सकती है। एक ऑनलाइन पोकर गेम था जिसने समय को एक सभ्य पीआरएनजी किया था, जिसका मतलब था कि कुछ कार्ड देखकर, पीआरएनजी शुरू करने के लिए यह संभव था, और इसलिए पूरे डेक को जानना संभव था। –

+1

यदि यह यादृच्छिक संख्या अनुक्रम की भविष्यवाणी करने में सक्षम नहीं होने के लिए * सभी * महत्वपूर्ण है, तो आप एक क्रिप्टोग्राफ़िक रूप से सुरक्षित जनरेटर चाहते हैं, न कि छद्म यादृच्छिक जनरेटर। (यदि आप एक छद्म यादृच्छिक जनरेटर पर वास्तविक धन जुआ का आधार रखते हैं तो आप पागल हो जाते हैं।) –

+0

मेरसेन ट्विस्टर के साथ बस एफवाईआई, आपको भविष्य के सभी कार्डों को जानने से पहले लगातार 624 कार्ड (12 डेक) का पालन करना होगा। –

0

शायद आपको /dev/urandom//dev/random से अधिक पसंद करना चाहिए। लिनक्स पर बाद वाले ब्लॉक यदि पर्याप्त एन्ट्रॉपी उपलब्ध नहीं है, तो प्रोग्राम आसानी से तब हो सकता है जब प्रोग्राम बिना किसी उपयोगकर्ता इंटरैक्शन के मशीन पर चलता है। यदि आप /dev/urandom नहीं खोल सकते हैं, तो आप फ़ॉलबैक का उपयोग करने के बजाय अपवाद फेंक सकते हैं।

1

"अच्छा" जनरेटर, "खराब जनरेटर" इसका कोई मतलब नहीं है। "कोई भी जो यादृच्छिक अंकों के उत्पादन के अंकगणितीय तरीकों को मानता है, निश्चित रूप से, पाप की स्थिति में है।" - जॉन वॉन न्यूमैन। हर ऐसा जनरेटर केवल एक निर्धारक एल्गोरिदम है। यह बहुत प्रारंभिक राज्य (बीज) रखने के लिए महत्वपूर्ण है जो पर्याप्त एन्ट्रॉपी लाता है। आपको जो चाहिए उसे निर्भर करते हुए, आपको अपनी जेनरेटर गुणवत्ता का परीक्षण करना चाहिए। मोंटे कार्लो विधि एक छद्म यादृच्छिक संख्या जेनरेटर का एक बहुत अच्छा अनुमानक है।

2

ठीक है यहां आपके इनपुट पर विचार करने के बाद किए गए परिवर्तन हैं। रास्ते से सबकुछ के लिए धन्यवाद!

unsigned int good_seed() 
{ 
    unsigned int random_seed, random_seed_a, random_seed_b; 
    std::ifstream file ("/dev/urandom", std::ios::binary); 
    if (file.is_open()) 
    { 
     char * memblock; 
     int size = sizeof(int); 
     memblock = new char [size]; 
     file.read (memblock, size); 
     file.close(); 
     random_seed_a = *reinterpret_cast<int*>(memblock); 
     delete[] memblock; 
    }// end if 
    else 
    { 
     random_seed_a = 0; 
    } 
    random_seed_b = std::time(0); 
    random_seed = random_seed_a xor random_seed_b; 
    std::cout << "random_seed_a = " << random_seed_a << std::endl; 
    std::cout << "random_seed_b = " << random_seed_b << std::endl; 
    std::cout << " random_seed = " << random_seed << std::endl; 
    return random_seed; 
} // end good_seed()