2012-12-06 11 views
5

मैं अनिश्चित क्यों कोड के इन दो ब्लॉकों अलग आउटपुट देना हूँ:सी यादृच्छिक() & setstate समारोह से व्यवहार नहीं कर के रूप में उम्मीद

unsigned int seed1 = 0; 
char state1[256]; 
initstate(seed1, state1, 256); 
printf("%10ld\n", random()); 
printf("%10ld\n", random()); 
// Gives: 
// 1216130483 
// 1950449197 

बनाम

unsigned int seed1 = 0; 
char state1[256]; 
initstate(seed1, state1, 256); 
printf("%10ld\n", random()); 
setstate(state1); 
printf("%10ld\n", random()); 
// Gives: 
// 1216130483 
// 625602885 

मैं क्या setstate गलतफहमी हूँ() कर देता है?

संपादित करें: दिलचस्प बात यह यह है कि क्या देता है पर देखने के:

unsigned int seed1 = 0; 
char state1[256]; 
initstate(seed1, state1, 256); 
printf("%10ld\n", random()); 
setstate(state1); 
setstate(state1); 
printf("%10ld\n", random()); 
// Gives: 
// 1216130483 
// 1950449197 
+1

सी केवल rand' और 'srand' और न' random', 'initstate' या' setstate' है ' । कृपया अपने प्रश्न को अपने ओएस के साथ टैग करें। –

+1

@ जेन्सगस्टेड मैंने बीएसडी टैग जोड़ा। – unwind

+0

'gcc (डेबियन 4.4.5-8) 4.4.5 का उपयोग करके डेबियन (स्थिर) पर इस उदाहरण को चला रहा है, मुझे तीनों कोड स्निपेट के लिए समान दो संख्याएं मिलती हैं। – alk

उत्तर

2

मुझे लगता है कि initstate() करने के लिए कॉल भी है कि राज्य में परिवर्तन नहीं करता है, लेकिन setstate() करने के लिए कॉल, करता है यही वजह है कि बाद के है random() कॉल नए राज्य से उत्पन्न एक नंबर देता है।

+2

कोड के साथ प्रयोग करने के बाद, मुझे नहीं लगता कि यह मामला है। 'Inststate() 'के ठीक बाद' सेटस्टेट() 'पर कॉल जोड़ना कोई फर्क नहीं पड़ता। – NPE

3

दोनों कार्यान्वयन सही हैं।

सेटस्टेट आपके बफर पर इंगित करने के लिए नियमित रूप से एक स्थिर सूचक को बदलता है।

इंटस्टेट को एक ही चीज़ करने की अनुमति है, लेकिन पहले बफर सामग्री को बदलने की भी अनुमति है। यदि पीआरएनजी एआरसी 4 या स्प्रिट्ज की तरह कुछ है, तो बफर को केवल मनमानी बिट्स की बजाय क्रमपरिवर्तन होना चाहिए। यदि पीआरएनजी एक nonlinear additive प्रतिक्रिया जनरेटर है, तो कम से कम राज्य में कहीं कम बिट्स सेट करने की जरूरत है या यह सही काम नहीं करेगा। और कुछ libs हैश राज्य बफर है इसलिए यह कहना आसान नहीं होगा कि बीज + आउटपुट जानकारी से किस प्रकार का पीआरएनजी उपयोग में है। उन्हें जरूरी नहीं है; lib libit और setstate के लिए बिल्कुल वही काम कर सकता है यदि जेनरेटर इसका उपयोग कर रहा है तो वह एक LFSG है या ऐसा कुछ जिसे किसी विशेष प्रारूप की आवश्यकता नहीं है या बफर के लिए कोई स्थिरता आवश्यकता नहीं है। लेकिन अगर आप इनस्टस्टेट नहीं करते हैं, और आपका ओएस ऐसी किसी चीज का उपयोग करता है जिसमें ऐसी ज़रूरतें हैं, तो आपका दोहराया जाने वाला अनुक्रम उतना ही अप्रत्याशित नहीं हो सकता जितना आप चाहें।

2

setstate का बीएसडी कार्यान्वयन पुरानी बफर को संग्रहीत करने से पहले त्रुटि जांच उद्देश्यों के लिए सहायक राज्य जानकारी लोड करता है। इसके अतिरिक्त initstate और setstate एकमात्र ऐसे कार्य हैं जो इस जानकारी को अपडेट करते हैं। इसका मतलब है कि जब एक ही बफर का उपयोग किया जाता है तो यह loads stale state, stores the new data, और updates the internal state with the former है। इस तरह से setstate को कॉल करने से बार-बार पुरानी संग्रहीत स्थिति और वर्तमान आंतरिक स्थिति वैकल्पिक हो जाएगी, जिसके परिणामस्वरूप परिणाम दो बार बुलाए जाते हैं।

