181783497276652981 और 8682522807148012 रैंडम (जावा 7) में क्या है?


112

में क्यों चुना 181783497276652981और 8682522807148012चुना गया Random.java?

यहाँ जावा एसई JDK 1.7 से प्रासंगिक स्रोत कोड है:

/**
 * Creates a new random number generator. This constructor sets
 * the seed of the random number generator to a value very likely
 * to be distinct from any other invocation of this constructor.
 */
public Random() {
    this(seedUniquifier() ^ System.nanoTime());
}

private static long seedUniquifier() {
    // L'Ecuyer, "Tables of Linear Congruential Generators of
    // Different Sizes and Good Lattice Structure", 1999
    for (;;) {
        long current = seedUniquifier.get();
        long next = current * 181783497276652981L;
        if (seedUniquifier.compareAndSet(current, next))
            return next;
    }
}

private static final AtomicLong seedUniquifier
    = new AtomicLong(8682522807148012L);

इसलिए, new Random()बिना किसी बीज पैरामीटर के आह्वान करने पर वर्तमान "बीज अद्वितीय" हो जाता है और इसके साथ XORs हो जाता है System.nanoTime()। फिर इसे 181783497276652981अगली बार संग्रहीत करने के लिए एक और बीज अद्वितीय बनाने के लिए उपयोग किया new Random()जाता है।

शाब्दिक 181783497276652981Lऔर 8682522807148012Lस्थिरांक में नहीं रखे जाते हैं, लेकिन वे कहीं और दिखाई नहीं देते हैं।

पहली बार में टिप्पणी ने मुझे एक आसान नेतृत्व दिया। उस लेख के लिए ऑनलाइन खोज करने से वास्तविक लेख मिलता है8682522807148012कागज में प्रकट नहीं होता है, लेकिन 181783497276652981प्रकट होता है - एक अन्य संख्या के विकल्प के रूप में 1181783497276652981, जो 181783497276652981एक 1पूर्वनिर्मित के साथ है ।

कागज का दावा है कि 1181783497276652981एक संख्या है जो एक रैखिक बधाई जनरेटर के लिए अच्छी "योग्यता" पैदा करती है। क्या यह संख्या केवल जावा में गलत कॉपी की गई थी? क्या 181783497276652981एक स्वीकार्य योग्यता है?

और क्यों 8682522807148012चुना गया ?

या तो संख्या के लिए ऑनलाइन खोज करने से कोई स्पष्टीकरण नहीं मिलता है, केवल यह पृष्ठ जो 1सामने गिराए गए को भी नोटिस करता है 181783497276652981

क्या अन्य संख्याओं को चुना जा सकता था जो इन दो संख्याओं के साथ-साथ काम करते? क्यों या क्यों नहीं?


मैं केवल यह बताना चाहूंगा कि इनमें से कोई भी स्थिरांक (यहां तक ​​कि शुरुआत में लोगों के साथ बड़े भी) फिट करने के लिए बहुत बड़े नहीं हैं, हालांकि गुणन एक अतिप्रवाह में परिणाम देगा।
नानोफैड

6
8682522807148012वर्ग के पिछले संस्करण की विरासत है, जैसा कि 2010 में किए गए संशोधनों में देखा जा सकता है । 181783497276652981Lलिखने में कोई त्रुटि वास्तव में हो रहा है और आप एक बग रिपोर्ट फ़ाइल कर सकते हैं।
assylias

6
या तो यह एक टाइपो, यानी एक बग, या अघोषित प्रेरणा के साथ एक सुविधा है। आपको लेखकों से पूछना होगा। यहां आपको जो कुछ भी मिलेगा, वह कमोबेश बेपर्दा राय होगा। यदि आपको लगता है कि यह बग है, तो बग रिपोर्ट सबमिट करें।
लोर्ने का अंक

1
विशेष रूप से विभिन्न उत्तरों को देखते हुए, यह प्रत्येक स्थिर के लिए दो अलग-अलग प्रश्न हो सकते हैं।
मार्क हर्ड

