क्या वास्तव में यह यादृच्छिक है? मैं ५२ कैसे उत्पन्न कर सकता हूँ! (भाज्य) संभव अनुक्रम?


202

मैं Random (java.util.Random)52 कार्ड के एक डेक फेरबदल करने के लिए उपयोग कर रहा हूँ । 52 हैं! (8.0658175e + 67) संभावनाएं। फिर भी, मुझे पता चला है कि बीज java.util.Randomएक है long, जो 2 ^ 64 (1.8446744e + 19) में बहुत छोटा है।

यहाँ से, मुझे संदेह है कि क्या java.util.Random वास्तव में यह यादृच्छिक है ; यह वास्तव में सभी 52 उत्पन्न करने में सक्षम है! संभावनाओं?

यदि नहीं, तो मैं कैसे एक बेहतर यादृच्छिक अनुक्रम उत्पन्न कर सकता हूं जो सभी 52 का उत्पादन कर सकता है! संभावनाओं?


21
"मैं निश्चित रूप से 52 पर एक वास्तविक यादृच्छिक संख्या कैसे उत्पन्न कर सकता हूं !" से संख्या Randomकभी भी वास्तविक यादृच्छिक संख्या नहीं होती है। यह एक PRNG है, जहां P "छद्म" के लिए खड़ा है। के लिए असली यादृच्छिक संख्या, आप अनियमितता (जैसे random.org के रूप में) का एक स्रोत की जरूरत है।
टीजे क्राउडर

7
@JimGarrison ओपी के बाद ऐसा नहीं है। वह 10 ^ 68 संभावित दृश्यों के बारे में बात कर रहा है। चूंकि प्रत्येक छद्म यादृच्छिक अनुक्रम को इसके बीज द्वारा पहचाना जाता है, ओपी का कहना है कि सबसे अधिक 2 ^ 64 अलग-अलग दृश्यों में हो सकता है।
dasblinkenlight

6
मुझे लगता है कि यह एक दिलचस्प सवाल है, और इसके बारे में सोचने लायक है। लेकिन मैं आपकी समस्या के संदर्भ में सोचने में मदद नहीं कर सकता: यह वही है जो सभी 52 उत्पन्न करने में सक्षम होने की आवश्यकता के लिए अग्रणी है! क्रमपरिवर्तन? उदाहरण के लिए, वास्तविक-विश्व पुल में हम डेक को फेरबदल कर सकते हैं और एक बार में एक कार्ड का सौदा कर सकते हैं, फिर भी केवल ~ 6e11 अलग-अलग हाथ हैं क्योंकि कई अलग-अलग क्रमपरिवर्तन एक ही हाथ में होते हैं। दूसरी दिशा में सोचते हुए, क्या आपको विशेष रूप से 52 के लिए एक समाधान की आवश्यकता है? या क्या आपको एक की आवश्यकता है जो कहते हैं, कहते हैं, दो डेक एक साथ फेरबदल करते हैं (104! / (2 ** 52) संभावनाओं, या ~ 2e150)?
NPE

9
@NPE - उदाहरण के लिए, त्यागी (क्लोंडिक) ले लो, 52! वास्तव में संभव हाथों की संख्या है ..
सर्ज अर्दोविच

3
मुझे लगता है कि यह एक दिलचस्प पढ़ा है: superuser.com/a/712583
Dennis_E

जवाबों:


153

एक यादृच्छिक क्रमचय का चयन करने के साथ-साथ आपके प्रश्न का तात्पर्य एक साथ अधिक और कम यादृच्छिकता की आवश्यकता है। मुझे समझाने दो।

बुरी खबर: अधिक यादृच्छिकता की जरूरत है।

आपके दृष्टिकोण में मूलभूत दोष यह है कि यह 64 बिट्स एन्ट्रॉपी (यादृच्छिक बीज) का उपयोग करके ~ 2 226 संभावनाओं के बीच चयन करने की कोशिश कर रहा है । ~ 2 226 संभावनाओं के बीच का चयन करने के लिए आपको 64 के बजाय 226 बिट्स एन्ट्रापी उत्पन्न करने का तरीका खोजना होगा।

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

