क्या असंगठित स्थानीय चर सबसे तेजी से यादृच्छिक संख्या जनरेटर है?


329

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

void updateEffect(){
    for(int i=0;i<1000;i++){
        int r;
        int g;
        int b;
        star[i].setColor(r%255,g%255,b%255);
        bool isVisible;
        star[i].setVisible(isVisible);
    }
}

क्या यह उससे तेज है

void updateEffect(){
    for(int i=0;i<1000;i++){
        star[i].setColor(rand()%255,rand()%255,rand()%255);
        star[i].setVisible(rand()%2==0?true:false);
    }
}

और भी अन्य यादृच्छिक संख्या जनरेटर की तुलना में तेजी से?


88
+1 यह पूरी तरह से वैध सवाल है। यह सच है कि व्यवहार में, अनधिकृत मान थोड़े यादृच्छिक हो सकते हैं। तथ्य यह है कि वे विशेष रूप से नहीं हैं और यह है कि यह यूबी कि बुरा पूछ नहीं है ।
imallett

35
@ हिमालय: बिल्कुल। यह एक अच्छा सवाल है, और कम से कम एक पुराना Z80 (Amstrad / ZX स्पेक्ट्रम) खेल अतीत में अपने इलाके को स्थापित करने के लिए डेटा के रूप में अपने कार्यक्रम का उपयोग करता है। तो वहाँ भी मिसाल हैं। इन दिनों ऐसा नहीं कर सकते। आधुनिक ऑपरेटिंग सिस्टम सभी मज़ा को दूर ले जाते हैं।
बाथशीबा

81
निश्चित रूप से मुख्य समस्या यह है कि यह यादृच्छिक नहीं है।
जॉन

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

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

जवाबों:


299

जैसा कि अन्य ने उल्लेख किया है, यह पूर्वनिर्धारित व्यवहार (यूबी) है।

व्यवहार में, यह (शायद) वास्तव में (तरह का) काम करेगा। X86 [-64] आर्किटेक्चर पर एक गैर-पंजीकृत रजिस्टर से पढ़ना वास्तव में कचरा परिणाम उत्पन्न करेगा, और शायद कुछ भी बुरा नहीं करेगा (उदाहरण के लिए इटेनियम का विरोध, जहां रजिस्टरों को अमान्य के रूप में चिह्नित किया जा सकता है , ताकि एनएएन के अनुसार प्रचार त्रुटियों को पढ़ सके)।

हालांकि दो मुख्य समस्याएं हैं:

  1. यह विशेष रूप से यादृच्छिक नहीं होगा। इस स्थिति में, आप स्टैक से पढ़ रहे हैं, इसलिए आपको पहले जो कुछ भी था वह मिलेगा। जो प्रभावी रूप से यादृच्छिक, पूरी तरह से संरचित हो सकता है, वह पासवर्ड जो आपने दस मिनट पहले दर्ज किया था, या आपकी दादी माँ की कुकी रेसिपी।

  2. यह बैड (कैपिटल 'बी') है जो इस तरह की चीजों को अपने कोड में डालने के लिए अभ्यास करता है। तकनीकी रूप से, कंपाइलर reformat_hdd();हर बार जब आप अपरिभाषित चर पढ़ सकते हैं। यह नहीं होगा , लेकिन आप इसे वैसे भी नहीं करना चाहिए। असुरक्षित चीजें न करें। आपके द्वारा किए गए कम अपवाद, आप सभी की आकस्मिक गलतियों से सुरक्षित हैं समय।

यूबी के साथ अधिक दबाव वाला मुद्दा यह है कि यह आपके पूरे कार्यक्रम के व्यवहार को अपरिभाषित बनाता है। आधुनिक संकलक इसका उपयोग आपके कोड के विशाल स्वाथों को समाप्त करने के लिए कर सकते हैं या यहां तक ​​कि समय में वापस जा सकते हैं । यूबी के साथ खेलना एक विक्टोरियन इंजीनियर की तरह है जो एक जीवित परमाणु रिएक्टर को नष्ट करता है। गलत होने के लिए एक zillion चीजें हैं, और आप शायद आधे अंतर्निहित सिद्धांतों या कार्यान्वित प्रौद्योगिकी को नहीं जान पाएंगे। यह ठीक हो सकता है, लेकिन आपको अभी भी ऐसा नहीं होने देना चाहिए। विवरण के लिए अन्य अच्छे उत्तरों को देखें।

इसके अलावा, मैं तुम्हें आग लगा दूँगा।


39
@Potatoswatter: इटेनियम रजिस्टर में NaT (नॉट थिंग) हो सकता है जो वास्तव में एक "अनइंस्टालर्ड रजिस्टर" है। इटेनियम पर, जब आपने इसे नहीं लिखा है तो एक रजिस्टर से पढ़ना आपके प्रोग्राम को रद्द कर सकता है (इस पर और अधिक पढ़ें: blogs.msdn.com/b/oldnewthing/archive/2004/01/19/60162.aspx )। इसलिए एक अच्छा कारण है कि असंवैधानिक मूल्यों को पढ़ना अपरिभाषित व्यवहार है। यह भी शायद एक कारण है कि इटेनियम बहुत लोकप्रिय नहीं है :)
टेबलर

58
मुझे वास्तव में "यह इस तरह के कार्यों" की धारणा पर आपत्ति है। भले ही आज यह सच था, जो कि यह नहीं है, यह किसी भी समय अधिक आक्रामक संकलक के कारण बदल सकता है। कंपाइलर किसी भी रीड unreachable()को आपके प्रोग्राम के आधे हिस्से से हटा सकता है। ऐसा व्यवहार में भी होता है। इस व्यवहार ने कुछ लिनक्स डिस्ट्रो में RNG को पूरी तरह से बेअसर कर दिया। इस प्रश्न के अधिकांश जवाबों से लगता है कि एक अनैतिक मूल्य एक मूल्य की तरह व्यवहार करता है। वह झूठा है।
यूएसआर

