C ++ रैंड () परिमाण के एक ही क्रम की केवल संख्या क्यों उत्पन्न करता है?


146

C / C ++ में लिखे गए एक छोटे से आवेदन में, मैं randफ़ंक्शन और शायद बीज के साथ एक समस्या का सामना कर रहा हूं :

मैं यादृच्छिक संख्याओं के अनुक्रम का उत्पादन करना चाहता हूं जो अलग-अलग आदेशों के हैं, अर्थात अलग-अलग लॉगरिदम मान (बेस 2) के साथ। लेकिन ऐसा लगता है कि उत्पादित सभी संख्याएं एक ही क्रम की हैं, केवल 2 ^ 25 और 2 ^ 30 के बीच उतार-चढ़ाव।

क्या यह इसलिए rand()है क्योंकि यूनिक्स समय के साथ वरीयता प्राप्त है जो अब तक अपेक्षाकृत बड़ी संख्या है? मैं क्या भूल रहा हूँ? मैं rand()शुरुआत में केवल एक बार बीजारोपण कर रहा हूं main()


7
FWIW तो, यह C या C ++ है? यदि C / C ++ से आपका मतलब है कि आप वास्तव में C ++ का उपयोग कर सकते हैं, और C का उल्लेख केवल यादृच्छिक था, तो शायद यह en.cppreference.com/w/cpp/numeric/random/binomial_distribution मदद कर सकता है।
आर। मार्टिनो फर्नांडिस

9
दुर्भाग्य से आप गलत घोड़े पर दांव लगा रहे थे। बीज आपकी समस्या नहीं होनी चाहिए। आपकी समस्या गलत अपेक्षित वितरण थी। चूंकि निष्पक्ष प्रोग्रामर rand()समान रूप से वितरित संख्या (उच्च Google रैंकिंग के साथ प्रलेखन स्पष्ट रूप से ऐसा कहता है) लौटने की उम्मीद करेगा, मुझे नहीं लगता कि यह प्रश्न भविष्य के पाठकों के लिए उपयोगी है। इसीलिए वोट डाउन करें लेकिन इसे एसओ के इस्तेमाल से हतोत्साहित न करें।
सम्राट ओरियोनी

12
@ doug65536 "... जहां कोई संख्या कभी दोहराई नहीं जाती है" - यह यादृच्छिक नहीं है! मैं अपनी सेवानिवृत्ति को फंड्स टेबल पर रख सकता था यदि मेरी रैंड () पासा कभी भी एक ही संख्या में दो बार वापस नहीं आती, जब तक कि हर संभव संख्या वापस नहीं हो जाती।
क्रिस ग्रीग

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

12
Doug65536, कोई भी झगड़े नहीं उठा रहा है। वे सिर्फ सही ढंग से कह रहे हैं कि आप गलत हैं। यदि मैं 1 और 10: 2 4 7 2 8 1 5 9 7 3 के बीच एक RAND चाहता था तो PRNG बहुत खुशी से निम्नलिखित मंथन कर सकता है, जो कि कई 2s और 7s के बावजूद पूरी तरह से मान्य होगा। मुझे लगता है कि आप अपने iPhone पर फेरबदल की सुविधा के साथ PRNG को भ्रमित कर रहे हैं।
साइप्रस में आराम

जवाबों:


479

1 और 2 30 के बीच केवल 3% संख्याएं हैं जो 2 25 और 2 30 के बीच नहीं हैं । तो, यह बहुत सामान्य लगता है :)

क्योंकि 2 25 /2 30 = 2 -5 = 1/32 = ०.०३१२५ = 3.125%


36
ऐ, अच्छी बात है! त्वरित उत्तर के लिए 2 से 25 और 2 ^ 30 के बीच की तुलना में 31 गुणा अधिक संख्याएं हैं। त्वरित उत्तर के लिए धन्यवाद। मुझे तब कार्यक्रम पर पुनर्विचार करने की आवश्यकता है। प्रश्न उत्तर दिया।
टालरॉन मैथियास

1
@TallaronMathias बिटशिफ्टिंग के माध्यम से संख्या को कम करने पर विचार करें >>- यह आपको छोटी संख्या देगा। (या एक मापांक के साथ ले रहे हैं %।)
सीन एलेड

13
मैं सबसे अधिक प्रोग्रामर से यह स्पष्ट होने की उम्मीद करूंगा: 2 ^ 25 से कम किसी भी अहस्ताक्षरित पूर्णांक में इसके पहले 7 बिट्स के बराबर होना चाहिए 0- और यदि प्रत्येक बिट यादृच्छिक है ...
BlueRaja - Danny Pflughoeft

