$ RANDOM का उपयोग करने पर मुझे असमान रूप से फैलने वाले परिणाम क्यों मिल रहे हैं?


14

मैं विकिपीडिया$RANDOM पर RNGs के बारे में पढ़ता हूँ और TLDP पर कार्य करता हूँ लेकिन यह वास्तव में इस परिणाम की व्याख्या नहीं करता है:

$ max=$((6*3600))
$ for f in {1..100000}; do echo $(($RANDOM%max/3600)); done | sort | uniq -c
  21787 0
  22114 1
  21933 2
  12157 3
  10938 4
  11071 5

2x से अधिक मान 0, 1, 2 के 3, 4, 5 से अधिक क्यों हैं, लेकिन जब मैं अधिकतम मोडुलो को बदलता हूं तो वे लगभग 10 मानों में समान रूप से फैल जाते हैं?

$ max=$((9*3600))
$ for f in {1..100000}; do echo $(($RANDOM%max/3600)); done | sort | uniq -c
  11940 0
  11199 1
  10898 2
  10945 3
  11239 4
  10928 5
  10875 6
  10759 7
  11217 8

9
इसका सामान्य उत्तर यह है कि यदि आप RANDOM के लिए अधिकतम मूल्य और आपके मॉडुलो में समान रूप से विभाजित कर सकते हैं, तो reroll (आप प्राप्त किए गए नंबर को छोड़ दें) को छोड़ दें। यह सामान्य-से-रैंडम नहीं है, यह सभी भाषाओं / टूल / आदि के लिए सामान्य-से-उपयोग-मोडुलो-टू-प्रतिबंधित-आरएनजी-डोमेन है । उस प्रकार के आरएनजी लागू करना।
चार्ल्स डफी

7
इस पूर्वाग्रह के स्रोत पर मेरा २०१३ का लेख देखें यदि आप चाहते हैं कि यह कितना अच्छा हो तो कुछ अच्छे रेखांकन: ericlippert.com/2013/12/16/…
एरिक

1
"यादृच्छिक संख्या की पीढ़ी को मौका देने के लिए छोड़ा जाना बहुत महत्वपूर्ण है।" - रॉबर्ट कोवेउ। FYI हालांकि: अधिकांश कार्यक्रम सही मायने में यादृच्छिक संख्या उत्पन्न करने में असमर्थ हैं
jesse_b

@ एरिक लिपर्ट धन्यवाद, मैं इसे खुशी से पढ़ूंगा!
cprn

1
ध्यान दें कि, भले ही आप modulo पूर्वाग्रह के कारण समस्याएँ देख रहे हों, लेकिन $RANDOMवैरिएबल आंतरिक रूप से एक अच्छे PRNG का उपयोग नहीं करता है ।
वन

जवाबों:


36

मोडुलो पूर्वाग्रह के विषय पर विस्तार करने के लिए, आपका सूत्र है:

max=$((6*3600))
$(($RANDOM%max/3600))

और इस सूत्र में, $RANDOM0-32767 रेंज में एक यादृच्छिक मूल्य है।

   RANDOM Each time this parameter is referenced, a random integer between
          0 and 32767 is generated.

यह कल्पना करने में मदद करता है कि यह मानचित्र संभावित मानों के लिए कैसा है:

0 = 0-3599
1 = 3600-7199
2 = 7200-10799
3 = 10800-14399
4 = 14400-17999
5 = 18000-21599
0 = 21600-25199
1 = 25200-28799
2 = 28800-32399
3 = 32400-32767

तो आपके सूत्र में, 0, 1, 2 के लिए संभावना 4, 5 से दोगुनी है। और 3 की संभावना 4, 5 से थोड़ी अधिक है। इसलिए आपका परिणाम 0, 1, 2 विजेता के रूप में और 4, 5 हारने वाले के रूप में है।

जब 9*3600इसे बदलना है , तो यह निम्नानुसार है:

0 = 0-3599
1 = 3600-7199
2 = 7200-10799
3 = 10800-14399
4 = 14400-17999
5 = 18000-21599
6 = 21600-25199
7 = 25200-28799
8 = 28800-32399
0 = 32400-32767

1-8 में समान संभावना है, लेकिन 0 के लिए अभी भी थोड़ा पूर्वाग्रह है, और इसलिए 100'000 पुनरावृत्तियों के साथ आपके परीक्षण में 0 अभी भी विजेता था।

मोडुलो पूर्वाग्रह को ठीक करने के लिए, आपको पहले सूत्र को सरल करना चाहिए (यदि आप केवल 0-5 चाहते हैं तो मोडुलो 6 है, 3600 नहीं है या क्रैजियर संख्या नहीं है, इसका कोई मतलब नहीं है)। यह सरलीकरण अकेले आपके पूर्वाग्रह को बहुत कम कर देगा (32766 नक्शे 0, 32767 से 1 तक उन दो नंबरों को एक छोटा सा पूर्वाग्रह देना)।