25
इसके अलावा, मुझे लगता है कि आप कहने के लिए एक अच्छी तरह से मूर्खतापूर्ण बात लगती है, यह मानते हुए कि यह अच्छा व्यवहार है, इसे कोड समीक्षा में पकड़ा जाना चाहिए, चर्चा की जानी चाहिए और फिर कभी नहीं होनी चाहिए। यह निश्चित रूप से पकड़ा जाना चाहिए क्योंकि हम सही चेतावनी झंडे का उपयोग कर रहे हैं, है ना?
शफिक याघमोर

17
@ मिचेल वास्तव में, यह है। यदि किसी कार्यक्रम में किसी भी बिंदु पर अपरिभाषित व्यवहार होता है, तो कंपाइलर आपके प्रोग्राम को इस तरह से अनुकूलित कर सकता है जो कि कोड को पूर्ववर्ती को प्रभावित करता है जो अपरिभाषित व्यवहार को प्रभावित करता है। इस बात की विभिन्न लेखों और प्रदर्शनों से पता चलता है कि यह किस तरह से टकराता है, यहाँ एक बहुत अच्छा मिल सकता है: blogs.msdn.com/b/oldnewthing/archive/2014/06/27/10537746.aspx (जिसमें मानक में बिट शामिल है जो कहता है सभी दांव बंद हो गए हैं यदि आपके कार्यक्रम में कोई पथ यूबी को आमंत्रित करता है)
टॉम टान्नर

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

213

मुझे यह स्पष्ट रूप से कहना चाहिए: हम अपने कार्यक्रमों में अपरिभाषित व्यवहार नहीं करते हैं । यह कभी भी एक अच्छा विचार नहीं है, अवधि। इस नियम के दुर्लभ अपवाद हैं; उदाहरण के लिए, यदि आप एक पुस्तकालय कार्यान्वयनकर्ता हैं जो ऑफसेटऑफ़ को लागू कर रहे हैं । यदि आपका मामला इस तरह के अपवाद के अंतर्गत आता है, तो आप यह पहले से ही जानते हैं। इस मामले में हम जानते हैं कि असिंचित स्वचालित चर का उपयोग करना अपरिभाषित व्यवहार है

अपरिभाषित व्यवहार के आस-पास अनुकूलन के साथ कंपाइलर बहुत आक्रामक हो गए हैं और हम कई ऐसे मामलों का पता लगा सकते हैं जहां अपरिभाषित व्यवहार से सुरक्षा को खतरा है। सबसे बदनाम मामला शायद लिनक्स कर्नेल नल पॉइंटर चेक रिमूवल है जिसे मैं अपने जवाब में C ++ संकलन बग के लिए उल्लेख करता हूं ? जहां अपरिभाषित व्यवहार के आसपास एक संकलक अनुकूलन ने एक अनंत लूप को अनंत में बदल दिया।

हम सीईआरटी के खतरनाक अनुकूलन और नुकसान का कारण ( वीडियो ) पढ़ सकते हैं, जो अन्य बातों के साथ कहता है:

तेजी से, संकलक लेखक अनुकूलन को बेहतर बनाने के लिए C और C ++ प्रोग्रामिंग भाषाओं में अपरिभाषित व्यवहारों का लाभ उठा रहे हैं।

अक्सर, ये अनुकूलन अपने स्रोत कोड पर कारण-प्रभाव विश्लेषण करने के लिए डेवलपर्स की क्षमता के साथ हस्तक्षेप कर रहे हैं, अर्थात्, पूर्व परिणामों पर डाउनस्ट्रीम परिणामों की निर्भरता का विश्लेषण कर रहे हैं।

नतीजतन, ये अनुकूलन सॉफ्टवेयर में कार्य-कारण को समाप्त कर रहे हैं और सॉफ्टवेयर दोष, दोष और कमजोरियों की संभावना को बढ़ा रहे हैं।

विशेष रूप से अनिश्चित मानों के संबंध में, सी मानक दोष रिपोर्ट 451: कुछ रोचक पढ़ने के लिए असिंचित स्वचालित चर की अस्थिरता । इसे अभी तक हल नहीं किया गया है, लेकिन वल्बी मूल्यों की अवधारणा का परिचय देता है जिसका अर्थ है कि मूल्य की अनिश्चितता कार्यक्रम के माध्यम से प्रचारित हो सकती है और कार्यक्रम में विभिन्न बिंदुओं पर अलग-अलग अनिश्चित मान हो सकते हैं।

मुझे ऐसा कोई उदाहरण नहीं पता है कि ऐसा कहां होता है लेकिन इस बिंदु पर हम इसे खारिज नहीं कर सकते।

वास्तविक उदाहरण, वह परिणाम नहीं जिसकी आप अपेक्षा करते हैं

आपको यादृच्छिक मान प्राप्त होने की संभावना नहीं है। एक संकलक दूर पाश को पूरी तरह से अनुकूलित कर सकता है। उदाहरण के लिए, इस सरलीकृत मामले के साथ:

void updateEffect(int  arr[20]){
    for(int i=0;i<20;i++){
        int r ;    
        arr[i] = r ;
    }
}

क्लैंग इसे दूर करता है ( इसे लाइव देखें ):

updateEffect(int*):                     # @updateEffect(int*)
    retq

या शायद सभी शून्य प्राप्त करें, इस संशोधित मामले के साथ:

void updateEffect(int  arr[20]){
    for(int i=0;i<20;i++){
        int r ;    
        arr[i] = r%255 ;
    }
}

इसे लाइव देखें :

updateEffect(int*):                     # @updateEffect(int*)
    xorps   %xmm0, %xmm0
    movups  %xmm0, 64(%rdi)
    movups  %xmm0, 48(%rdi)
    movups  %xmm0, 32(%rdi)
    movups  %xmm0, 16(%rdi)
    movups  %xmm0, (%rdi)
    retq

ये दोनों मामले अपरिभाषित व्यवहार के बिल्कुल स्वीकार्य रूप हैं।

ध्यान दें, यदि हम एक इटेनियम पर हैं तो हम एक ट्रैप वैल्यू के साथ समाप्त हो सकते हैं :

[...] यदि रजिस्टर एक विशेष नॉट-ए-मान रखने के लिए होता है, तो कुछ निर्देशों को छोड़कर रजिस्टर ट्रैप को पढ़ना [...]