अच्छी खबर: कम यादृच्छिकता की जरूरत है।

एक बार जब आपके पास उन 226 यादृच्छिक बिट्स होते हैं, तो बाकी का निर्धारण निर्धारक रूप से किया जा सकता है और इसलिए गुणों को java.util.Randomअप्रासंगिक बनाया जा सकता है । यहां कैसे।

मान लें कि हम सभी 52 उत्पन्न करते हैं! क्रमपरिवर्तन (मेरे साथ सहन) और उन्हें शाब्दिक रूप से क्रमबद्ध करें।

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

अब, आपको वास्तव में उन सभी क्रमपरिवर्तन को उत्पन्न करने की आवश्यकता नहीं है। आप हमारी काल्पनिक छँटाई की सूची में अपनी बेतरतीब ढंग से चुनी गई स्थिति को देखते हुए सीधे उत्पादन कर सकते हैं। यह लेहमर [1] कोड का उपयोग करके ओ (एन 2 ) समय में किया जा सकता है ( क्रमांकन क्रमांकन और फैक्टियाडिक संख्या प्रणाली भी देखें )। यहाँ n आपके डेक का आकार है, अर्थात 52।

इस StackOverflow जवाब में एक C कार्यान्वयन है । वहाँ कई पूर्णांक चर वहाँ n = 52 के लिए अतिप्रवाह होगा, लेकिन सौभाग्य से जावा में आप उपयोग कर सकते हैं java.math.BigInteger। शेष संगणनाओं को लगभग इस प्रकार प्रेषित किया जा सकता है:

public static int[] shuffle(int n, BigInteger random_index) {
    int[] perm = new int[n];
    BigInteger[] fact = new BigInteger[n];
    fact[0] = BigInteger.ONE;
    for (int k = 1; k < n; ++k) {
        fact[k] = fact[k - 1].multiply(BigInteger.valueOf(k));
    }

    // compute factorial code
    for (int k = 0; k < n; ++k) {
        BigInteger[] divmod = random_index.divideAndRemainder(fact[n - 1 - k]);
        perm[k] = divmod[0].intValue();
        random_index = divmod[1];
    }

    // readjust values to obtain the permutation
    // start from the end and check if preceding values are lower
    for (int k = n - 1; k > 0; --k) {
        for (int j = k - 1; j >= 0; --j) {
            if (perm[j] <= perm[k]) {
                perm[k]++;
            }
        }
    }

    return perm;
}

public static void main (String[] args) {
    System.out.printf("%s\n", Arrays.toString(
        shuffle(52, new BigInteger(
            "7890123456789012345678901234567890123456789012345678901234567890"))));
}

[१] लेहरर के साथ भ्रमित होने की नहीं । :)


7
हेह, और मुझे यकीन था कि अंत में लिंक न्यू मैथ होगा । :-)
टीजे क्राउडर

5
@TJCrowder: यह बहुत लगभग था! यह असीम रूप से अलग-थलग रहने वाला रिऐमानियन मैनिफोल्ड्स था जिसने इसे घुमाया। :-)
NPE

2
क्लासिक्स की सराहना करते लोगों को देखकर अच्छा लगा। :-)
टीजे क्राउडर

3
जावा में आपको यादृच्छिक 226 बिट्स कहां से मिलते हैं ? क्षमा करें, आपके कोड का उत्तर नहीं है।
थोरस्टेन एस।

5
मुझे समझ में नहीं आ रहा है कि आपका क्या मतलब है, जावा रैंडम () या तो 64 बिट्स की एंट्रोपी प्रदान नहीं करेगा। ओपी का तात्पर्य एक अनिर्दिष्ट स्रोत से है जो PRNG को बोने के लिए 64 बिट्स का उत्पादन कर सकता है। यह समझ में आता है कि आप 226 बिट्स के लिए एक ही स्रोत पूछ सकते हैं।
मोनिका

60