1
इस तरह के एक मौलिक वर्ग में निर्मित वैश्विक स्केलेबिलिटी अड़चन को देखने के लिए दुख की बात है। seedUniquifierएक 64 कोर बॉक्स पर बेहद संरक्षित हो सकता है। एक थ्रेड-लोकल अधिक स्केलेबल होता।
usr

जवाबों:


57
  1. क्या यह संख्या केवल जावा में गलत कॉपी की गई थी?

    हाँ, एक टाइपो लगता है।

  2. क्या 181783497276652981 में स्वीकार्य योग्यता है?

    यह कागज में प्रस्तुत मूल्यांकन एल्गोरिदम का उपयोग करके निर्धारित किया जा सकता है। लेकिन "मूल" संख्या की योग्यता शायद अधिक है।

  3. और 8682522807148012 को क्यों चुना गया?

    बेतरतीब लगता है। यह कोड लिखे जाने पर System.nanoTime () का परिणाम हो सकता है।

  4. क्या अन्य संख्याओं को चुना जा सकता था जो इन दो संख्याओं के साथ-साथ काम करते?

    हर संख्या समान रूप से "अच्छी" नहीं होगी। तो, नहीं।

सीडिंग रणनीतियाँ

JRE के विभिन्न संस्करणों और कार्यान्वयन के बीच डिफ़ॉल्ट-सीडिंग स्कीमा में अंतर हैं।

public Random() { this(System.currentTimeMillis()); }
public Random() { this(++seedUniquifier + System.nanoTime()); }
public Random() { this(seedUniquifier() ^ System.nanoTime()); }

यदि आप एक पंक्ति में कई RNG बनाते हैं, तो पहले वाला स्वीकार्य नहीं है। यदि उनके निर्माण का समय एक ही मिलीसेकंड सीमा में पड़ता है, तो वे पूरी तरह से समान अनुक्रम देंगे। (वही बीज => वही क्रम)

दूसरा एक धागा सुरक्षित नहीं है। जब एक ही समय में कई थ्रेड्स समान आरएनजी प्राप्त कर सकते हैं। इसके अतिरिक्त, बाद के आरंभीकरण के बीज सहसंबद्ध होते हैं। सिस्टम के वास्तविक टाइमर रिज़ॉल्यूशन के आधार पर, बीज अनुक्रम रैखिक रूप से बढ़ सकता है (n, n + 1, n + 2, ...)। जैसा कि कहा गया है कि यादृच्छिक बीजों को कितने अलग-अलग होने की आवश्यकता है? और संदर्भित कागज आम दोष छद्म आयामी संख्या जनरेटर के प्रारंभ में , सहसंबद्ध बीज कई आरएनजी के वास्तविक अनुक्रमों के बीच सहसंबंध उत्पन्न कर सकते हैं।

तीसरा दृष्टिकोण बेतरतीब ढंग से वितरित और इस तरह के असंबंधित बीज बनाता है, यहां तक ​​कि थ्रेड्स और उसके बाद के आरंभीकरण में भी। तो वर्तमान जावा डॉक्स:

यह कंस्ट्रक्टर यादृच्छिक संख्या जनरेटर के बीज को इस निर्माता के किसी भी अन्य आह्वान से अलग होने की संभावना के मूल्य पर सेट करता है।

"धागे के पार" और "असंबद्ध" द्वारा बढ़ाया जा सकता है

बीज की गुणवत्ता