अन्य महत्वपूर्ण नोट्स

यूबी कैनरी परियोजना में जीसीसी और क्लैंग के बीच विचरण को ध्यान में रखते हुए यह ध्यान रखना दिलचस्प है कि वे असंबद्ध स्मृति के संबंध में अपरिभाषित व्यवहार का लाभ उठाने के लिए कितने इच्छुक हैं। लेख नोट्स ( जोर मेरा ):

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

जैसा कि मैथ्यू एम। बताता है कि हर सी प्रोग्रामर को अपरिभाषित व्यवहार के बारे में क्या जानना चाहिए # 2/3 भी इस प्रश्न के लिए प्रासंगिक है। यह अन्य बातों के बीच कहता है ( मेरा जोर ):

एहसास करने के लिए महत्वपूर्ण और डरावना बात यह है कि अपरिभाषित व्यवहार के आधार पर किसी भी अनुकूलन के बारे में भविष्य में किसी भी समय छोटी गाड़ी कोड पर शुरू किया जा सकता है । इनलाइनिंग, लूप अनरोलिंग, मेमोरी प्रमोशन और अन्य अनुकूलन बेहतर होते रहेंगे, और मौजूदा के लिए उनके कारण का एक महत्वपूर्ण हिस्सा ऊपर की तरह माध्यमिक अनुकूलन को उजागर करना है।

मेरे लिए, यह गहरा असंतोषजनक है, आंशिक रूप से क्योंकि संकलक अनिवार्य रूप से समाप्त हो रहा है, लेकिन यह भी क्योंकि इसका मतलब है कि सी कोड के विशाल निकाय केवल विस्फोट करने के लिए इंतजार कर रहे हैं।

पूर्णता के लिए, मुझे संभवतः यह उल्लेख करना चाहिए कि कार्यान्वयन अपरिभाषित व्यवहार को अच्छी तरह से परिभाषित करने का विकल्प चुन सकते हैं, उदाहरण के लिए जीसीसी यूनियनों के माध्यम से टाइपिंग की अनुमति देता है जबकि सी ++ में यह अपरिभाषित व्यवहार की तरह लगता है । यदि यह मामला है तो कार्यान्वयन को इसका दस्तावेज बनाना चाहिए और यह आमतौर पर पोर्टेबल नहीं होगा।


1
कंपाइलर आउटपुट उदाहरणों के लिए + (int) (PI / 3); एक वास्तविक जीवन का उदाहरण है कि यूबी, ठीक है, यूबी है

2
यूबी का उपयोग प्रभावी रूप से एक उत्कृष्ट हैकर का ट्रेडमार्क हुआ करता था। यह परंपरा शायद 50 साल या उससे अधिक समय के लिए चली गई है। दुर्भाग्य से, कंप्यूटर को अब खराब लोगों के कारण यूबी के प्रभावों को कम करने की आवश्यकता है। मुझे वास्तव में यह पता लगाने में मज़ा आया कि यूबी मशीन कोड या पोर्ट रीड / राइट्स आदि के साथ शांत चीजें कैसे करें, आदि I 90 के दशक में, जब ओएस उपयोगकर्ता को खुद से बचाने में सक्षम नहीं था।
sfdcfox

1
@ sfdcfox यदि आप मशीन कोड / कोडांतरक में कर रहे थे, तो यह अपरिभाषित व्यवहार नहीं था (यह अपरंपरागत व्यवहार हो सकता है)।
21

2
यदि आपके मन में एक विशिष्ट असेंबली है, तो इसका उपयोग करें और बिना सी लिखें नहीं लिखें। तब सभी को पता चल जाएगा कि आप एक विशिष्ट गैर-पोर्टेबल चाल का उपयोग कर रहे हैं। और यह बुरे लोग नहीं हैं, जिनका मतलब है कि आप यूबी का उपयोग नहीं कर सकते हैं, यह इंटेल आदि चिप पर अपनी चाल चल रहा है।
7

2
@ 500-इंटरनल सेवरर्रर क्योंकि वे आसानी से पता लगाने योग्य नहीं हो सकते हैं या सामान्य मामले में बिल्कुल भी पता लगाने योग्य नहीं हो सकते हैं और इसलिए उन्हें अस्वीकार करने का कोई तरीका नहीं होगा। जो अलग है तो व्याकरण के उल्लंघन का पता लगाया जा सकता है। हमारे पास दुर्भावनापूर्ण और बीमार रूप से गठित कोई निदान भी नहीं है, जो सामान्य रूप से खराब रूप से गठित कार्यक्रमों को अलग करता है जो कि सिद्धांत से उन लोगों का पता लगाया जा सकता है जिन्हें सिद्धांत रूप से नहीं पहचाना जा सकता है।
शैफिक याघमौर

164

नहीं, यह भयानक है।

एक असंवैधानिक चर का उपयोग करने का व्यवहार C और C ++ दोनों में अपरिभाषित है, और यह बहुत कम संभावना है कि ऐसी योजना में वांछनीय सांख्यिकीय गुण होंगे।

यदि आप एक "त्वरित और गंदे" यादृच्छिक संख्या जनरेटर चाहते हैं, तो rand()आपका सबसे अच्छा शर्त है। इसके कार्यान्वयन में, यह सब एक गुणा, एक जोड़ और एक मापांक है।

सबसे तेज़ जनरेटर जो मुझे पता है कि आपको uint32_tछद्म यादृच्छिक चर के प्रकार के रूप में उपयोग करने की आवश्यकता है I, और उपयोग करें

I = 1664525 * I + 1013904223

क्रमिक मूल्यों को उत्पन्न करने के लिए। आप किसी भी प्रारंभिक मूल्य I(जिसे बीज कहा जाता है ) का चयन कर सकते हैं जो आपके फैंस को पसंद आता है। जाहिर है आप इनलाइन को कोड कर सकते हैं। एक अहस्ताक्षरित प्रकार का मानक-गारंटीकृत रैपराउंड मापांक के रूप में कार्य करता है। (सांख्यिक स्थिरांक उस उल्लेखनीय वैज्ञानिक प्रोग्रामर डोनाल्ड नथ द्वारा हाथ से उठाए गए हैं।)


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

