रैंड () का उपयोग करते समय मुझे यह विशेष रंग पैटर्न क्यों मिलता है?


170

मैंने इस तरह एक छवि फ़ाइल बनाने की कोशिश की:

uint8_t raw_r[pixel_width][pixel_height];
uint8_t raw_g[pixel_width][pixel_height];
uint8_t raw_b[pixel_width][pixel_height];
uint8_t blue(uint32_t x, uint32_t y)
{
    return (rand()%2)? (x+y)%rand() : ((x*y%1024)%rand())%2 ? (x-y)%rand() : rand();
}
uint8_t green(uint32_t x, uint32_t y)
{
    return (rand()%2)? (x-y)%rand() : ((x*y%1024)%rand())%2 ? (x+y)%rand() : rand();
}
uint8_t red(uint32_t x, uint32_t y)
{
    return (rand()%2)? (y-x)%rand() : ((x*y%1024)%rand())%2 ? (x+y)%rand() : rand();
}

for (y=0; y<pixel_height; ++y)
{
    for (x=0; x<pixel_width; ++x)
    {
        raw_b[x][y]=blue(x, y);
        raw_g[x][y]=green(x, y);
        raw_r[x][y]=red(x, y);
    }
}

मुझे कुछ यादृच्छिक (सफेद शोर) मिलने की उम्मीद थी। हालांकि, आउटपुट दिलचस्प है:

क्या आप इसका कारण जानते हैं?


संपादित करें

अब, यह स्पष्ट है कि इसका कोई लेना-देना नहीं है rand()

इस कोड को भी आज़माएं:

for (x=0; x<pixel_width; ++x)
    for (y=0; y<pixel_height; ++y)
    {
        r[x][y] = (x+y);
        g[x][y] = (y-x);
        /* b[x][y] = rand()%2? x : y; */
    }


26
cos rand isnt rand - इसका अच्छा प्रदर्शन। यह 100% नियतात्मक है
pm100


50
@ pm100: जैसा कि bames53 का जवाब इतनी अच्छी तरह से समझाता है, अगर आप एक सही यादृच्छिक संख्या जनरेटर का उपयोग करते हैं तो भी आपको वही पैटर्न मिलेगा।
टोनीके

13
एक प्रश्न क्षमा करें: चूंकि आप पिक्सेल मानों की गणना करने के लिए x और y निर्देशांक का उपयोग कर रहे हैं, आप उन मूल्यों के समन्वय से स्वतंत्र होने की उम्मीद क्यों करेंगे? यदि छवि बहुत समान रूप से यादृच्छिक दिखती है, तो आपको वही चाहिए, जो सही है?
थॉमस पैड्रॉन-मैक्कार्थी

15
सबक सीखा: यादृच्छिक संख्याओं के साथ यादृच्छिक चीजें करना यादृच्छिक परिणाम उत्पन्न नहीं करता है :)
हेगन वॉन ईटजन

जवाबों:


355

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

TL; DR: आपके द्वारा देखा जाने वाला पैटर्न अंतर्निहित रैंडम नंबर जनरेटर से कोई लेना-देना नहीं है और इसके बजाय बस इस तरह से है कि आपका प्रोग्राम संख्याओं में हेरफेर कर रहा है।

मैं आपके नीले फंक्शन से चिपके रहूँगा क्योंकि वे सभी समान हैं।

uint8_t blue(uint32_t x, uint32_t y) {
    return (rand() % 2)                  ? (x + y) % rand() :
           ((x * y % 1024) % rand()) % 2 ? (x - y) % rand() :
                                           rand();
}

प्रत्येक पिक्सेल मूल्य तीन कार्यों में से एक से चयन किया जाता है: (x + y) % rand(), (x - y) % rand(), और rand();

आइए, इनमें से प्रत्येक द्वारा निर्मित छवियों को देखें।

  • rand()

यह वही है जो आप उम्मीद करेंगे, बस शोर। इस "छवि सी" को कॉल करें

यहां छवि विवरण दर्ज करें


  • (x + y) % rand()

यहां आप एक साथ पिक्सेल निर्देशांक जोड़ रहे हैं और एक यादृच्छिक संख्या से विभाजित करके शेष ले रहे हैं। यदि छवि 1024x1024 है, तो योग सीमा [0-2046] में है। आप जिस यादृच्छिक संख्या से डाइविंग कर रहे हैं वह [0, RAND_MAX] श्रेणी में है, जहाँ RAND_MAX कम से कम 32k है और कुछ प्रणालियों पर 2 बिलियन है। दूसरे शब्दों में, 16 में से 1 में सबसे अच्छा मौका है जो शेष नहीं है (x + y)। इसलिए अधिकांश भाग के लिए यह फ़ंक्शन सिर्फ + x + y दिशा की ओर नीले रंग की वृद्धि का एक ग्रेडिएंट पैदा करेगा।

हालाँकि, आप केवल सबसे कम 8 बिट्स का उपयोग कर रहे हैं, क्योंकि आप ए वापस करते हैं uint8_t, इसलिए आपके पास 256 पिक्सेल चौड़े ग्रेडिएंट्स की धारियाँ होंगी।

इस "छवि A" को कॉल करें

यहां छवि विवरण दर्ज करें


  • (x - y) % rand()

यहां आप कुछ ऐसा ही करते हैं, लेकिन घटाव के साथ। जब तक x y से अधिक है, तो आपके पास पिछली छवि के समान कुछ होगा। लेकिन जहां y अधिक है, परिणाम बहुत बड़ी संख्या है क्योंकि xऔर yअहस्ताक्षरित हैं (नकारात्मक परिणाम अहस्ताक्षरित प्रकार की सीमा के शीर्ष के चारों ओर लपेटते हैं), और फिर % rand()kicks में और आप वास्तव में शोर करते हैं।

