2012-04-17 9 views
19

मैं अपने कार्यक्रम में सी ++ रैंड() फ़ंक्शन के आधार पर कुछ हज़ार ऑब्जेक्ट उत्पन्न करता हूं। उन्हें स्मृति में रखते हुए संपूर्ण होगा। क्या किसी भी समय रैंड() के वर्तमान बीज की प्रतिलिपि बनाने का कोई तरीका है? यह मुझे केवल मौजूदा बीजों को स्टोर करने का अवसर प्रदान करेगा, न कि पूर्ण वस्तुओं को। (इस प्रकार मैं उन वस्तुओं पुनर्जीवित कर सकता, यादृच्छिक संख्या का ठीक उसी उप दृश्यों पुनः द्वारा)सी ++ रैंड() से वर्तमान बीज कैसे प्राप्त करें?

एक संपूर्ण समाधान) रैंड (द्वारा दिए गए पूर्ण यादृच्छिक संख्या के अनुक्रम भंडारण है - इसके लायक नहीं है। एक और समाधान यादृच्छिक संख्याओं के लिए अपनी कक्षा को लागू करना है।

Google ने मुझे कोई सकारात्मक संकेत नहीं दिया। रैंड और एसआरएंड की मूल बातें सिखाते हुए सैकड़ों लेख हैं, और मुझे विशिष्ट नहीं मिल सका।

क्या कोई भी लागू बीज-स्टीयरर के साथ अन्य यादृच्छिक संख्या जेनरेटर जानता है?


आपके तेज उत्तरों के लिए धन्यवाद! इस प्रश्न के लिए अधिक संभावित उत्तर/समाधान हैं, इसलिए मैंने यहां आपके उत्तरों की एक सूची बनाई है।

समाधान:

  1. संक्षिप्त उत्तर है: बीज

  2. निकटतम संभावित समाधान, शुरुआत में प्रारंभिक बीज बचाने के लिए, और गिनती कितने है पाने के लिए कोई मानक तरीका है बार आप रैंड() फ़ंक्शन को कॉल करते हैं। मैंने इसे समाधान के रूप में चिह्नित किया क्योंकि यह वर्तमान std :: rand()प्रत्येक कंपाइलर (और यह मुख्य प्रश्न था) पर कार्य करता है। मैंने अपने 2.0 गीगाहर्ट्ज सीपीयू को बेंचमार्क किया है, और पाया कि मैं & रैंड() 35 सेकंड में 1,000,000,000 बार गिन सकता हूं। यह अच्छा लग सकता है, लेकिन मेरे पास एक ऑब्जेक्ट उत्पन्न करने के लिए 80,000 कॉल हैं। यह पीढ़ियों की संख्या 50,000 तक सीमित करता है क्योंकि हस्ताक्षर किए गए लंबे आकार का आकार।

    class rand2 
    { 
        unsigned long n; 
    
        public: 
    
        rand2() : n(0) {} 
    
        unsigned long rnd() 
        { 
         n++; 
         return rand(); 
        } 
        // get number of rand() calls inside this object 
        unsigned long getno() 
        { 
         return n; 
        } 
        // fast forward to a saved position called rec 
        void fast_forward (unsigned long rec) 
        { 
         while (n < rec) rnd(); 
        } 
    }; 
    
  3. एक और तरीका है, अपने खुद के छद्म यादृच्छिक संख्या जनरेटर लागू करने के लिए है की तरह एक Matteo इटली का सुझाव दिया: वैसे भी, यहाँ मेरी कोड है। यह सबसे तेज़, और संभवतः सबसे अच्छा समाधान है। आप 4,294,967,295 रैंड() कॉल तक सीमित नहीं हैं, और अन्य पुस्तकालयों का उपयोग करने की आवश्यकता नहीं है। यह उल्लेखनीय है कि विभिन्न कंपाइलरों के पास अलग जनरेटर हैं। मैंने मैट्वे के एलसीजी की तुलना रैंड() मिंगव/जीसीसी 3.4.2 और जी ++ 4.3.2 में की है। उनमें से सभी अलग थे (बीज = 0 के साथ)।

  4. सी ++ 11 या अन्य पुस्तकालयों से जनरेटर का उपयोग करें कबी, जेरी कॉफिन और माइक सेमुर ने सुझाव दिया। यह सबसे अच्छा विचार है, अगर आप पहले से ही उनके साथ काम कर रहे हैं। सी ++ 11 जनरेटर के लिए लिंक: http://en.cppreference.com/w/cpp/numeric/random

+0

यदि समाधान 2 में केवल गिनती सीमा समस्या है तो आप ओवरफ्लो को गिनने के लिए एक और 'हस्ताक्षरित लंबा' काउंटर जोड़ सकते हैं। यह प्रभावी रूप से आपके काउंटर के बिट आकार को दोगुना कर देगा और, ज़ाहिर है, आगे बढ़ाया जा सकता है। – bjhend

+0

बीटीडब्लू, समाधान समाधान जोड़ने के लिए यह अच्छा है (अच्छी पुरानी यूजनेट परंपरा?)। – bjhend

+0

हे, नहीं। मुझे वास्तव में गूगल का उपयोग करना था जिसका अर्थ है :)। बस सोचा कि कुछ प्रतिक्रिया देना अच्छा होगा, कि उत्तर उपयोगी थे। – user1339629