24
@ जल्दी और गंदे के लिए एक इकाई चर की तुलना में? यह काफी बेहतर उपाय है।
माइक मैकमोहन

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

1
रैंड () में एक और भयानक मुद्दा है: यह एक तरह के लॉक का उपयोग करता है, जिसे थ्रेड्स के अंदर कहा जाता है, यह आपके कोड को नाटकीय रूप से धीमा कर देता है। कम से कम, एक रीक्रेंट संस्करण है। और यदि आप C ++ 11 का उपयोग करते हैं, तो रैंडम एपीआई आपको वह सब कुछ प्रदान करता है, जिसकी आपको आवश्यकता है।
मारवान बुर्ल

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

42

अच्छा प्रश्न!

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

  1. हमेशा एक ही।
  2. मूल्यों के एक छोटे समूह में से एक बनें।
  3. एक या अधिक छोटी श्रेणियों में मान प्राप्त करें।
  4. 16/32 / 64-बिट सिस्टम पर संकेत से 2/4/8 द्वारा विभाजित कई मान देखें
  5. ...

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

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

यादृच्छिकता के बारे में पढ़ें । जैसा कि आप देखेंगे कि संपत्ति प्राप्त करने के लिए यादृच्छिकता बहुत विशिष्ट और कठिन है। यह सोचना एक सामान्य गलती है कि यदि आप बस कुछ ऐसा करना चाहते हैं जिसे ट्रैक करना मुश्किल है (जैसे कि आपके सुझाव) तो आपको एक यादृच्छिक मूल्य मिलेगा।


7
... और वह सभी संकलक-अनुकूलन छोड़ रहा है जो पूरी तरह से उस कोड को प्राप्त करेगा।
डेडुपिलेटर

6 ... आपको डिबग और रिलीज़ में अलग "यादृच्छिकता" मिलेगी। अपरिभाषित का मतलब है कि आप इसे गलत कर रहे हैं।
Sql सर्फर

सही। मैं संक्षिप्त या "अपरिभाषित"! = "मनमाना"! = "यादृच्छिक" के साथ संक्षेप करता हूँ। इन सभी प्रकार के "अज्ञातता" में अलग-अलग गुण हैं।
fche

वैश्विक चर की गारंटी एक परिभाषित मूल्य है, चाहे स्पष्ट रूप से प्रारंभिक हो या नहीं। यह निश्चित रूप से सी ++ और सी में भी सही है
ब्रायन वैंडेनबर्ग

32

कई अच्छे जवाब, लेकिन मुझे एक और जोड़ने और इस बिंदु पर जोर देने की अनुमति दें कि एक नियतात्मक कंप्यूटर में, कुछ भी यादृच्छिक नहीं है। यह एक छद्म- RNG द्वारा उत्पादित दोनों संख्याओं के लिए सही है और स्टैक पर C / C ++ स्थानीय चर के लिए आरक्षित स्मृति के क्षेत्रों में पाए जाने वाले "यादृच्छिक" संख्याएं हैं।

लेकिन ... एक महत्वपूर्ण अंतर है।

एक अच्छे छद्म आयामी जनरेटर द्वारा उत्पन्न संख्याओं में ऐसे गुण होते हैं जो उन्हें सांख्यिकीय रूप से वास्तव में यादृच्छिक ड्रॉ के समान बनाते हैं। उदाहरण के लिए, वितरण एक समान है। चक्र की लंबाई लंबी है: चक्र को दोहराने से पहले आप लाखों यादृच्छिक संख्या प्राप्त कर सकते हैं। अनुक्रम स्वतःसंबंधित नहीं है: उदाहरण के लिए, यदि आप हर 2, 3, या 27 वें नंबर को लेते हैं, या यदि आप उत्पन्न संख्याओं में विशिष्ट अंकों को देखते हैं, तो आपको अजीब पैटर्न उभरने लगते हैं।

इसके विपरीत, स्टैक पर पीछे छोड़ दिए गए "यादृच्छिक" संख्याओं में इनमें से कोई भी गुण नहीं है। उनके मूल्य और उनकी स्पष्ट यादृच्छिकता पूरी तरह से इस बात पर निर्भर करती है कि कार्यक्रम का निर्माण कैसे किया जाता है, इसे कैसे संकलित किया जाता है, और यह कंपाइलर द्वारा कैसे अनुकूलित किया जाता है। उदाहरण के रूप में, यहाँ एक स्व-निहित कार्यक्रम के रूप में आपके विचार की भिन्नता है:

#include <stdio.h>

notrandom()
{
        int r, g, b;

        printf("R=%d, G=%d, B=%d", r&255, g&255, b&255);
}

int main(int argc, char *argv[])
{
        int i;
        for (i = 0; i < 10; i++)
        {
                notrandom();
                printf("\n");
        }

        return 0;
}

जब मैं एक लिनक्स मशीन पर जीसीसी के साथ इस कोड को संकलित करता हूं और इसे चलाता हूं, तो यह अप्रिय रूप से नियतात्मक होता है:

R=0, G=19, B=0
R=130, G=16, B=255
R=130, G=16, B=255
R=130, G=16, B=255
R=130, G=16, B=255
R=130, G=16, B=255
R=130, G=16, B=255
R=130, G=16, B=255
R=130, G=16, B=255
R=130, G=16, B=255

यदि आप एक डिस्सैम्बलर के साथ संकलित कोड को देखते हैं, तो आप विस्तार से बता सकते हैं कि क्या चल रहा था। नोट्रिज़्म () के पहले कॉल में स्टैक के एक क्षेत्र का उपयोग किया गया था जो पहले इस कार्यक्रम द्वारा उपयोग नहीं किया गया था; कौन जानता है कि वहाँ क्या था। लेकिन उसके बाद नॉट्रैंडम () पर कॉल करने के लिए, प्रिंटफ () के लिए एक कॉल है (जो कि जीसीसी कंपाइलर वास्तव में पुचर (), लेकिन कभी भी मन नहीं करता है) को कॉल के लिए अनुकूलित करता है और स्टैक को ओवरराइट करता है। तो अगले और बाद के समय, जब नोट्रोनियम () कहा जाता है, स्टैक में पुचर () के निष्पादन से बासी डेटा होगा, और चूंकि पुचर () को हमेशा एक ही तर्कों के साथ कहा जाता है, यह बासी डेटा हमेशा समान रहेगा, भी।

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

