2011-08-27 14 views
23

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

srand((unsigned int)time(0)); 
int i = rand();

वहाँ यादृच्छिक संख्या इंजन, वितरण, और बीज के लिए उचित चूक रहे हैं कि कोई बॉक्स से बाहर निकल सकता है?

+0

विकिपीडिया? http://en.wikipedia.org/wiki/C%2B%2B0x#Extensible_random_number_facility – quasiverse

+2

आपके पास कोड के साथ क्या गलत है? AFAIK, नए यादृच्छिक संख्या जनरेटर को अधिक "गंभीर" अनुप्रयोगों के लिए जोड़ा गया था जहां यादृच्छिक संख्या पीढ़ी के पहलू वास्तव में मायने रखते हैं। – GManNickG

+3

@GMan: निष्पक्ष होने के लिए, नए मानक में यादृच्छिक संख्या इंजनों में से कई को सरल और तेज़ के रूप में वर्णित किया जा सकता है और मैं उन्हें विशेष रूप से "गंभीर" के रूप में नहीं देखूंगा। –

उत्तर

30

आप की तरह कुछ करने के लिए सक्षम होना चाहिए:

std::default_random_engine e((unsigned int)time(0)); 
int i = e(); 

default_random_engine की गुणवत्ता कार्यान्वयन निर्भर है। तुम भी std::min_rand0 या std::min_rand इस्तेमाल कर सकते हैं।

शायद एक बेहतर एक यादृच्छिक इंजन बीज के रास्ते सच के रूप में एक यादृच्छिक संख्या के साथ है के रूप में के बजाय कार्यान्वयन से उपलब्ध है time का उपयोग करें।

उदा।

std::random_device rd; 
std::default_random_engine e(rd()); 
+1

स्पष्टीकरण के लिए, क्या आपका मतलब "चाहिए" जैसा कि "यह अस्तित्व में नहीं है लेकिन इसे" या "एसडी" होना चाहिए और आपके कंपाइलर को इसका समर्थन करना चाहिए "? – GManNickG

+8

सूचनात्मक: इस उत्तर और ओपी के उदाहरण के बीच सबसे बड़ा अंतर यह है कि कोडर नियंत्रण करता है जहां इंजन का राज्य है: यह 'ई' में है। ओपी के कोड में राज्य 'रैंड' के अंदर स्थिर डेटा के रूप में छिपा हुआ है। बहुप्रचारित कार्यक्रमों से निपटने के दौरान यह एक महत्वपूर्ण अंतर है। 'रैंड' को इसे थ्रेड सुरक्षित बनाने के लिए किसी तरह की सुरक्षा होनी चाहिए। 'default_random_engine' नहीं है। यदि आप इसे एकाधिक धागे से कॉल करना चाहते हैं, तो आप बाहरी रूप से सिंक्रनाइज़ेशन तंत्र स्वयं प्रदान करते हैं। इसका अर्थ यह है कि यदि आपको इसे सिंक्रनाइज़ करने की आवश्यकता नहीं है तो 'default_random_engine' तेज हो सकता है। –

+0

@GMan: इसका मतलब है कि इस समय मेरे पास केवल एक ही कार्यान्वयन है जिसका समर्थन नहीं है, इसलिए मैं अपने कोड का परीक्षण करने में सक्षम नहीं हूं;)। –

2

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

0

रैंडम संख्या पीढ़ी एक कठिन समस्या है। ऐसा करने के लिए वास्तव में यादृच्छिक तरीका नहीं है। यदि आप सिर्फ एक गेम पर्यावरण के लिए यादृच्छिकता पैदा कर रहे हैं तो आपका दृष्टिकोण ठीक होना चाहिए। रैंड() में कई कमियां हैं।

आप अनियमितता की आवश्यकता होगी, रहे हैं तो एन्क्रिप्शन कुंजी उत्पन्न करने के लिए आप S.O.L. रहे उस मामले में सबसे अच्छा तरीका ऑपरेटिंग सिस्टम में जाना है, जिसमें आमतौर पर तंत्र होता है। POSIX पर जो यादृच्छिक() है (या यदि आप इतना डिस्पोजेड हैं तो/dev/यादृच्छिक से पढ़ें)।

https://www.securecoding.cert.org/confluence/display/seccode/MSC30-C.+Do+not+use+the+rand%28%29+function+for+generating+pseudorandom+numbers

0

आप RC4 इस्तेमाल कर सकते हैं यादृच्छिक बाइट्स उत्पन्न करने के लिए: Windows पर आप CryptoAPI उपयोग कर सकते हैं। यह संभवत: वे गुण हैं जो आप चाहते हैं। यह लागू करने के लिए तेज़ और काफी सरल है। जब बीज ज्ञात होता है तो अनुक्रम दो कार्यान्वयन में दोहराया जा सकता है, और जब बीज ज्ञात नहीं होता है तो पूरी तरह अप्रत्याशित होता है। http://en.wikipedia.org/wiki/RC4

2

मैं अपने प्रोजेक्ट में निम्न कोड का उपयोग करें। 'इंजन' और 'वितरण' लाइब्रेरी द्वारा प्रदान की जाने वाली एक हो सकती है।