उत्तर

5

उपयोग srand() बीज स्थापित करने के लिए (वहाँ कुछ एल्गोरिथ्म वर्णन यहाँ भी कर रहे हैं)। बीज के रूप में उपयोग किए जाने वाले मूल्य को बचाएं।

http://cplusplus.com/reference/clibrary/cstdlib/srand/

+5

यह ठीक है अगर आप पूरे अनुक्रम को फिर से बनाना चाहते हैं, लेकिन यदि आप किसी भी समय बीज को निकालना नहीं चाहते हैं। –

8

वहाँ वर्तमान बीज प्राप्त करने के लिए (आप केवल srand के माध्यम से यह निर्धारित कर सकते हैं) कोई मानक तरीका है, लेकिन आप कोड की कुछ लाइनों में rand() reimplement कर सकते हैं (जो आमतौर पर एक linear congruential generator है) खुद के द्वारा:

class LCG 
{ 
private: 
    unsigned long next = 1; 
public: 

    LCG(unsigned long seed) : next(seed) {} 

    const unsigned long rand_max = 32767 

    int rand() 
    { 
     next = next * 1103515245 + 12345; 
     return (unsigned int)(next/65536) % 32768; 
    } 

    void reseed(unsigned long seed) 
    { 
     next = seed; 
    } 

    unsigned long getseed() 
    { 
     return next; 
    } 
}; 
13

किसी को भी लागू किया बीज चोर के साथ अन्य यादृच्छिक संख्या जनरेटर पता है

सभी मानक सी ++ 11 यादृच्छिक संख्या जनरेटर (TR1 और बूस्ट में भी उपलब्ध) इस कार्यक्षमता की पेशकश करते हैं। आप जनरेटर ऑब्जेक्ट्स को प्रतिलिपि बना सकते हैं या उन्हें क्रमबद्ध/deserialize कर सकते हैं।

सी ++ 11 समर्थन operator<< उसे वापस पढ़ने के लिए अपने राज्य (ज्यादातर बीज) और operator>> स्टोर करने के लिए में
5

यादृच्छिक संख्या पीढ़ी वर्गों। तो, मूल रूप से, इससे पहले कि आप अपने वस्तुओं को बनाने, राज्य, बचाने के फिर जब आप उसी अनुक्रम को फिर से उत्पन्न करने की आवश्यकता है, राज्य को वापस पढ़ें, और आप जाने से बाहर।

4

rand() बीज निकालने या डुप्लिकेट करने का कोई तरीका नहीं प्रदान करता है। सबसे अच्छा आप बीज के प्रारंभिक मूल्य को स्टोर कर सकते हैं जब आप इसे srand() के साथ सेट करते हैं, और फिर उस से पूरे अनुक्रम का पुनर्निर्माण करते हैं।

पॉज़िक्स फ़ंक्शन rand_r() आपको बीज का नियंत्रण देता है।

सी ++ 11 लाइब्रेरी में अनुक्रम-उत्पन्न "इंजन" के आधार पर एक यादृच्छिक संख्या लाइब्रेरी शामिल है; ये इंजन कॉपी करने योग्य हैं, और << और >> ऑपरेटरों के साथ उनके राज्य को निकालने और पुनर्स्थापित करने की अनुमति देते हैं, ताकि आप किसी भी समय अनुक्रम की स्थिति को कैप्चर कर सकें। टीआर 1 और बूस्ट में बहुत ही समान पुस्तकालय उपलब्ध हैं, यदि आप अभी तक सी ++ 11 का उपयोग नहीं कर सकते हैं।