आपका विश्लेषण सही है: किसी भी विशिष्ट बीज के साथ एक छद्म यादृच्छिक संख्या जनरेटर को एक फेरबदल के बाद उसी क्रम में प्राप्त करना चाहिए, जो क्रमपरिवर्तन की संख्या को सीमित करता है जिसे आप 2 64 तक प्राप्त कर सकते हैं । यह दावा दो बार कॉल करके प्रयोगात्मक रूप से सत्यापित करने के लिए आसान हैCollection.shuffle , एक Randomही बीज के साथ आरंभीकृत वस्तु को पारित करना, और यह देखना कि दो यादृच्छिक फेरबदल समान हैं।

इसके लिए एक समाधान, एक यादृच्छिक संख्या जनरेटर का उपयोग करना है जो एक बड़े बीज के लिए अनुमति देता है। जावा SecureRandomवर्ग प्रदान करता है जिसे byte[]लगभग असीमित आकार के सरणी के साथ आरंभ किया जा सकता है । फिर आप कार्य पूरा SecureRandomकरने के Collections.shuffleलिए एक उदाहरण दे सकते हैं :

byte seed[] = new byte[...];
Random rnd = new SecureRandom(seed);
Collections.shuffle(deck, rnd);

8
निश्चित रूप से, एक बड़े बीज की गारंटी नहीं है कि सभी 52! संभावनाओं का उत्पादन किया जाएगा (जो कि यह सवाल विशेष रूप से किस बारे में है)? एक विचार प्रयोग के रूप में, एक रोग संबंधी PRNG पर विचार करें जो एक मनमाने ढंग से बड़े बीज लेता है और एक अनंत लंबी श्रृंखला उत्पन्न करता है। यह बहुत स्पष्ट लगता है कि PRNG को एक बड़े पर्याप्त बीज लेने की तुलना में अधिक आवश्यकताओं को पूरा करना होगा।
NPE

2
@SerjArdovic हाँ, किसी भी बीज सामग्री को सिक्योरग्रैंडैम वस्तु के लिए पारित किया जाना चाहिए, जो कि जावा प्रलेखन के अनुसार अप्रत्याशित होना चाहिए।
dasblinkenlight

10
@NPE आप सही हैं, हालाँकि बहुत छोटा बीज ऊपरी सीमा की गारंटी है, एक बड़ा पर्याप्त बीज निचली सीमा पर गारंटी नहीं है। यह सब करता है एक सैद्धांतिक ऊपरी सीमा को हटा रहा है, जिससे आरएनजी के लिए सभी 52 उत्पन्न करना संभव है! संयोजन।
dasblinkenlight

5
@SerjArdovic के लिए आवश्यक बाइट्स की सबसे छोटी संख्या 29 है (आपको 52 का प्रतिनिधित्व करने के लिए 226 बिट्स की आवश्यकता है! संभावित बिट संयोजन, जो 28.25 बाइट्स हैं, इसलिए हमें इसे गोल करना होगा)। ध्यान दें कि बीज सामग्री के 29 बाइट्स का उपयोग करने से निचली सीमा स्थापित किए बिना आपके द्वारा प्राप्त किए जा सकने वाले फेरबदल की संख्या पर सैद्धांतिक ऊपरी सीमा को हटा दिया जाता है (एक बहुत बड़े बीज लेने वाले भद्दे आरएनजी के बारे में एनपीई की टिप्पणी देखें) और सभी शून्य का एक क्रम उत्पन्न करता है।
dasblinkenlight

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

26

सामान्य तौर पर, एक छद्म आयामी संख्या जनरेटर (PRNG) 52-आइटम सूची के सभी क्रमपरिवर्तन में से नहीं चुन सकता है यदि इसकी राज्य लंबाई 226 बिट्स से कम है।

java.util.Random2 48 के मापांक के साथ एक एल्गोरिथ्म लागू करता है ; इस प्रकार इसकी राज्य लंबाई केवल 48 बिट्स है, इसलिए मेरे द्वारा संदर्भित 226 बिट्स की तुलना में बहुत कम है। आपको एक बड़े राज्य की लंबाई के साथ एक और PRNG का उपयोग करने की आवश्यकता होगी - विशेष रूप से, 52 भाज्य या उससे अधिक की अवधि के साथ।