#include <random> 
#include <functional> 
#include <iostream> 
... 
std::uniform_int_distribution<unsigned int> unif; 
std::random_device rd; 
std::mt19937 engine(rd()); 
std::function<unsigned int()> rnd = std::bind(unif, engine); 

std::cout << rnd() << '\n'; 
6

एकीकृत और नमूने पहले से ही मैं करने के लिए संक्षेप में प्रस्तुत करेंगे प्रदान किए गए कुछ सरल बनाने:

// Good random seed, good engine 
auto rnd1 = std::mt19937(std::random_device{}()); 

// Good random seed, default engine 
auto rnd2 = std::default_random_engine(std::random_device{}()); 

// like rnd1, but force distribution to int32_t range 
auto rnd3 = std::bind(std::uniform_int_distribution<int32_t>{}, std::mt19937(std::random_device{}())); 

// like rnd3, but force distribution across negative numbers as well 
auto rnd4 = std::bind(std::uniform_int_distribution<int32_t>{std::numeric_limits<int32_t>::min(),std::numeric_limits<int32_t>::max()}, std::mt19937(std::random_device{}())); 

तो मैं कुछ परीक्षण चलाया, तो चूक की तरह लग रही देखने के लिए:

#include <random> 
#include <functional> 
#include <limits> 
#include <iostream> 

template<class Func> 
void print_min_mean_max(Func f) { 
    typedef decltype(f()) ret_t; 
    ret_t min = std::numeric_limits<ret_t>::max(), max = std::numeric_limits<ret_t>::min(); 
    uint64_t total = 0, count = 10000000; 
    for (uint64_t i = 0; i < count; ++i) { 
     auto res = f(); 
     min = std::min(min,res); 
     max = std::max(max,res); 
     total += res; 
    } 
    std::cout << "min: " << min << " mean: " << (total/count) << " max: " << max << std::endl; 
} 

int main() { 
    auto rnd1 = std::mt19937(std::random_device{}()); 
    auto rnd2 = std::default_random_engine(std::random_device{}()); 

    auto rnd3 = std::bind(std::uniform_int_distribution<int32_t>{}, std::mt19937(std::random_device{}())); 
    auto rnd4 = std::bind(std::uniform_int_distribution<int32_t>{std::numeric_limits<int32_t>::min(),std::numeric_limits<int32_t>::max()}, std::mt19937(std::random_device{}())); 

    print_min_mean_max(rnd1); 
    print_min_mean_max(rnd2); 
    print_min_mean_max(rnd3); 
    print_min_mean_max(rnd4); 
} 

का उत्पादन आउटपुट:

min: 234 mean: 2147328297 max: 4294966759 
min: 349 mean: 1073305503 max: 2147483423 
min: 601 mean: 1073779123 max: 2147483022 
min: -2147481965 mean: 178496 max: 2147482978 

तो जैसा कि हम देख सकते हैं, mt19937 और default_random_engine की एक अलग डिफ़ॉल्ट सीमा है, इसलिए uniform_int_distribution का उपयोग करने की सलाह दी जाती है।

इसके अलावा, डिफ़ॉल्ट वर्दी_इन_डिस्ट्रिब्यूशन [0, max_int] (गैर-नकारात्मक) है, यहां तक ​​कि एक हस्ताक्षरित पूर्णांक प्रकार का उपयोग करते समय भी। यदि आप पूर्ण सीमा चाहते हैं तो सीमा को स्पष्ट रूप से प्रदान करना होगा।

अंत में, its important to remember this इन दिनों कभी-कभी।

+2

ध्यान दें, 'std :: mt19937' का 64 बिट संस्करण है:' std :: mt19937_64' जो प्रति कॉल यादृच्छिकता के 64 बिट देता है। 'ऑटो rnd5 = std :: mt19937_64 (std :: random_device {}()); // मिनट: 4879020137534 माध्य: 1655417118684 अधिकतम: 18446741225191893648' – Sean

+0

वैसे, क्या यह कई वितरण और std :: bind() के साथ एक ही यादृच्छिक संख्या इंजन का पुन: उपयोग करना सुरक्षित है या क्या यह प्रत्येक वितरण को नए से जोड़ना बेहतर है इंजन उदाहरण? यह कैसे है: 'std :: mt19937_64 यादृच्छिक = std :: mt19937_64 (std :: random_device {}());' 'स्वचालित यादृच्छिकता = std :: बाइंड (std :: uniform_int_distribution (1, 4), यादृच्छिक);' 'ऑटो randomValue = std :: बाइंड (std :: uniform_real_distribution (-1.0, 1.0), यादृच्छिक);' – Xharlie

2

यहां आप जाते हैं। यादृच्छिक युगल एक श्रेणी में:

// For ints 
// replace _real_ with _int_, 
// <double> with <int> and use integer constants 

#include <random> 
#include <iostream> 
#include <ctime> 
#include <algorithm> 
#include <iterator> 

int main() 
{ 
    std::default_random_engine rng(std::random_device{}()); 
    std::uniform_real_distribution<double> dist(-100, 100); //(min, max) 

    //get one 
    const double random_num = dist(rng); 

    //or.. 
    //print 10 of them, for fun. 
    std::generate_n( 
     std::ostream_iterator<double>(std::cout, "\n"), 
     10, 
     [&]{ return dist(rng);}); 
    return 0; 
} 
संबंधित मुद्दे