118
@ BlueRaja-DannyPflughoeft - यदि संभावनाएं स्पष्ट थीं, तो कैसीनो व्यवसाय से बाहर हो जाएगा।
ब्रेट हेल

26
@BrettHale - मुझे नहीं लगता कि प्रोग्रामर एक कैसीनो के लक्ष्य जनसांख्यिकीय हैं।
एकोस्तिकमार्टिन

272

हल्का हरा 0 और 2 25 के बीच का क्षेत्र है ; गहरा हरा 2 25 और 2 30 के बीच का क्षेत्र है । टिक्स 2 की शक्तियां हैं।

वितरण


42

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

यदि आप हमें वितरण बताते हैं, तो हम आपको वह quantileकार्य बता सकते हैं, जिसकी आपको आवश्यकता है।


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

18

यदि आप परिमाण के विभिन्न आदेश चाहते हैं, तो बस कोशिश क्यों नहीं करते pow(2, rand())? या शायद रैंड () के रूप में सीधे ऑर्डर चुनें, जैसा कि हेरोल्ड ने सुझाव दिया था?


3
अच्छा विचार है, लेकिन आपको ^ (जो कि तार्किक xor ऑपरेटर है, शक्ति नहीं है, C भाषा में) के बजाय pow का उपयोग करके अपने उत्तर को ठीक करना चाहिए।
क्रि।

6
चूंकि rand()आप ऊपर जा सकते हैं RAND_MAX, आपको वास्तव में अपने यादृच्छिक संख्या को स्केल करने की आवश्यकता है ताकि परिणाम अतिप्रवाह न हो ...
फ्लोरिस

@ फ़्लोरिस: लेकिन यदि आप एक बहुत बड़ी रेंज पर एक छोटी गणना योग्य सीमा को मापते हैं, तो आपके पास बहुत सारे छेद होंगे, जो कि ओपी की उम्मीद नहीं है।
एंड्रे कारन

13

@ C4stor ने शानदार प्रदर्शन किया। लेकिन, एक अधिक सामान्य मामले के लिए और मानव के लिए समझने में आसान (आधार 10): 1 से 10 ^ n तक की सीमा के लिए, ~ 90% संख्या 10 ^ (n-1) से 10 ^ n तक है, इसलिए, ~ 99% संख्या 10 ^ (n-2) से 10 ^ n तक जाती है। आप जितने चाहें उतने डेसीमल जोड़ते रहें।

मजेदार गणित, यदि आप n के लिए ऐसा कर रहे हैं, तो आप देख सकते हैं कि 1 से 10 ^ n, 99.9999 ...% = 100% संख्याएं 10 ^ 0 से 10 ^ n तक इस पद्धति के साथ हैं।

अब कोड के बारे में, यदि आप 0 से 10 ^ n तक के परिमाण के यादृच्छिक क्रम के साथ एक यादृच्छिक संख्या चाहते हैं, तो आप ऐसा कर सकते हैं:

  1. 0 से n तक एक छोटी यादृच्छिक संख्या उत्पन्न करें

  2. यदि आप जानते हैं कि n की सीमा है, तो ऑर्डर की एक बड़ी यादृच्छिक संख्या 10 ^ k उत्पन्न करें जहां k> अधिकतम {n}।

  3. इस बड़े यादृच्छिक संख्या के n अंक प्राप्त करने के लिए लंबी यादृच्छिक संख्या को काटें।


46
आप पूरी तरह से सही हैं, लेकिन वास्तव में उत्तर को समझने में आसान के लिए, ओपी को खुद से पूछना चाहिए कि 1 और 100 के बीच 90% यादृच्छिक संख्याएं दो अंक क्यों हैं।
मोनिका

13

मूल (और सही) उत्तर पहले से ही दिया गया था और ऊपर स्वीकार किया गया था: 0 और 9 के बीच 10 नंबर हैं, 10 और 99 के बीच 90 नंबर हैं, 100 और 999 के बीच 900 हैं, आदि।

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

s = rand() & 31; // a random number between 0 and 31 inclusive, assuming RAND_MAX = 2^32-1
r = rand() >> s; // right shift

यह सही नहीं है, लेकिन यह कंप्यूटिंग की तुलना में बहुत तेज है pow(2, rand()*scalefactor)। यह इस अर्थ में "ढेलेदार" होगा कि वितरण एक कारक 2 के भीतर संख्या के लिए समान होगा (128 से 255 के लिए एक समान, 256 से 1023 के लिए आधा घनत्व, आदि)।