वास्तव में, दूसरों के रूप में, मैं किसी ऐसे व्यक्ति पर गोलीबारी करने पर भी विचार करूंगा, जिसने इस विचार को "उच्च प्रदर्शन आरएनजी" के रूप में पारित करने की कोशिश की।


1
"एक नियतात्मक कंप्यूटर में, कुछ भी यादृच्छिक नहीं है" - यह वास्तव में सच नहीं है। आधुनिक कंप्यूटरों में सभी प्रकार के सेंसर होते हैं जो आपको अलग हार्डवेयर जनरेटर के बिना सही , अप्रत्याशित यादृच्छिकता उत्पन्न करने की अनुमति देते हैं । एक आधुनिक वास्तुकला पर, के मूल्यों/dev/random तरह के हार्डवेयर स्रोतों से अक्सर को वरीयता दी जाती है, और वास्तव में "क्वांटम शोर", यानी शब्द के सर्वश्रेष्ठ भौतिक अर्थ में वास्तव में अप्रत्याशित है।
कोनराड रुडोल्फ

2
लेकिन फिर, यह एक नियतात्मक कंप्यूटर नहीं है, क्या यह है? अब आप पर्यावरण इनपुट पर भरोसा कर रहे हैं। किसी भी मामले में, यह हमें पारंपरिक छद्म-आरएनजी बनाम "यादृच्छिक" बिट्स की एकतरफा स्मृति में चर्चा से परे ले जाता है। इसके अलावा ... / देव / यादृच्छिक के वर्णन को देखें कि सराहना करने के लिए उनके रास्ते से कितना दूर चले गए ताकि यह सुनिश्चित हो सके कि यादृच्छिक संख्याएं क्रिप्टोग्राफिक रूप से सुरक्षित हैं ... ठीक है क्योंकि इनपुट स्रोत शुद्ध नहीं हैं, असंबंधित क्वांटम शोर लेकिन बल्कि, संभावित रूप से अत्यधिक सहसंबद्ध सेंसर रीडिंग जिसमें केवल एक छोटी सी यादृच्छिकता है। यह बहुत धीमा है।
विक्टर टोथ

29

अपरिभाषित व्यवहार का मतलब है कि संकलक के लेखक समस्या की अनदेखी करने के लिए स्वतंत्र हैं क्योंकि प्रोग्रामर को कभी भी शिकायत करने का अधिकार नहीं होगा।

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

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

यकीन है कि आप यह उम्मीद नहीं कर सकते कि यह एक अच्छा यादृच्छिक जनरेटर है।


28

अपरिभाषित व्यवहार अपरिभाषित है। इसका मतलब यह नहीं है कि आपको एक अपरिभाषित मूल्य मिलता है, इसका मतलब है कि कार्यक्रम कुछ भी कर सकता है और अभी भी भाषा विनिर्देश को पूरा कर सकता है ।

एक अच्छा अनुकूलन कंपाइलर लेना चाहिए

void updateEffect(){
    for(int i=0;i<1000;i++){
        int r;
        int g;
        int b;
        star[i].setColor(r%255,g%255,b%255);
        bool isVisible;
        star[i].setVisible(isVisible);
    }
}

और इसे एक noop पर संकलित करें। यह निश्चित रूप से किसी भी विकल्प से तेज है। इसका नकारात्मक पक्ष यह है कि यह कुछ भी नहीं करेगा, लेकिन यह अपरिभाषित व्यवहार का नकारात्मक पहलू है।


3
बहुत कुछ इस बात पर निर्भर करता है कि क्या कम्पाइलर का उद्देश्य प्रोग्रामर को डोमेन की आवश्यकताओं को पूरा करने वाली निष्पादन योग्य फ़ाइलों का निर्माण करने में मदद करता है, या क्या उद्देश्य सबसे "कुशल" निष्पादन योग्य उत्पादन करना है जिसका व्यवहार C मानक की न्यूनतम आवश्यकताओं के अनुरूप होगा, बिना इस तरह का व्यवहार किसी भी उपयोगी उद्देश्य के लिए काम करेगा। पूर्व उद्देश्य के संबंध में, कोड का उपयोग r, g, b, या डीबगर जाल को ट्रिगर करने के लिए कुछ मनमाने ढंग से प्रारंभिक मानों का उपयोग करते हैं, यदि व्यावहारिक रूप से, कोड को एनओपी में बदलने की तुलना में अधिक उपयोगी होगा। बाद के उद्देश्य के संबंध में ...
सुपरकैट

2
... एक इष्टतम कंपाइलर को यह निर्धारित करना चाहिए कि इनपुट किस विधि को निष्पादित करने के लिए उपरोक्त विधि का कारण बनेंगे, और किसी भी कोड को समाप्त करेंगे जो केवल तभी प्रासंगिक होगा जब इस तरह के इनपुट प्राप्त होते हैं।
सुपरकाट

1
@supercat या इसका उद्देश्य C. मानक के अनुपालन में कुशल निष्पादन योग्य बनाने के लिए हो सकता है, जबकि प्रोग्रामर उन स्थानों को खोजने में मदद करता है जहाँ अनुपालन उपयोगी नहीं हो सकता है। कंपाइलर्स इस समझौते के उद्देश्य को जीसीएस जैसे मानक की तुलना में अधिक निदान का उत्सर्जन करके पूरा कर सकते हैं -Wall -Wextra
डेमियन यरिक