यादृच्छिक संख्या जनरेटर पर मेरे लेख में "फेरबदल" भी देखें ।

यह विचार PRNG की प्रकृति से स्वतंत्र है; यह क्रिप्टोग्राफिक और गैर-क्रिप्टोग्राफ़िक PRNGs पर समान रूप से लागू होता है (निश्चित रूप से, जब भी सूचना सुरक्षा शामिल होती है, तो गैर-क्रिप्टोग्राफ़िक PRNG अनुपयुक्त होते हैं)।


यद्यपि java.security.SecureRandomअसीमित लंबाई के बीजों को पारित करने की अनुमति देता है, SecureRandomकार्यान्वयन एक अंतर्निहित PRNG (जैसे, "SHA1PRNG" या "DRBG") का उपयोग कर सकता है। और यह उस PRNG की अवधि (और कुछ हद तक, राज्य की लंबाई) पर निर्भर करता है, चाहे वह 52 गुटीय क्रमपरिवर्तन में से चुनने में सक्षम हो। (ध्यान दें कि मैं "राज्य की लंबाई" को परिभाषित करता हूं क्योंकि "PRNG बीज का अधिकतम आकार उस बीज को छोटा या संपीड़ित किए बिना अपने राज्य को शुरू करने के लिए ले जा सकता है ")।


18

मुझे पहले से माफी मांगनी चाहिए, क्योंकि यह समझना थोड़ा कठिन है ...

सबसे पहले, आप पहले से ही जानते हैं कि java.util.Randomपूरी तरह से यादृच्छिक नहीं है। यह बीज से पूरी तरह से अनुमानित तरीके से अनुक्रम उत्पन्न करता है। आप पूरी तरह से सही हैं कि, क्योंकि बीज केवल 64 बिट लंबा है, यह केवल 2 ^ 64 विभिन्न अनुक्रम उत्पन्न कर सकता है। यदि आप किसी तरह 64 वास्तविक यादृच्छिक बिट्स उत्पन्न करते हैं और एक बीज का चयन करने के लिए उनका उपयोग करते हैं, तो आप उस बीज का उपयोग 52 के सभी के बीच बेतरतीब ढंग से चुनने के लिए नहीं कर सकते हैं ! समान संभावना के साथ संभव अनुक्रम।

हालाँकि, इस तथ्य का कोई परिणाम नहीं है जब तक आप वास्तव में 2 ^ 64 से अधिक अनुक्रम उत्पन्न करने वाले नहीं हैं, जब तक कि 2 ^ 64 अनुक्रमों के बारे में 'विशेष' या 'विशेष रूप से विशेष' कुछ भी नहीं है जो इसे उत्पन्न कर सकता है ।

कहते हैं कि आपके पास बहुत बेहतर PRNG था जो 1000-बिट बीजों का उपयोग करता था। कल्पना कीजिए कि आपके पास इसे आरंभ करने के दो तरीके हैं - एक तरीका यह है कि इसे पूरे बीज का उपयोग करके आरंभ किया जाएगा, और एक तरीका यह होगा कि बीज को प्रारंभिक करने से पहले 64 बिट तक नीचे ले जाया जाए।

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

वैकल्पिक रूप से, कल्पना करें कि Randomवर्ग में 2 ^ 64 अनुक्रमों की एक सरणी थी जो कि किसी भी समय दूर के अतीत में पूरी तरह से और यादृच्छिक रूप से चुनी गई थी, और यह कि बीज इस सरणी में सिर्फ एक सूचकांक था।

तो यह तथ्य कि Randomइसके बीज के लिए केवल 64 बिट्स का उपयोग किया जाता है, वास्तव में जरूरी नहीं कि यह एक समस्या है, जब तक कि कोई महत्वपूर्ण मौका नहीं है कि आप एक ही बीज का दो बार उपयोग करेंगे।

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

संपादित करें:

मुझे यह जोड़ना चाहिए, भले ही उपरोक्त सभी सही हो, कि वास्तविक कार्यान्वयन java.util.Randomभयानक नहीं है। यदि आप कार्ड गेम लिख रहे हैं, तो शायद MessageDigestSHA-256 हैश उत्पन्न करने के लिए API का "MyGameName"+System.currentTimeMillis()उपयोग करें, और उन बिट्स का उपयोग डेक को फेरबदल करने के लिए करें। उपरोक्त तर्क के अनुसार, जब तक आपके उपयोगकर्ता वास्तव में जुआ नहीं कर रहे हैं, आपको चिंता करने की ज़रूरत नहीं है कि currentTimeMillisएक लंबा रिटर्न देता है। यदि आपके उपयोगकर्ता वास्तव में जुआ कर रहे हैं , तो SecureRandomबिना बीज के उपयोग करें ।


6
@ टॉर्स्टन, आप किसी भी तरह का परीक्षण कैसे लिख सकते हैं जो यह निर्धारित कर सके कि कार्ड संयोजन हैं जो कभी नहीं आ सकते हैं?
मैट टिमरमैन

2
जॉर्ज मार्साग्लिया से डेयरहार्ड या पियरे L'Ecuyer / रिचर्ड Simard से टेस्टहेड जैसे कई यादृच्छिक संख्या परीक्षण सूट हैं जो यादृच्छिक आउटपुट में सांख्यिकीय विसंगतियों को आसानी से पाते हैं। कार्ड जाँच के लिए आप दो वर्गों का उपयोग कर सकते हैं। आप कार्ड ऑर्डर निर्धारित करें। पहला वर्ग xy युग्म के रूप में पहले दो कार्डों की स्थिति दिखाता है: पहला कार्ड x के रूप में और दूसरा कार्ड के अंतर (!) स्थिति (-26-25) y के रूप में। दूसरा वर्ग 2nd / 3rd के सापेक्ष (-25-25) के साथ 3rd और 4th कार्ड दिखाता है। यदि आप इसे कुछ समय के लिए चलाते हैं तो यह आपके वितरण में तुरंत अंतराल और क्लस्टर दिखाएगा
थोर्स्टन एस।

4
ठीक है, यह वह परीक्षण नहीं है जो आपने कहा था कि आप लिख सकते हैं, लेकिन यह भी लागू नहीं होता है। आप यह क्यों मानते हैं कि वितरण में अंतराल और गुच्छे हैं जो ऐसे परीक्षणों को उजागर करेंगे? जैसा कि मैंने उल्लेख किया "PRNG कार्यान्वयन में एक विशिष्ट कमजोरी" होगी, और संभव बीजों की संख्या के साथ कुछ भी नहीं करना है। ऐसे परीक्षणों के लिए आपको जनरेटर की आवश्यकता नहीं होती है। मैंने शुरुआत में चेतावनी दी थी कि यह समझना मुश्किल था।
मैट टिम्मरमैन

3
@ThorstenS। वे परीक्षण सूट बिल्कुल निर्धारित नहीं करेंगे कि क्या आपका स्रोत 64-बिट-सीड क्रिप्टोग्राफिक रूप से सुरक्षित PRNG है या एक वास्तविक NNG है। (परीक्षण PRNGs उन सभी के लिए उपयुक्त हैं, आखिरकार।) भले ही आप उपयोग में एल्गोरिथ्म जानते हों, एक अच्छा PRNG राज्य स्थान की एक क्रूर बल खोज के बिना राज्य का निर्धारण करने के लिए इसे संभव बनाता है।
स्नेफेल

1
@ThorstenS .: कार्ड के एक वास्तविक डेक में, संयोजन के विशाल बहुमत कभी नहीं आएगा। आप अभी नहीं जानते कि वे कौन से हैं। एक अर्ध-सभ्य PRNG के लिए यह एक ही है - यदि आप परीक्षण कर सकते हैं कि क्या दिया गया आउटपुट अनुक्रम लंबे समय तक इसकी छवि में है, तो यह PRNG में एक दोष है। 52 की तरह हास्यास्पद रूप से विशाल राज्य / अवधि! आवश्यकता नहीं है; 128-बिट को पर्याप्त होना चाहिए।
आर .. गिटहब स्टॉप हेल्पिंग ICE