यहां संख्या 0 से 31 (1M नमूनों में) की आवृत्ति का एक हिस्टोग्राम है:

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


नाइटपिक: इससे बहुत कम संख्या को प्रोत्साहित किया जा सकता है जो एक से अधिक की उम्मीद कर सकता है। शून्य प्राप्त करने की संभावना एक 10. की तुलना में काफी अधिक है
मिंग डक

ठीक है - इसका पूरा बिंदु छोटी संख्या को प्रोत्साहित करना है, इसलिए मुझे खुशी है कि यह काम कर रहा है! मैंने एक मोंटे कार्लो सिमुलेशन चलाया, और यह मुझे संख्या में दोगुना होने की संभावना में एक कारक 2 ड्रॉप दे रहा है - एक लॉग वितरण के विपरीत नहीं। चित्र के साथ अपडेट किया गया उत्तर।
फ्लोरिस

नहीं, मेरा मतलब है, rand()>>(rand()&31);एक व्यक्ति सहज रूप से 32 बिट्स के लिए 1/32 वें नंबर की उम्मीद करता है, और 1/32 वीं संख्याओं के लिए 31 बिट्स के लिए, और 1/32 वीं संख्याओं में 30 बिट्स होने के लिए, आदि लेकिन वह है। आपके द्वारा प्राप्त किए जा रहे परिणाम नहीं , केवल 1/64 नंबरों के बारे में 32 बिट्स का परिणाम होगा, जबकि लगभग आधा होना चाहिए। 0. चूंकि मेरे मानसिक गणित आपके माप से असहमत हैं, इसलिए मुझे यह पता लगाने के लिए अपने स्वयं के माप करने होंगे यह बाहर है।
मूविंग डक

2
मेरे कहने का मतलब यह नहीं है कि आपका कोड गलत है। यह शायद मैं क्या करूँगा। यह सिर्फ एक चेतावनी के योग्य है कि परिणाम काफी वितरित नहीं हैं क्योंकि कोई उम्मीद कर सकता है।
मूविंग डक

1
मुझे लगता है कि समस्या 0 बिट 1 नंबर के रूप में सोचने से आती है ... जब आप पूर्णांकों और लॉगरिथम को मिलाते हैं, तो आप इस तरह के कोन्ड्रूम में भाग लेते हैं। हालांकि यह एक अच्छा अभ्यास रहा है और आपने मुझे कुछ सोचने के लिए दिया। "अपने एल्गोरिथ्म की सीमाओं का परीक्षण करें" - यह कभी भी पुराना नहीं होता है।
फ्लोरिस

5

0 और 2 ^ 29 और 2 ^ 29 और 2 ^ 30 के बीच की संख्या के बराबर संख्या हैं।

समस्या को देखने का एक अन्य तरीका: आपके द्वारा उत्पन्न यादृच्छिक संख्या के द्विआधारी प्रतिनिधित्व पर विचार करें, संभावना है कि उच्चतम बिट 1 बराबर 1/2 है, और इसलिए, आपको आधे मामलों में ऑर्डर 29 मिलता है। आप जो चाहते हैं वह ऐसी संख्या को देखना है जो 2 ^ 25 से नीचे होगी, लेकिन इसका मतलब है कि 5 उच्चतम बिट्स सभी शून्य हैं, जो 1/32 की कम संभावना के साथ होता है। संभावना है कि अगर आप इसे लंबे समय तक चलाते हैं, तो आप कभी भी 15 से नीचे के आदेश को नहीं देख पाएंगे (संभावना कुछ इस तरह से है कि 6 से 6 बार रोल कर सकते हैं)।

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



2

यदि आप एक ऑनलाइन सेवा से यादृच्छिक संख्याओं का उपयोग करना चाहते हैं, तो आप इसके लिए wget का उपयोग कर सकते हैं, आप यह देखना चाहते हैं कि आप यादृच्छिक संख्या जैसी सेवाओं का उपयोग अपनी यादृच्छिक संख्या पीढ़ी के लिए भी कर सकते हैं, आप उन्हें wget का उपयोग करके पकड़ सकते हैं और फिर से संख्याओं को पढ़ सकते हैं। डाउनलोड की गई फ़ाइल

wget -q https://www.random.org/integers/?num=100&min=1&max=100&col=5&base=10&format=html&rnd=new -O new.txt

http://programmingconsole.blogspot.in/2013/11/a-better-and-different-way-to-generate.html


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