1
यह मान अपरिभाषित हैं कि इसका मतलब यह नहीं है कि आस-पास के कोड का व्यवहार अपरिभाषित है। किसी भी कंपाइलर को उस कार्य को नहीं करना चाहिए। दो फ़ंक्शन कॉल करते हैं, जो भी इनपुट दिए जाते हैं, उन्हें बिल्कुल कहा जाना चाहिए; पहले MUST को 0 और 255 के बीच तीन संख्याओं के साथ बुलाया जाना चाहिए, और दूसरे MUST को सही या गलत मान के साथ बुलाया जाना चाहिए। एक "अच्छा अनुकूलन करने वाला कंपाइलर" फंक्शन परमेस को मनमाने ढंग से स्थिर मानों के साथ ऑप्टिमाइज़ कर सकता है, चर से पूरी तरह से छुटकारा दिला सकता है, लेकिन जहां तक ​​यह जा सकता है (अच्छी तरह से, जब तक कि कुछ इनपुट पर फंक्शन को कम किया जा सकता है)।
डेवी मॉर्गन

@DewiMorgan - जैसा कि कहा जाता है कि फ़ंक्शन "इस पैरामीटर को सेट करें" प्रकार के हैं, वे लगभग निश्चित रूप से शोर को कम करते हैं जब इनपुट पैरामीटर के वर्तमान मूल्य के समान होता है, जिसे संकलक मानने के लिए स्वतंत्र है।
जूल्स

18

अभी तक उल्लेख नहीं किया गया है, लेकिन अपरिहार्य व्यवहार को लागू करने वाले कोड पथ को संकलक को जो भी करना है, जैसे करने की अनुमति है

void updateEffect(){}

जो निश्चित रूप से आपके सही लूप से तेज है, और यूबी के कारण, पूरी तरह से अनुरूप है।


18

सुरक्षा कारणों के कारण, प्रोग्राम को सौंपी गई नई मेमोरी को साफ करना पड़ता है, अन्यथा सूचना का उपयोग किया जा सकता है, और पासवर्ड एक एप्लिकेशन से दूसरे में लीक हो सकते हैं। केवल जब आप मेमोरी का पुन: उपयोग करते हैं, तो आपको 0. से भिन्न मान मिलते हैं और यह बहुत संभावना है, कि एक स्टैक पर पिछले मूल्य को ठीक किया जाता है, क्योंकि उस मेमोरी का पिछला उपयोग तय हो जाता है।


13

आपका विशेष कोड उदाहरण शायद वह नहीं करेगा जो आप उम्मीद कर रहे हैं। जबकि तकनीकी रूप से लूप का प्रत्येक पुनरावृत्ति r, g, और b मानों के लिए स्थानीय चर को फिर से बनाता है, व्यवहार में यह स्टैक पर सटीक समान मेमोरी स्पेस है। इसलिए यह प्रत्येक पुनरावृत्ति के साथ पुन: यादृच्छिक नहीं होगा, और आप 1000, प्रत्येक रंग के लिए समान 3 मान निर्दिष्ट करेंगे, भले ही r, g, और b कितने यादृच्छिक हों और व्यक्तिगत रूप से शुरू में।

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


12

जैसा कि यहां के अधिकांश लोगों ने अपरिभाषित व्यवहार का उल्लेख किया है। अनिर्धारित का अर्थ यह भी है कि आपको कुछ पूर्णांक मान मिल सकता है (सौभाग्य से) और इस मामले में यह तेज होगा (जैसा कि रैंड फ़ंक्शन कॉल नहीं किया गया है)। लेकिन व्यावहारिक रूप से इसका उपयोग न करें। मुझे यकीन है कि यह भयानक परिणाम होगा क्योंकि भाग्य हर समय आपके साथ नहीं है।


1
बहुत अच्छी बात! यह एक व्यावहारिक चाल हो सकती है, लेकिन वास्तव में एक जिसे भाग्य की आवश्यकता होती है।
अर्थ-मामलों

1
इसमें कोई भाग्य शामिल नहीं है। यदि कंपाइलर अपरिभाषित व्यवहार को दूर नहीं करता है, तो आपको मिलने वाले मान पूरी तरह से निर्धारक हो जाएंगे (= पूरी तरह से आपके प्रोग्राम, इसके इनपुट, इसके कंपाइलर, इसका उपयोग करने वाले पुस्तकालयों, इसके थ्रेड्स का समय यदि थ्रेड्स हैं) पर निर्भर करता है। समस्या यह है कि आप इन मूल्यों के बारे में तर्क नहीं कर सकते क्योंकि वे कार्यान्वयन विवरण पर निर्भर करते हैं।
विस्फ़ोटक - मोनिका

एक ऑपरेटिंग सिस्टम की अनुपस्थिति में एप्लिकेशन स्टैक से अलग एक इंटरप्ट-हैंडलिंग स्टैक के साथ, भाग्य अच्छी तरह से शामिल हो सकता है, क्योंकि इंटरप्ट अक्सर वर्तमान स्टैक सामग्री से परे मेमोरी की सामग्री को थोड़ा परेशान करेगा।
सुपरकैट

12

सच में ख़राब! बुरी आदत, बुरा परिणाम। विचार करें:

A_Function_that_use_a_lot_the_Stack();
updateEffect();

यदि फ़ंक्शन A_Function_that_use_a_lot_the_Stack()हमेशा एक ही इनिशियलाइज़ेशन करता है तो यह उस पर समान डेटा के साथ स्टैक को छोड़ देता है। वह डेटा जिसे हम कॉल करते हैं updateEffect(): हमेशा एक ही मूल्य!


11

मैंने एक बहुत ही सरल परीक्षण किया, और यह बिल्कुल भी यादृच्छिक नहीं था।

#include <stdio.h>

int main() {

    int a;
    printf("%d\n", a);
    return 0;
}

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


अच्छी बात। एक परिणाम दृढ़ता से इस बात पर निर्भर करता है कि यह "यादृच्छिक" नंबर जनरेटर कोड में कहां कहा जाता है। यह यादृच्छिक के बजाय अप्रत्याशित है।
21

10

