वास्तव में n सेट बिट्स के साथ संख्या उत्पन्न करने के लिए PRNG


12

मैं वर्तमान में बाइनरी डेटा उत्पन्न करने के लिए कुछ कोड लिख रहा हूं। मुझे विशेष रूप से सेट बिट्स की संख्या के साथ 64-बिट संख्या उत्पन्न करने की आवश्यकता है; अधिक सटीक रूप से, प्रक्रिया को कुछ लेना चाहिए और एक छद्म यादृच्छिक 64-बिट संख्या को वापस बिट्स सेट करना चाहिए , और शेष 0 पर सेट करना चाहिए।0<n<64n1

मेरे वर्तमान दृष्टिकोण में कुछ इस तरह शामिल हैं:

  1. एक छद्म आयामी 64-बिट संख्या उत्पन्न करें ।k
  2. में बिट्स गणना , में परिणाम भंडारण ।kb
  3. यदि , आउटपुट ; अन्यथा 1 पर जाएं।b=nk

यह काम करता है, लेकिन यह असंगत लगता है। क्या पीआरएनजी एल्गोरिथ्म के कुछ प्रकार हैं जो सेट बिट्स के साथ संख्याओं को इससे अधिक सुरुचिपूर्ण ढंग से उत्पन्न कर सकते हैं ?n

जवाबों:


12

आपको जो चाहिए वह 0 और बीच एक यादृच्छिक संख्या है । समस्या तो यह है कि इसे थोड़ा पैटर्न में बदलना है।(64n)1

इसे एन्यूमेरेटिव कोडिंग के रूप में जाना जाता है, और यह सबसे पुराने तैनात कम्प्रेशन एल्गोरिदम में से एक है। संभवतः सबसे सरल एल्गोरिथ्म थॉमस कवर से है। यह सरल अवलोकन पर आधारित है कि यदि आपके पास एक ऐसा शब्द है जो बिट्स लंबा है, जहां सेट बिट्स सबसे महत्वपूर्ण बिट क्रम में हैं, तो इस शब्द की स्थिति इस शब्द के साथ सभी शब्दों के लेक्सिकोग्राफ़िक क्रम में है है:nxkx1

1ik(xii)

इसलिए, उदाहरण के लिए, 7-बिट शब्द के लिए:

i(0000111)=(23)+(12)+(01)=0
i(0001011)=(33)+(12)+(01)=1
i(0001101)=(33)+(22)+(01)=2

...और इसी तरह।

ऑर्डिनल से बिट पैटर्न प्राप्त करने के लिए, आप बदले में प्रत्येक बिट को डीकोड करते हैं। सी-लाइक भाषा में कुछ इस तरह:

uint64_t decode(uint64_t ones, uint64_t ordinal)
{
    uint64_t bits = 0;
    for (uint64_t bit = 63; ones > 0; --bit)
    {
        uint64_t nCk = choose(bit, ones);
        if (ordinal >= nCk)
        {
            ordinal -= nCk;
            bits |= 1 << bit;
            --ones;
        }
    }
    return bits;
}

ध्यान दें कि चूंकि आपको केवल 64 तक के द्विपद गुणांक की आवश्यकता है, इसलिए आप उन्हें रोक सकते हैं।


  • कवर, टी।, एनुमेरेटिव सोर्स एन्कोडिंग । IEEE सूचना थ्योरी, वॉल्यूम IT-19, नंबर 1, जनवरी 1973 पर लेनदेन।

सुंदर और सुरुचिपूर्ण! Enumerative कोडिंग कुछ ऐसी लगती है जो बहुत उपयोगी है - क्या इस पर कोई अच्छा संसाधन हैं (अधिमानतः पाठ्यपुस्तक के रूप में)?
कोज रॉस

क्या यह वास्तव में अभ्यास में बेहतर प्रदर्शन देता है? (बेशक यह RNG की गति पर निर्भर करता है।) यदि नहीं तो अधिक जटिल कोड का उपयोग करने का कोई मतलब नहीं है।
गिल्स एसओ- बुराई को रोकें '10

1
@ बच्चों ने इसकी व्याख्या एक कंप्यूटर विज्ञान के प्रश्न के रूप में की, क्योंकि यह cs.se है। मैंने केवल स्रोत कोड दिया क्योंकि मुझे हुआ कि यह एक आरआरआर सरणी कार्यान्वयन से पड़ा हुआ है। (देखें, उदाहरण के लिए, alexbowe.com/rrr का अर्थ है कि इसका क्या अर्थ है)।
छद्म नाम