लेकिन बोने के अनुक्रम की यादृच्छिकता अंतर्निहित आरएनजी के रूप में ही अच्छी है। इस जावा कार्यान्वयन में बीज अनुक्रम के लिए उपयोग किया जाने वाला RNG, c = 0 और m = 2 ^ 64 के साथ गुणक रैखिक गुणक जनरेटर (MLCG) का उपयोग करता है। (मापांक 2 ^ 64 को स्पष्ट रूप से 64 बिट लंबे पूर्णांकों के अतिप्रवाह द्वारा दिया गया है) क्योंकि शून्य c और 2-mod मापांक की शक्ति, "गुणवत्ता" (चक्र की लंबाई, बिट-सहसंबंध, ...) सीमित है । जैसा कि कागज कहता है, समग्र चक्र लंबाई के अलावा, हर एक बिट की अपनी चक्र लंबाई होती है, जो कम महत्वपूर्ण बिट्स के लिए तेजी से घट जाती है। इस प्रकार, निचले बिट्स का दोहराव पैटर्न होता है। (सीड यूनीक्युटिफ़ायर () का परिणाम थोड़ा-सा उलटा होना चाहिए, इससे पहले कि यह वास्तविक आरएनजी में 48-बिट्स पर काट दिया जाए)

लेकिन यह तेज़ है! और अनावश्यक तुलना-और-सेट-लूप से बचने के लिए, लूप शरीर तेज होना चाहिए। यह संभवतः इस विशिष्ट MLCG के उपयोग को समझाता है, बिना जोड़ के, बिना किसी गुणा के, केवल एक गुणा।

और उल्लिखित पेपर 1181783497276652981 के रूप में c = 0 और m = 2 ^ 64 के लिए अच्छे "गुणक" की सूची प्रस्तुत करता है।

सभी सब में: प्रयास @ JRE- डेवलपर्स के लिए;) लेकिन एक टाइपो है। (लेकिन कौन जानता है, जब तक कि कोई इसका मूल्यांकन नहीं करता है, संभावना है कि लापता 1 वास्तव में सीडिंग आरएनजी को बेहतर बनाता है।)

लेकिन कुछ गुणक निश्चित रूप से बदतर हैं: "1" एक निरंतर अनुक्रम की ओर जाता है। "2" एक एकल-बिट-बढ़ते अनुक्रम (किसी तरह सहसंबद्ध) की ओर जाता है ...

RNGs के लिए अंतर-अनुक्रम-सहसंबंध वास्तव में (मोंटे कार्लो) सिमुलेशन के लिए प्रासंगिक है, जहां कई यादृच्छिक अनुक्रम त्वरित और समानांतर भी हैं। इस प्रकार "स्वतंत्र" सिमुलेशन रन प्राप्त करने के लिए एक अच्छी सीडिंग रणनीति आवश्यक है। इसलिए C ++ 11 मानक असम्बद्ध बीजों के उत्पादन के लिए बीज अनुक्रम की अवधारणा का परिचय देता है ।


3
कम से कम यह अभी भी अजीब है, अगर उन्होंने सबसे महत्वपूर्ण एक के बजाय कम से कम एक महत्वपूर्ण गिरा दिया था, तो प्रत्येक गुणन थोड़ा खो देता है जब तक कि अंततः (62 चरणों के बाद) seedUniquifierशून्य पर अटक जाता है।
हेरोल्ड

9

यदि आप मानते हैं कि यादृच्छिक संख्या जनरेटर के लिए उपयोग किया जाने वाला समीकरण है:

LCGEquation

जहां X (n + 1) अगला नंबर है, एक गुणक है, X (n) वर्तमान संख्या है, c, वृद्धि है और m मापांक है।

यदि आप आगे देखते हैं Random, तो ए, सी और एम को कक्षा के हेडर में परिभाषित किया गया है

private static final long multiplier = 0x5DEECE66DL;   //= 25214903917 -- 'a'
private static final long addend = 0xBL;               //= 11          -- 'c'
private static final long mask = (1L << 48) - 1;       //= 2 ^ 48 - 1  -- 'm'

और विधि protected int next(int bits)को देखते हुए यह समीकरण लागू किया गया था

nextseed = (oldseed * multiplier + addend) & mask;
//X(n+1) =  (X(n)   *      a     +    c  ) mod m