आपको 'रैंडम' से जो मतलब है, उसकी परिभाषा आपके पास होनी चाहिए। एक समझदार परिभाषा में यह शामिल है कि आपके द्वारा प्राप्त मूल्यों का थोड़ा सहसंबंध होना चाहिए। आप इसे माप सकते हैं। यह एक नियंत्रित, प्रतिलिपि प्रस्तुत करने योग्य तरीके से प्राप्त करने के लिए भी मामूली नहीं है। तो अपरिभाषित व्यवहार निश्चित रूप से वह नहीं है जो आप खोज रहे हैं।


7

ऐसी कुछ स्थितियाँ हैं जिनमें अनइंस्टॉल की गई मेमोरी को सुरक्षित रूप से "अहस्ताक्षरित चार *" का उपयोग करके पढ़ा जा सकता है [जैसे एक बफर से लौटा malloc]। इस तरह की मेमोरी को खिड़की के बाहर संकलक फेंकने के कारण संकलक के बारे में चिंता किए बिना ऐसी मेमोरी पढ़ सकते हैं, और कई बार ऐसा भी हो सकता है कि कोड को किसी भी मेमोरी के लिए तैयार करने के लिए अधिक कुशल हो सकता है जिसमें यह सुनिश्चित करने की तुलना में शामिल हो सकता है कि अनधिकृत डेटा नहीं पढ़ा जाएगा ( इसका एक आम उदाहरण memcpyआंशिक रूप से आरंभिक बफर पर उपयोग करना होगा, न कि उन सभी तत्वों की विवेकपूर्ण नकल करने के बजाय जो अर्थपूर्ण डेटा को शामिल करते हैं)।

हालांकि, ऐसे मामलों में, किसी को हमेशा यह मानना ​​चाहिए कि यदि बाइट्स का कोई संयोजन विशेष रूप से अस्थिर होगा, तो इसे पढ़ने से हमेशा बाइट्स के उस पैटर्न का उत्पादन होगा (और यदि एक निश्चित पैटर्न उत्पादन में अस्थिर होगा, लेकिन विकास में नहीं, जैसे कि पैटर्न तब तक दिखाई नहीं देगा जब तक कोड उत्पादन में नहीं है)।

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


2
"यदि बाइट्स का कोई भी संयोजन विशेष रूप से विवादास्पद होगा, तो इसे पढ़ने से बाइट्स के उस पैटर्न का हमेशा पता चलेगा" - जब तक आप उस पैटर्न का सामना करने के लिए कोड नहीं बनाते हैं, तब तक यह अब और अधिक अस्थिर नहीं है और भविष्य में एक अलग पैटर्न पढ़ा जाएगा।
स्टीव जेसप

@SteveJessop: ठीक है। विकास बनाम उत्पादन के बारे में मेरी लाइन एक समान धारणा को व्यक्त करने के लिए थी। कोड को इस बात की परवाह नहीं करनी चाहिए कि "कुछ यादृच्छिकता अच्छी हो सकती है" की अस्पष्ट धारणा से परे एकतरफा स्मृति में क्या है। यदि कार्यक्रम व्यवहार एकतरफा स्मृति के एक टुकड़े की सामग्री से प्रभावित होता है, तो भविष्य में हासिल किए गए टुकड़ों की सामग्री इससे प्रभावित हो सकती है।
सुपरकाट

5

जैसा कि दूसरों ने कहा है, यह तेज़ होगा, लेकिन यादृच्छिक नहीं।

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

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

महत्वपूर्ण रूप से आपके उदाहरण फ़ंक्शन का उपयोग करने के लिए, ये मान जब भी आप उन्हें पढ़ते हैं, तो वे हर बार समान नहीं होंगे। तो आपको एक ही रंग और दृश्यता के लिए सभी 100 सितारे मिलेंगे।

इसके अलावा, कुछ भी नहीं कहता है कि कंपाइलर को इन वैल्यू को इनिशियलाइज़ नहीं करना चाहिए - इसलिए फ्यूचर कंपाइलर ऐसा कर सकता है।

सामान्य तौर पर: बुरा विचार, यह मत करो। (बहुत सारे "चतुर" कोड स्तर के अनुकूलन की तरह ...)


2
आप इस बारे में कुछ मजबूत भविष्यवाणियां कर रहे हैं कि क्या होगा हालांकि इसकी कोई गारंटी नहीं है कि यूबी के कारण इसकी गारंटी दी गई है। यह व्यवहार में भी सही नहीं है।
यूआरआर

3

जैसा कि दूसरों ने पहले ही उल्लेख किया है, यह अपरिभाषित व्यवहार ( यूबी ) है, लेकिन यह "काम" हो सकता है।

दूसरों द्वारा पहले से बताई गई समस्याओं को छोड़कर, मुझे एक अन्य समस्या (नुकसान) दिखाई देती है - यह C और C ++ के अलावा किसी भी भाषा में काम नहीं करेगी। मुझे पता है कि यह प्रश्न C ++ के बारे में है, लेकिन यदि आप कोड लिख सकते हैं जो कि अच्छा C ++ और Java कोड होगा और यह कोई समस्या नहीं है कि क्यों? हो सकता है कि किसी दिन किसी को इसे अन्य भाषा में पोर्ट करना होगा और "मैजिक ट्रिक्स" यूबी के कारण होने वाली बग्स की खोज करना होगा, निश्चित रूप से यह एक बुरा सपना होगा (विशेषकर अनुभवहीन सी / सी ++ डेवलपर के लिए)।

यहां एक और समान यूबी के बारे में सवाल है। बस अपने आप को इस यूबी के बारे में जाने बिना बग को खोजने की कोशिश कर रहे हैं। यदि आप C / C ++ में ऐसी अजीब चीजों के बारे में अधिक पढ़ना चाहते हैं, तो लिंक से प्रश्न के उत्तर पढ़ें और इस महान स्लाइड शो को देखें। यह समझने में मदद करेगा कि हुड के नीचे क्या है और यह कैसे काम कर रहा है; यह "जादू" से भरा एक और स्लाइड शो नहीं है। मुझे पूरा यकीन है कि अधिकांश अनुभवी C / c ++ प्रोग्रामर भी इससे बहुत कुछ सीख सकते हैं।


3

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

यह मेरी पिछली पोस्ट में उल्लेख किया गया था जिसमें ऑटो सुविधा का लाभ और उसी के लिए उपयोगी लिंक शामिल हैं।