पूर्वाग्रह से पूरी तरह से छुटकारा पाने के लिए, आपको फिर से रोल करने की आवश्यकता होती है, (उदाहरण के लिए) $RANDOMसे कम होने पर 32768 % 6(उन राज्यों को समाप्त करें जो पूरी तरह से उपलब्ध यादृच्छिक श्रेणी के लिए मैप नहीं करते हैं)।

max=6
for f in {1..100000}
do
    r=$RANDOM
    while [ $r -lt $((32768 % $max)) ]; do r=$RANDOM; done
    echo $(($r%max))
done | sort | uniq -c | sort -n

परीक्षा परिणाम:

  16425 5
  16515 1
  16720 0
  16769 2
  16776 4
  16795 3

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


आपका उत्तर काफी हद तक सही है, सिवाय इसके: "आपको फिर से रोल करने की आवश्यकता है जब $ RANDOM 32768% 6 से कम हो" वास्तव में "मंजिल के बराबर या उससे अधिक होना चाहिए ((RANDMAX + 1) / 6) * 6" (यानी 32766) ), और उसके नीचे संबंधित शेल कोड को ठीक करें।
नईयुकी

अगर आप एक विशिष्ट त्रुटि (जो दिए गए संदर्भ में लागू होते हैं) को इंगित कर सकते हैं, तो मुझे इसे सही करने में खुशी होगी। मेरा समाधान सिर्फ एक उदाहरण है, इसे करने के विभिन्न तरीके हैं। आप पूर्वाग्रह को स्टार्ट रेंज, या एंड रेंज, या कहीं बीच से हटा सकते हैं, इससे कोई फर्क नहीं पड़ता। आप इसे बेहतर तरीके से गणना कर सकते हैं (और हर पुनरावृत्ति में एक modulo नहीं)। आप विशेष मामलों को संभाल सकते हैं जैसे कि मनमानी मोडुल और रैंडमैक्स मान, यह भी संभालें RANDMAX = INTMAX जहां RANDMAX + 1 मौजूद नहीं है, लेकिन वह यहां ध्यान केंद्रित नहीं था।
फ्रॉस्टचुट्ज़ जूल

आपका उत्तर आपके पोस्ट से काफी खराब है। सबसे पहले, मैंने विशेष रूप से बताया कि आपका कौन सा वाक्यांश तथ्यात्मक रूप से गलत है। ध्यान दें कि "32768% 6" == 2, इसलिए आप हर बार $ RANDOM <2 को फिर से भरना चाहते हैं? रेंज के शुरू / अंत / midde पर पूर्वाग्रह के बारे में, आपकी पूरी पोस्ट सीमा के अंत में पूर्वाग्रह को हटाने के बारे में है, और मेरी प्रतिक्रिया वास्तव में भी पूरी करती है। तीसरा, आप RANDMAX = INTMAX को संभालने के बारे में बात करते हैं, लेकिन आपने अपने उत्तर में कई बार 32768 (= 32767 + 1) मूल्य का उल्लेख किया है, जिसका अर्थ है कि आप RANDMAX + 1 की गणना करने में सहज हैं।
नायुकी

1
@Nayuki मेरा कोड 0 और 1 को हटाता है, आपका 32766 और 32767 निकालता है और मैं आपको विस्तृत करना चाहूंगा: इससे क्या फर्क पड़ता है? मैं केवल मानव हूं, मैं गलतियां करता हूं, लेकिन आपने अभी तक कहा है कि "यह गलत है" बिना समझाए या दिखाए क्यों। धन्यवाद।
१५:०५ पर फ्रॉस्ट्सटुट जूल

1
कोई बात नहीं, यह पता लगा। झूठे अलार्म के बारे में क्षमा करें।
नियूकी

23

यह मोडुलो पूर्वाग्रह है। यदि RANDOMअच्छी तरह से निर्मित है, तो 0 और 32767 के बीच प्रत्येक मूल्य समान संभावना के साथ निर्मित होता है। जब आप modulo का उपयोग करते हैं, तो आप संभावनाओं को बदलते हैं: modulo के ऊपर के सभी मानों की प्रायिकता उन मानों में जोड़ दी जाती है जिनसे वे मैप करते हैं।

आपके उदाहरण में, 6 × 3600 मूल्यों की सीमा का लगभग दो तिहाई है। शीर्ष तीसरे की संभावनाओं को इसलिए नीचे के तीसरे से जोड़ा जाता है, जिसका अर्थ है कि 0 से 2 (लगभग) का मान 3 से 5 तक होने की संभावना है। 3 से 5. 9 × 3600 के मान लगभग 32767 हैं, इसलिए मोडुलो पूर्वाग्रह बहुत छोटा है और केवल 32400 से 32767 तक मूल्यों को प्रभावित करता है।

अपने मुख्य प्रश्न का उत्तर देने के लिए, यदि आप बीज जानते हैं तो कम से कम बैश में यादृच्छिक अनुक्रम पूरी तरह से अनुमानित है। देखें intrand32में variables.c

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