1

आप उस मूल्य को सहेजने का प्रयास कर सकते हैं जिसे आपने बीज के पहले (या उसके बाद) बीज में उपयोग किया था।

तो, उदाहरण के लिए:

int seed = time(NULL); 
srand(time(NULL)); 

cout << seed << endl; 
cout << time(NULL); 

दो मानों ही होना चाहिए।

0

मैं आपको Mersenne Twister Pseudo-Random Number Generator का उपयोग करने की सलाह दूंगा। यह तेज़ है और बहुत अच्छी यादृच्छिक संख्या प्रदान करता है। आप

unsigned long rSeed = 10; 
MTRand myRandGen(rSeed); 

तो फिर तुम सिर्फ कहीं बीज आप दृश्यों उत्पन्न करने के लिए इस्तेमाल किया स्टोर करने के लिए की जरूरत से बहुत बस वर्ग के निर्माता में जनरेटर बीज कर सकते हैं ...

0

वहाँ करने के लिए एक रास्ता है किसी भी समय रैंड() के वर्तमान बीज की प्रतिलिपि बनाएँ?

क्या इस प्रकार बचाने के लिए और छद्म यादृच्छिक संख्या जनरेटर (PRNG) राज्य कि उबंटू लिनक्स पर सी पुस्तकालय (14.04 और 16.04 पर परीक्षण) के साथ काम करता बहाल करने के लिए एक कार्यान्वयन-विशिष्ट तरीका है।

#include <array> 
#include <cstdlib> 
#include <iostream> 

using namespace std; 

constexpr size_t StateSize = 128; 
using RandState = array<char, StateSize>; 

void save(RandState& state) { 
    RandState tmpState; 
    char* oldState = initstate(1, tmpState.data(), StateSize); 
    copy(oldState, oldState + StateSize, state.data()); 
    setstate(oldState); 
} 

void restore(RandState& state) { 
    setstate(state.data()); 
} 

int main() { 
    cout << "srand(1)\n"; 

    srand(1); 

    cout << " rand(): " << rand() << '\n'; 
    cout << " rand(): " << rand() << '\n'; 
    cout << " rand(): " << rand() << '\n'; 
    cout << " rand(): " << rand() << '\n'; 
    cout << " rand(): " << rand() << '\n'; 
    cout << " rand(): " << rand() << '\n'; 
    cout << " rand(): " << rand() << '\n'; 
    cout << " rand(): " << rand() << '\n'; 

    cout << "srand(1)\n"; 

    srand(1); 

    cout << " rand(): " << rand() << '\n'; 
    cout << " rand(): " << rand() << '\n'; 
    cout << " rand(): " << rand() << '\n'; 
    cout << " rand(): " << rand() << '\n'; 

    cout << "save()\n"; 

    RandState state; 
    save(state); 

    cout << " rand(): " << rand() << '\n'; 
    cout << " rand(): " << rand() << '\n'; 
    cout << " rand(): " << rand() << '\n'; 
    cout << " rand(): " << rand() << '\n'; 

    cout << "restore()\n"; 

    restore(state); 

    cout << " rand(): " << rand() << '\n'; 
    cout << " rand(): " << rand() << '\n'; 
    cout << " rand(): " << rand() << '\n'; 
    cout << " rand(): " << rand() << '\n'; 
} 

इस पर निर्भर करता है:

  1. ही PRNG सी पुस्तकालय द्वारा किया जा रहा दोनों rand() और random() इंटरफेस का पर्दाफाश करने के लिए, और
  2. सी में इस PRNG के डिफ़ॉल्ट प्रारंभ के बारे में कुछ ज्ञान पुस्तकालय (128 बाइट्स राज्य)।

हैं चलाने के लिए, यह होना चाहिए उत्पादन:

srand(1) 
    rand(): 1804289383 
    rand(): 846930886 
    rand(): 1681692777 
    rand(): 1714636915 
    rand(): 1957747793 
    rand(): 424238335 
    rand(): 719885386 
    rand(): 1649760492 
srand(1) 
    rand(): 1804289383 
    rand(): 846930886 
    rand(): 1681692777 
    rand(): 1714636915 
save() 
    rand(): 1957747793 
    rand(): 424238335 
    rand(): 719885386 
    rand(): 1649760492 
restore() 
    rand(): 1957747793 
    rand(): 424238335 
    rand(): 719885386 
    rand(): 1649760492 

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

संबंधित मुद्दे