इस "छवि बी" को कॉल करें

यहां छवि विवरण दर्ज करें

आपकी अंतिम छवि में प्रत्येक पिक्सेल इन तीन छवियों में से एक फ़ंक्शन से लिया गया है rand() % 2और ((x * y % 1024) % rand()) % 2। इनमें से पहले को 50% प्रायिकता (मुद्दों के साथ rand()और इसके निम्न क्रम बिट्स की अनदेखी) के साथ पढ़ा जा सकता है ।

यहां एक क्लोजअप है जहां rand() % 2सच है (सफेद पिक्सेल) इसलिए छवि ए का चयन किया गया है।

यहां छवि विवरण दर्ज करें

दूसरे फ़ंक्शन में एक ((x * y % 1024) % rand()) % 2बार फिर यह मुद्दा है कि rand()आमतौर पर आप जिस चीज़ को विभाजित कर रहे हैं, उससे अधिक है (x * y % 1024), जो कि 1023 पर है। तब (x*y%1024)%20 और 1 समान रूप से उत्पन्न नहीं होता है। किसी भी विषम संख्या को किसी सम संख्या से गुणा किया जाता है। किसी भी संख्या को किसी सम संख्या से गुणा करने पर भी सम संख्या होती है। केवल एक विषम संख्या से गुणा एक विषम संख्या विषम है, और इसलिए %2उन मूल्यों पर भी जो उस समय के तीन चौथाई हैं, समय के 0 तीन चौथाई का उत्पादन करेंगे।

यहाँ एक क्लोज़अप है जहाँ ((x * y % 1024) % rand()) % 2सच है ताकि Image B को चुना जा सके। यह ठीक वही है जहाँ दोनों निर्देशांक विषम हैं।

यहां छवि विवरण दर्ज करें

और यहाँ जहाँ छवि C का चयन किया जा सकता है:

यहां छवि विवरण दर्ज करें

अंत में यहाँ की स्थितियों को मिलाकर जहाँ चित्र B को चुना गया है:

यहां छवि विवरण दर्ज करें

और जहां छवि C का चयन किया गया है:

यहां छवि विवरण दर्ज करें

परिणामी संयोजन को इस प्रकार पढ़ा जा सकता है:

50% संभावना के साथ छवि ए से पिक्सेल का उपयोग करें। बाकी समय छवि बी और छवि सी, बी के बीच चुनें जहां दोनों निर्देशांक विषम हैं, सी जहां या तो एक भी है।

अंत में, चूंकि आप तीन अलग-अलग रंगों के लिए एक ही कर रहे हैं, लेकिन विभिन्न झुकावों के साथ पैटर्न प्रत्येक रंग में अलग-अलग उन्मुख होते हैं और आपके द्वारा देखे जा रहे क्रॉसिंग स्ट्रिप्स या ग्रिड पैटर्न का उत्पादन करते हैं।


45

आपके द्वारा अपने कोड में की जा रही गणनाओं में से कई वास्तव में यादृच्छिक मूल्यों को जन्म नहीं देंगी। वे तीखी रेखाएँ जो आप देख रहे हैं, उन स्थानों के अनुरूप हैं जहाँ आपके x और y के सापेक्ष मूल्य एक दूसरे के साथ व्यापार का समन्वय करते हैं, और जब ऐसा होता है तो आप मौलिक रूप से भिन्न सूत्रों का उपयोग कर रहे होते हैं। उदाहरण के लिए, कंप्यूटिंग (x + y) % rand()आम तौर पर आपको मूल्य वापस दे देगी x + y, क्योंकि rand()(आमतौर पर) एक संख्या को बहुत अधिक लौटाया जाएगा, जो x + yदिए गए की तुलना में बहुत बड़ा है जो RAND_MAXआमतौर पर एक काफी महत्वपूर्ण संख्या है। इस अर्थ में, आपको सफेद शोर वापस करने की उम्मीद नहीं करनी चाहिए, क्योंकि एल्गोरिथ्म आप चीजों को उत्पन्न करने के लिए उपयोग कर रहे हैं सफेद शोर पैदा करने से दूर पक्षपाती है। यदि आप सफेद शोर चाहते हैं, तो बस प्रत्येक पिक्सेल को सेट करेंrand()। यदि आप अपने ऊपर एक अच्छा पैटर्न पसंद करते हैं, लेकिन थोड़ी सी बेतरतीबी के साथ इधर-उधर फेंक दिया जाता है, तो उस कोड का उपयोग करते रहें जो आपने लिखा है।

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

छवि

आप आर, जी, और बी निर्देशांक के साथ एक्स, वाई, और z निर्देशांक की जगह है, तो यह दिखता उल्लेखनीय उत्पादन के लिए इसी तरह अपने कार्यक्रम द्वारा बनाई जा रही। मुझे संदेह है कि यह शायद यहाँ मुख्य मुद्दा नहीं है, क्योंकि ऊपर उल्लिखित अन्य पहलू शायद अधिक स्पष्ट होगा।

यदि आप उच्च-गुणवत्ता वाले यादृच्छिक संख्याओं की तलाश कर रहे हैं, तो आपको उच्च-गुणवत्ता वाले यादृच्छिक स्रोत का उपयोग करना होगा। सी में, आप /dev/urandom/(लिनक्स जैसी प्रणाली पर) से बाइट्स पढ़ने पर विचार कर सकते हैं , जो काफी समान रूप से यादृच्छिक मान देता है। C ++ के पास अब अपने मानक पुस्तकालयों में कई अच्छी यादृच्छिक-संख्या वाली पीढ़ी के प्राइमिटिव हैं, अगर यह आपके लिए उपलब्ध है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.