1
@ गिल्स आपके सवाल पर अमल करने के लिए, मैंने अपनी भोली पद्धति और फोर्थ में छद्म नाम से प्रदान की गई दोनों को लागू किया। भोली विधि, यहां तक ​​कि एक बहुत ही साधारण xorshift PRNG का उपयोग करते समय, प्रति सेकंड 20 सेकंड के क्रम में कुछ लिया , जबकि छद्म नाम की विधि लगभग तात्कालिक थी। मैंने इसके लिए पूर्व-निर्मित द्विपद की तालिकाओं का उपयोग किया।
कोज रॉस

1
@KozRoss यदि आप n बिट संख्या उत्पन्न करते हैं, और k बिट सेट के साथ संख्याओं की तलाश करते हैं, तो वे काफी दुर्लभ होंगे यदि k n / 2 से बहुत दूर है; यह समझाएगा।
gnasher729

3

अन्य साधनों द्वारा प्राप्त छद्म नाम के उत्तर के समान।

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

तब आपको जो चाहिए वह एक फ़ंक्शन है जो आपको pseudorandom number से ले सकता है , से , इसी 64-बिट संयोजन के लिए।k1c

पास्कल का त्रिभुज आपकी सहायता कर सकता है, क्योंकि प्रत्येक नोड का मान उस नोड से त्रिकोण की जड़ तक के रास्तों की संख्या का सटीक रूप से प्रतिनिधित्व करता है, और प्रत्येक पथ को आपके द्वारा खोजे जा रहे तारों में से एक का प्रतिनिधित्व करने के लिए बनाया जा सकता है, यदि सभी बाएँ मुड़ते हैं साथ लेबल किया गया है , और प्रत्येक दाएं साथ बारी है ।10

तो चलो बिट्स निर्धारित करने के लिए छोड़ दिया है की संख्या है, और उपयोग करने के लिए छोड़ लोगों की संख्या हो।xy

हम जानते हैं कि , और हम इसे संख्या के अगले बिट को ठीक से निर्धारित करने के लिए उपयोग कर सकते हैं प्रत्येक चरण पर:(xy)=(x1y)+(x1y1)

whilex>0

ifx>y

ifk>(x1y):ss+"1",kk(x1y),yy1

else:ss+"0"

else:ss+"1",yy1

xx1


2

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

word randomKBits(int k) {
    word min = 0;
    word max = word(~word(0)); // all 1s
    int n = 0;
    while (n != k) {
        word x = randomWord();
        x = min | (x & max);
        n = popcount(x);
        if (n > k)
            max = x;
        else
            min = x;
    }
    return min;
}

मैंने विभिन्न तरीकों की एक प्रदर्शन तुलना की और यह आमतौर पर सबसे तेज़ है जब तक कि के को बहुत छोटा नहीं जाना जाता है।


0

आप निम्न कार्य कर सकते हैं:

1) यादृच्छिक संख्या उत्पन्न करें, से बीच ।k164

2) सेट वें से ।k01

3) चरण 1 और 2 बार दोहराएंn

A[] है सब के साथ बिट सरणी रों640

for(i=1 to n)
{
    k=ran(1,65-i) % random number between 1 and 65-i
    for(x=1;x<65;x++)
    {
        if(A[x]==0)k--;
        if(k==0)break;
    }
    A[x]=1;
}

गद्य आपके कोड से मेल नहीं खाता है? कोड कभी 1भी सरणी के लिए असाइन नहीं होता है । यह भी एक समान वितरण उत्पन्न करने के लिए प्रतीत नहीं होता है (और संख्या भी नहीं है कि बाधाओं को संतुष्ट) जब एकाधिक ks टकराए
Bergi

@ बर्गी हां भूल गए लाइन ... अब इसे जोड़ा। और k की कई टक्कर को संभाला जाता है। पहली संख्या को 1 और 64 के बीच चुना जाता है, दूसरा 1 और "शेष" 63 के बीच चुना जाता है। इसलिए यह गिनती करते समय 1 को छोड़ देता है ... देखेंलाइन। और यह समान वितरण है। A[x]=1if(A[x]==0)k;
यूजर नॉट

आह, मैं अब देखता हूं। गद्य एल्गोरिथ्म में लंघन का उल्लेख नहीं था।
बरगी

@ अर्घ्यचक्रवर्ती आप 1-आधारित अनुक्रमणिका का उपयोग कर रहे हैं?
कोज रॉस

@KozRoss के साथ शुरू होता है अगर (निश्चित रूप से सभी शून्य होगा) तो, यह जाँच करेगा और अर्थ प्राप्तजो देता है । तो, लूप के बाहर सेट करता है। तो हाँ यह 1-आधारित अनुक्रमण है। यह 0 आधारित तुम सब करने की है भीतरी बदल जाता है बनाने के करने के लिएi=1,k=1AA[1]==0truek;k=0A[1]=1for(x=0;x<64;x++)
उपयोगकर्ता नहीं मिला
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.