https://stackoverflow.com/a/26170069/2724703

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

void updateEffect(){
    for(int i=0;i<1000;i++){
        auto r;
        auto g;
        auto b;
        star[i].setColor(r%255,g%255,b%255);
        auto isVisible;
        star[i].setVisible(isVisible);
    }
}

3

मुझे आपका सोचने का तरीका पसंद है। वास्तव में बॉक्स के बाहर। हालाँकि ट्रेडऑफ़ वास्तव में इसके लायक नहीं है। मेमोरी-रनटाइम ट्रेडऑफ़ एक ऐसी चीज़ है, जिसमें रनटाइम के लिए अपरिभाषित व्यवहार शामिल नहीं है

यह जानने के लिए कि आपको अपने व्यापार तर्क के रूप में इस तरह के "यादृच्छिक" का उपयोग कर रहे हैं, यह जानने के लिए आपको बहुत परेशान महसूस करना होगा। मैं ऐसा नहीं करता।


3

7757हर उस जगह का उपयोग करें, जहां पर आप अनैतिक तरीके से चर का उपयोग कर रहे हैं। मैंने इसे प्रमुख संख्याओं की सूची से बेतरतीब ढंग से उठाया:

  1. यह परिभाषित व्यवहार है

  2. यह हमेशा 0 नहीं होने की गारंटी है

  3. यह प्रमुख है

  4. यह सांख्यिकीय रूप से यादृच्छिक रूप से अनधिकृत चर के रूप में होने की संभावना है

  5. चूंकि इसकी कीमत संकलन समय पर जानी जाती है, इसलिए यह अनैतिक रूप से भिन्न चर की तुलना में तेज होने की संभावना है


तुलना के लिए, इस उत्तर में परिणाम देखें: stackoverflow.com/a/31836461/2963099
ग्लेन टीइटेलबौम

1

विचार करने की एक और संभावना है।

आधुनिक कंपाइलर (अहम जी ++) इतने बुद्धिमान होते हैं कि वे आपके कोड के माध्यम से यह देखने के लिए जाते हैं कि निर्देश राज्य को क्या प्रभावित करते हैं, और क्या नहीं, और यदि किसी निर्देश को राज्य को प्रभावित नहीं करने की गारंटी दी जाती है, तो जी ++ केवल उस निर्देश को हटा देगा।

तो यहाँ क्या होगा। g ++ निश्चित रूप से यह देखेगा कि आप पढ़ रहे हैं, अंकगणित कर रहे हैं, बचत कर रहे हैं, अनिवार्य रूप से कचरा मूल्य क्या है, जो अधिक कचरा पैदा करता है। चूंकि इस बात की कोई गारंटी नहीं है कि नया कचरा पुराने वाले की तुलना में अधिक उपयोगी है, यह बस आपके लूप को दूर करेगा। Bloop!

यह विधि उपयोगी है, लेकिन यहाँ मैं क्या करूँगा। UB (अपरिभाषित व्यवहार) को रैंड () गति के साथ मिलाएं।

बेशक, rand()निष्पादित किए गए को कम करें , लेकिन उन्हें संकलक में मिलाएं ऐसा कुछ भी नहीं करें जो आप इसे नहीं चाहते हैं।

और मैं तुम्हें आग नहीं दूंगा।


मुझे यह विश्वास करना बहुत मुश्किल है कि एक कंपाइलर तय कर सकता है कि आपका कोड मूर्खतापूर्ण कुछ कर रहा है और इसे हटा दें। मुझे उम्मीद है कि यह केवल अप्रयुक्त कोड को अनुकूलित करने के लिए होगा , न कि अनजाने कोड के लिए। क्या आपके पास एक प्रतिलिपि प्रस्तुत करने योग्य परीक्षण मामला है? किसी भी तरह से, यूबी की सिफारिश खतरनाक है। इसके अलावा, GCC केवल सक्षम कंपाइलर नहीं है, इसलिए इसे "आधुनिक" के रूप में एकल करना अनुचित है।
अंडरस्कोर_ड

-1

यादृच्छिकता के लिए अनइंस्टॉल किए गए डेटा का उपयोग करना आवश्यक नहीं है अगर ठीक से किया जाए। वास्तव में, OpenSSL अपने PRNG को बोने के लिए ठीक यही करता है।

जाहिरा तौर पर इस उपयोग को हालांकि अच्छी तरह से प्रलेखित नहीं किया गया था, क्योंकि किसी ने वैलगाइंड को अनइंस्टाल्यूटेड डेटा का उपयोग करने के बारे में शिकायत करते हुए देखा और इसे "ठीक" कर दिया, जिससे PRNG में एक बग पैदा हो गया

तो आप इसे कर सकते हैं, लेकिन आपको यह जानना होगा कि आप क्या कर रहे हैं और यह सुनिश्चित करें कि आपका कोड पढ़ने वाला कोई भी व्यक्ति इसे समझता है।


1
यह आपके कंपाइलर पर निर्भर करने वाला है जो कि अपरिभाषित व्यवहार के साथ अपेक्षित है, जैसा कि हम अपने उत्तर क्लैंग से देख सकते हैं आज वे नहीं करेंगे जो वे चाहते हैं।
शाफिक याघमोर

6
कि OpenSSL ने इस पद्धति का उपयोग एक एन्ट्रापी इनपुट के रूप में किया है, यह नहीं कहता कि यह कोई अच्छा था। आखिरकार, उनके द्वारा उपयोग किया जाने वाला एकमात्र अन्य एंट्रोपी स्रोत पीआईडी था । बिल्कुल अच्छा यादृच्छिक मूल्य नहीं। ऐसे बुरे एंट्रोपी स्रोत पर निर्भर रहने वाले व्यक्ति से, मैं उनके अन्य एंट्रोपी स्रोत पर अच्छे निर्णय की उम्मीद नहीं करूंगा। मैं सिर्फ आशा करता हूं, जो लोग वर्तमान में ओपनएसएसएल को बनाए रखते हैं वे उज्जवल हैं।
सेंटास्टर -
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.