10

मैं इस पर थोड़ा अलग करने जा रहा हूं। आप अपनी मान्यताओं पर सही हैं - आपका PRNG सभी 52 को हिट करने में सक्षम नहीं है! संभावनाओं।

सवाल यह है: आपके कार्ड गेम का पैमाना क्या है?

यदि आप एक सरल klondike शैली खेल बना रहे हैं? तो आप निश्चित रूप से सभी 52 की जरूरत नहीं है ! संभावनाओं। इसके बजाय, इसे इस तरह से देखें: एक खिलाड़ी के पास 18 क्विंटल होगा अलग खेल होंगे। यहां तक ​​कि 'बर्थडे प्रॉब्लम' के लिए भी, उन्हें पहले डुप्लिकेट गेम में दौड़ने से पहले अरबों हाथों को खेलना होगा।

यदि आप एक मोंटे कार्लो सिमुलेशन बना रहे हैं? तब तुम शायद हो ठीक हो। PRNG में 'P' के कारण आपको कलाकृतियों से निपटना पड़ सकता है, लेकिन आप शायद कम बीज स्थान (फिर से, आप अद्वितीय संभावनाओं के क्विंटलों को देख रहे हैं) के कारण समस्याओं में नहीं जा सकते। फ्लिप पक्ष, यदि आप बड़े पुनरावृत्ति गणना के साथ काम कर रहे हैं, तो, हाँ, आपका कम बीज स्थान एक डील-ब्रेकर हो सकता है।

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


9

लघु समाधान जो अनिवार्य रूप से दासब्लिंकलाइट के समान है:

// Java 7
SecureRandom random = new SecureRandom();
// Java 8
SecureRandom random = SecureRandom.getInstanceStrong();

Collections.shuffle(deck, random);

आपको आंतरिक स्थिति के बारे में चिंता करने की आवश्यकता नहीं है। लंबी व्याख्या क्यों:

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

यह इनपुट (!) जिसमें अभी भी स्प्यूरियस निशान हो सकते हैं, को क्रिप्टोग्राफिक रूप से मजबूत हैश में खिलाया जाता है जो उन निशानों को हटा देता है। यही कारण है कि उन CSPRNG का उपयोग किया जाता है, न कि उन संख्याओं को स्वयं बनाने के लिए! SecureRandomएक काउंटर जो कितने बिट्स इस्तेमाल किया गया (निशान है getBytes(), getLong()और आदि) रिफिल SecureRandomएन्ट्रापी बिट्स के साथ जब आवश्यक

संक्षेप में: आपत्तियों को भूल जाते हैं और SecureRandomसही यादृच्छिक संख्या जनरेटर के रूप में उपयोग करते हैं ।


4

यदि आप संख्या को केवल बिट्स (या बाइट्स) के एक सरणी के रूप में मानते हैं तो शायद आप Random.nextBytesइस स्टैक ओवरफ्लो प्रश्न में सुझाए गए (सुरक्षित) समाधान का उपयोग कर सकते हैं , और फिर सरणी को ए में मैप कर सकते हैं new BigInteger(byte[])


3

एक बहुत ही सरल एल्गोरिथ्म SHA-256 को 0 से ऊपर की ओर बढ़ने वाले पूर्णांकों के अनुक्रम में लागू करना है। (एक नमक को "एक अलग अनुक्रम प्राप्त करने के लिए" वांछित होने पर संलग्न किया जा सकता है।) यदि हम मानते हैं कि SHA-256 का उत्पादन "उतना ही अच्छा है" "0 और 2 256 के बीच समान रूप से वितरित पूर्णांक - 1 तो हमारे पास पर्याप्त एंट्रोपी है कार्य।

SHA256 (जब पूर्णांक के रूप में व्यक्त किया गया है) के आउटपुट से क्रमचय प्राप्त करने के लिए बस इसे 52 52, 51, 50 कम करने की आवश्यकता है ... इस छद्मकोश में:

deck = [0..52]
shuffled = []
r = SHA256(i)

while deck.size > 0:
    pick = r % deck.size
    r = floor(r / deck.size)

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