The comment for setstate कहता है कि वर्तमान बफर के साथ इसे कॉल करना ठीक है, इसलिए या तो यह इच्छित व्यवहार है, या decades old बग है।

ध्यान दें कि जिस क्रम में बातें किया जाता है के कारण, यह setstate() कॉल करने के लिए वर्तमान स्थिति के रूप में ही राज्य के साथ ठीक है।

1

initstate() यादृच्छिक बताता है कि बफर अगले यादृच्छिक संख्या के लिए जानकारी स्टोर करने के लिए उपयोग करने के लिए। आपको random() पर कॉल में अलग-अलग उत्तर मिलते हैं क्योंकि आपके बफर state1[256] में जानकारी बदल गई है।निम्नलिखित कोड के उत्पादन को देखो:

#define LEN (32) 
void print_hex(char *b) 
{ 
    int i; 
    for(i=0; i < LEN; i++) printf("%02x ",((unsigned char *)b)[i]);  
    printf("\n"); 
} 

main() 
{ 
    char state1[256], state2[256], tmp[256]; 
    initstate(42, state2, LEN); 
    initstate(62, state1, LEN) ; 
    printf("buffer before random():\n"); 
    print_hex(state1) ; 
    printf("%10ld\n", random()); 
    printf("buffer after random():\n"); 
    print_hex(state1) ; 

    setstate(state2); // Now we are free to copy data from state1 
    printf("buffer after setstate():\n"); 
    print_hex(state1) ; 
    memcpy(tmp, state1, 256); 
    printf("copied to tmp\n"); 

    setstate(state1); // Go on with original sequence 
    printf("next random():\n") ; 
    printf("%10ld\n", random()); 
    printf("next random():\n") ; 
    printf("%10ld\n", random()); 

    setstate(state2) ; // Again, this allows us to play with data in state1 
    memcpy(state1, tmp, 256); 
    setstate(state1) ; 
    printf("back copy:\n"); 
    printf("random() after copy:\n") ; 
    printf("%10ld\n", random()); 
    printf("next random():\n") ; 
    printf("%10ld\n", random()); 
} 

यह आउटपुट देता है:

buffer before random(): 
01 00 00 00 e7 22 1d 21 f1 62 9c 90 89 72 b5 89 35 2b 97 b5 76 8c ff a8 56 14 14 7b ba 19 d9 f7 
1801070350 
buffer after random(): 
01 00 00 00 e7 22 1d 21 f1 62 9c 90 89 72 b5 89 1c 4e b4 d6 76 8c ff a8 56 14 14 7b ba 19 d9 f7 
buffer after setstate(): 
06 00 00 00 e7 22 1d 21 f1 62 9c 90 89 72 b5 89 1c 4e b4 d6 76 8c ff a8 56 14 14 7b ba 19 d9 f7 
copied to tmp 
next random(): 
483260339 
next random(): 
    40158063 
back copy: 
random() after copy: 
483260339 
next random(): 
40158063 

आप बफर state1 की सामग्री बदलती random() को देख सकते हैं कि पहली कॉल के बाद। random() उस क्षेत्र का उपयोग अपने राज्य को संग्रहीत करने के लिए करता है। इस राज्य को बफर tmp पर कॉपी किया गया है। बाद में हम इसे state1 पर कॉपी करते हैं, और यादृच्छिक संख्याओं का एक ही अनुक्रम प्राप्त करते हैं। ध्यान दें कि यादृच्छिक संख्याओं के लिए उपयोग किए जाने वाले बफर से कॉपी करने से पहले आपको या initstate() का उपयोग करके उस बफर का उपयोग रोकने के लिए random() बताना होगा। इसका कारण यह है कि जब setstate() कहा जाता है, तो पुराने बफर को setstate() के साथ फिर से लोड करने की अनुमति देने के लिए संशोधित किया जाता है।

तो मूल प्रश्न में के रूप में ही जवाब पाने के लिए, आप का उपयोग करना होगा:

unsigned int seed1 = 42; 
char state1[256], tmp[256]; 
initstate(seed1, state1, 256); 
printf("%10ld\n", random()); 
initstate(0, tmp, 256); // <- notice this 
setstate(state1) ; 
printf("%10ld\n", random()); 
संबंधित मुद्दे