इसका तात्पर्य यह है कि विधि seedUniquifier()वास्तव में एक्स (एन) या पहले मामले में प्रारंभिक एक्स (0) पर हो रही है 8682522807148012 * 181783497276652981, जो वास्तव में है , इस मान को फिर से संशोधित किया जाता है System.nanoTime()। यह एल्गोरिथ्म ऊपर दिए गए समीकरण के अनुरूप है, लेकिन निम्नलिखित X (0) = 8682522807148012, a = 181783497276652981, m = 2 ^ 64 और c = 0. के साथ है, लेकिन जैसा कि मॉड मीटर मीटर के पूर्ववर्ती अतिप्रवाह से होता है, वैसे ही बन जाता है

eq2

कागज को देखते हुए , a का मान 1181783497276652981m = 2 ^ 64, c = 0. के लिए है, इसलिए यह सिर्फ एक टाइपो प्रतीत होता है और 8682522807148012X (0) के लिए मान जो प्रतीत होता है कि विरासत कोड से यादृच्छिक रूप से चुनी गई संख्या प्रतीत होती है के लिए Randomजैसा कि यहां देखा गया है। लेकिन इन चुने हुए नंबरों की योग्यता अभी भी मान्य हो सकती है लेकिन जैसा कि थॉमस बी ने उल्लेख किया है, शायद कागज में "अच्छा" नहीं है।

EDIT - नीचे मूल विचारों को स्पष्ट किया गया है इसलिए इसे अवहेलना किया जा सकता है लेकिन इसे संदर्भ के लिए छोड़ दिया जाता है

इससे मुझे निष्कर्ष मिलता है:

  1. कागज का संदर्भ स्वयं मूल्य के लिए नहीं है, बल्कि a, c और m के विभिन्न मूल्यों के कारण मूल्यों को प्राप्त करने के लिए उपयोग की जाने वाली विधियों के लिए है

  2. यह केवल संयोग है कि मूल्य अन्यथा प्रमुख 1 के अलावा अन्य है और टिप्पणी गलत है (हालांकि अभी भी विश्वास करने के लिए संघर्ष कर रहे हैं)

या

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

तो आपके सवाल का जवाब देने के लिए

क्या अन्य संख्याओं को चुना जा सकता था जो इन दो संख्याओं के साथ-साथ काम करते? क्यों या क्यों नहीं?

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


1
वास्तव में नहीं - दो एल्गोरिदम हैं: (i) 1 हर बार एक नया यादृच्छिक बीज बनाने के लिए जिसे कंस्ट्रक्टर कहा जाता है। वह एलगो एक साधारण X_n + 1 = X_n * a का उपयोग करता है। लंबे ओवरफ्लो के कारण यह X_n + 1 = X_n * a mod m के बराबर है। एक = 181783497276652981 और एम = 2 ^ 64 के साथ। (ii) एक अन्य एल्गो, जो एक दिए गए बीज से शुरू होता है, यादृच्छिक संख्या की एक श्रृंखला का उत्पादन करता है। दूसरा अहंकार वह है जिसका आप उल्लेख करते हैं और डॉक्स समझाते हैं कि " यह एक रेखीय अभिनंदनशील छद्म आयामी संख्या जनरेटर है, जैसा कि नुथ इन कंप्यूटर प्रोग्रामिंग के द्वारा वर्णित है "।
अस्तिलिअ

1
@assylias मैं आपकी बात देख रहा हूं, मुझे स्रोत कोड में पकड़ा गया Randomऔर उद्धृत पेपर मैंने मूल प्रश्न को पूरी तरह से देख लिया है, जल्द ही संपादित करेगा, धन्यवाद।
जावा डेविल

3

आपके द्वारा दिए गए लिंक के अनुसार, उन्होंने 2 ^ 64 से सबसे अच्छी पैदावार ( लापता 1 को जोड़ने के बाद ) को चुना है क्योंकि लंबे समय तक 2 ^ 128 से संख्या नहीं हो सकती है

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