क्यों System.Security.Cryptography.RandomNumberGenerator के बजाय C # क्लास System.Random का उपयोग करें?


85

क्यों किसी को भी "मानक" यादृच्छिक संख्या से जनरेटर का प्रयोग करेंगे System.Random सभी के बजाय हमेशा से क्रिप्टोग्राफी द्वारा सुरक्षित यादृच्छिक संख्या जनरेटर का उपयोग कर System.Security.Cryptography.RandomNumberGenerator (या उसके उपवर्गों क्योंकि RandomNumberGenerator सार है)?

नैट लॉसन ने अपनी गूगल टेक टॉक प्रस्तुति " क्रिप्टो स्ट्राइक्स बैक " में मिनट 13:11 पर हमें बताया कि पायथन, जावा और सी # से "मानक" यादृच्छिक संख्या जनरेटर का उपयोग न करें और इसके बजाय क्रिप्टोग्राफिक रूप से सुरक्षित संस्करण का उपयोग करें।

मुझे यादृच्छिक संख्या जनरेटर के दो संस्करणों के बीच अंतर पता है ( प्रश्न 101337 देखें )।

लेकिन सुरक्षित यादृच्छिक संख्या जनरेटर का उपयोग न करने के लिए क्या औचित्य है? क्यों System.Random का उपयोग करें? शायद प्रदर्शन?


7
जो आप टाइप करेंगे?
माचा

13
बहुत सारे लोग गंभीरता से इसका उपयोग करते हैं कि वे क्या करते हैं (आमतौर पर ज़ोर से नहीं)। कोड जितना लिखा गया है, उससे अधिक पढ़ा जाता है, जो तुच्छ लंबाई के अंतर की परवाह करता है?
मार्क सोउल

3
लेकिन वैसे भी अगर आप क्रिप्टोग्राफी नहीं कर रहे हैं तो आपको क्रिप्टोग्राफिक आरएनजी का उपयोग क्यों करना चाहिए?
मार्क सोउल

3
@ माचा, कि क्या उपनाम के लिए कर रहे हैं ->using R = System.Security.Cryptography.RandomNumberGenerator; R.Create();
cchamberlain

जवाबों:


144

गति और आशय। यदि आप एक यादृच्छिक संख्या उत्पन्न कर रहे हैं और सुरक्षा की कोई आवश्यकता नहीं है, तो धीमी क्रिप्टो फ़ंक्शन का उपयोग क्यों करें? आपको सुरक्षा की आवश्यकता नहीं है, इसलिए किसी और को यह क्यों लगता है कि नंबर का उपयोग किसी सुरक्षित चीज़ के लिए किया जा सकता है जब वह नहीं होगा?


30
मुझे आशय तर्क बहुत पसंद है।
Lernkurve

12
यह ध्यान दिया जाना चाहिए कि Random.GetNext स्पेक्ट्रम पर यादृच्छिक संख्याओं को "फैलाने" से दूर है, विशेष रूप से थ्रेडेड वातावरण में। जब मैं Rand7 समस्या से Rand7 के विभिन्न समाधानों का परीक्षण करने के लिए एक कार्यक्रम लिख रहा था, तो मैं इस समस्या को लेकर भागा। त्वरित थ्रेडेड टेस्ट में अब 0 और 10 के बीच 100000 रैंडम संख्याओं में से, उत्पन्न संख्याओं के 82470 0. थे। मैंने अपने पिछले परीक्षणों में इसी तरह की विसंगतियां देखीं। क्रायटोग्राफ़ी यादृच्छिक संख्याओं के वितरण में भी बहुत है। मुझे लगता है कि सबक हमेशा अपने यादृच्छिक डेटा का परीक्षण करना है यह देखने के लिए कि यह आपकी आवश्यकताओं के लिए "यादृच्छिक पर्याप्त" है।
क्रिस्टोफर L

35
@ क्रिस्तोफ़र मुझे लगता है कि आपने दुरुपयोग किया है Random। मुझे लगता है कि: आपने Randomप्रत्येक संख्या के लिए वर्ग का एक नया उदाहरण बनाया है , क्योंकि यह मोटे टाइमर द्वारा वरीयता प्राप्त है, लगभग 1-16ms के अंतराल के लिए समान मूल्य के साथ बोया जाएगा।
कोडइन्चौस

15
@CodesInChaos: इसके अलावा, एक दौड़-स्थिति है Randomजिसके कारण यह सभी 0 को वापस करने के लिए होता है जब एक ही वस्तु का उपयोग कई थ्रेड से किया जाता है।
ब्लूराजा - डैनी पफ्लुगुएफ्ट

3
@ क्रिस्तोफेलर: ऊपर टिप्पणी देखें, यह उत्तर
ब्लूराजा - डैनी पफ्लुगुफ़ेक्ट

65

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

Random gen1 = new Random();     // auto seeded by the clock
Random gen2 = new Random(0);    // Next(10) always yields 7,8,7,5,2,....

2
और BitConverter.ToInt32 (बाइट [] मूल्य, int startIndex) है, जिसे समझना आसान हो सकता है। ;)
सिसवे

7
इयान बेल और डेविड ब्रेबेन ने बहुत सीमित स्मृति के साथ ग्रहों और उनकी विशेषताओं (आकार आदि) की एक विशाल सूची बनाने के लिए कंप्यूटर गेम एलीट में एक यादृच्छिक जनरेटर का उपयोग किया। यह जनरेटर पर एक नियतात्मक पैटर्न (एक बीज से) बनाने पर भी निर्भर करता है - जिसे क्रिप्टो एक स्पष्ट रूप से (डिजाइन द्वारा) नहीं करता है। उन्होंने यहां कैसे किया इस पर कुछ और जानकारी है: wiki.alioth.net/index.php। / Random_number_generator और किताब "अनंत गेम यूनिवर्स: गणितीय तकनीक" आईएसबीएन: 1584500581 में ऐसी तकनीकों पर अधिक सामान्य चर्चा है।
डेनियल जेम्स ब्रायर्स


2
@phoog "परिणामस्वरूप, आपके एप्लिकेशन कोड को यह नहीं मान लेना चाहिए कि उसी बीज का .NET .NET फ्रेमवर्क के विभिन्न संस्करणों में समान छद्म यादृच्छिक क्रम होगा।" - मुझे पता नहीं, मुझे बहुत स्पष्ट लगता है। हालांकि, मुझे आश्चर्य नहीं होगा अगर वे इस चेतावनी के बावजूद मौजूदा कार्यक्रमों को तोड़ने के बिना व्यवहार में इसे बदल नहीं सकते हैं।
रोमन स्टार्कोव

2
@ फोग: आप एक बात कह रहे हैं और फिर इसके ठीक विपरीत। आप सीधे खुद का विरोध कर रहे हैं।
तिमवी

53

सबसे पहले आपने जो प्रस्तुति दी, वह सुरक्षा उद्देश्यों के लिए केवल यादृच्छिक संख्याओं के बारे में बात करती है। इसलिए यह दावा नहीं करता है कि यह Randomगैर-सुरक्षा उद्देश्यों के लिए खराब है।

लेकिन मैं दावा करता हूं कि यह है। .Net 4 कार्यान्वयन Randomकई तरीकों से त्रुटिपूर्ण है। यदि आप अपने यादृच्छिक संख्या की गुणवत्ता के बारे में परवाह नहीं करते हैं तो मैं केवल इसका उपयोग करने की सलाह देता हूं। मैं बेहतर तीसरे पक्ष के कार्यान्वयन का उपयोग करने की सलाह देता हूं।

ज्वाला 1: बीजारोपण

वर्तमान समय के साथ डिफ़ॉल्ट निर्माता बीज। इस प्रकार Randomकम समय-सीमा (ca. 10ms) के भीतर डिफ़ॉल्ट कंस्ट्रक्टर के साथ बनाए गए सभी उदाहरण उसी क्रम को वापस करते हैं। यह प्रलेखित और "बाय-डिज़ाइन" है। यदि आप अपने कोड को मल्टी-थ्रेड करना चाहते हैं तो यह विशेष रूप से कष्टप्रद है, क्योंकि आप Randomप्रत्येक थ्रेड के निष्पादन की शुरुआत में केवल एक उदाहरण नहीं बना सकते हैं ।

जब आवश्यक हो तो डिफ़ॉल्ट कंस्ट्रक्टर और मैन्युअल रूप से बीज का उपयोग करते समय वर्कअराउंड अतिरिक्त सावधान रहना चाहिए।

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

दोष 2: यादृच्छिक संख्याओं का वितरण Next(int maxValue)पक्षपाती है

ऐसे पैरामीटर हैं जिनके Next(int maxValue)लिए स्पष्ट रूप से एक समान नहीं है। उदाहरण के लिए यदि आप गणना r.Next(1431655765) % 2करते हैं तो आपको 0लगभग 2/3 नमूने मिलेंगे । (उत्तर के अंत में नमूना कोड।)

दोष 3: NextBytes()विधि अक्षम है।

प्रति बाइट लागत NextBytes()लगभग पूर्ण के साथ पूर्णांक नमूना उत्पन्न करने के लिए लागत जितनी बड़ी है Next()। इससे मुझे संदेह है कि वे वास्तव में प्रति बाइट एक नमूना बनाते हैं।

प्रत्येक नमूने में से 3 बाइट्स का उपयोग करके एक बेहतर कार्यान्वयन NextBytes()लगभग एक कारक 3 की गति बढ़ाएगा।

इस दोष के लिए धन्यवाद Random.NextBytes()केवल System.Security.Cryptography.RNGCryptoServiceProvider.GetBytesमेरी मशीन (Win7, Core i3 2600MHz) की तुलना में लगभग 25% तेज है ।

मुझे यकीन है कि अगर किसी ने स्रोत / विघटित बाइट कोड का निरीक्षण किया, तो मुझे मेरे ब्लैक बॉक्स विश्लेषण के साथ और भी अधिक खामियां मिलेंगी।


कोड के नमूने

r.Next(0x55555555) % 2 दृढ़ता से पक्षपाती है:

Random r = new Random();
const int mod = 2;
int[] hist = new int[mod];
for(int i = 0; i < 10000000; i++)
{
    int num = r.Next(0x55555555);
    int num2 = num % 2;
    hist[num2]++;
}
for(int i=0;i<mod;i++)
    Console.WriteLine(hist[i]);

प्रदर्शन:

byte[] bytes=new byte[8*1024];
var cr=new System.Security.Cryptography.RNGCryptoServiceProvider();
Random r=new Random();

// Random.NextBytes
for(int i=0;i<100000;i++)
{
    r.NextBytes(bytes);
}

//One sample per byte
for(int i=0;i<100000;i++)
{   
    for(int j=0;j<bytes.Length;j++)
      bytes[j]=(byte)r.Next();
}

//One sample per 3 bytes
for(int i=0;i<100000;i++)
{
    for(int j=0;j+2<bytes.Length;j+=3)
    {
        int num=r.Next();
        bytes[j+2]=(byte)(num>>16);   
        bytes[j+1]=(byte)(num>>8);
        bytes[j]=(byte)num;
    }
    //Yes I know I'm not handling the last few bytes, but that won't have a noticeable impact on performance
}

//Crypto
for(int i=0;i<100000;i++)
{
    cr.GetBytes(bytes);
}

1
दिलचस्प है, आपकी खोज की पुष्टि कर सकता है: मेरी मशीन पर अगला (1431655765) भी किसी भी बोने के साथ 2/3 देता है। 1431655765 का जादू क्या है? आप इस नंबर पर कैसे पहुंचे?
सिटीकीड

1
@citykid हेक्स या बिट्स के रूप में संख्या को देखें। यह जादू है कि संदिग्ध Randomऊपरी सीमा के साथ 31 बिट पूर्णांक को संख्या में बदलने के लिए उपयोग करने वाले संदिग्ध तरीके से उत्पन्न होता है । मैं विवरण भूल गया, लेकिन यह कुछ ऐसा है randomValue * max / 2^{31}
कोडइन्चोअर्स

1431655765_10 = 10101010101010101010101010101_2
टिम एस।

6
हम्म। तो क्या आप C # के लिए रैंडम का उपयोग करते हैं?
आर्सेन ज़ाहरे

1
पवित्र गाय, Next()यहाँ आपके द्वारा प्रदर्शित की गई वितरण की गैर-एकरूपता , एक बहुत ही शानदार बग है - और अभी भी मौजूद है, 6 साल बाद जब आपने पहली बार अपने निष्कर्ष लिखे। (मैं केवल "दोष" के बजाय "बग" कहता हूं, क्योंकि डॉक्स का दावा है कि "छद्म यादृच्छिक संख्याओं को संख्याओं के परिमित सेट से समान संभावना के साथ चुना जाता है" यह ऐसा नहीं है, और यहां आपका कोड इसे साबित करता है।)
मार्क अमेरी

24

System.Random बहुत अधिक प्रदर्शन है क्योंकि यह क्रिप्टोग्राफिक रूप से सुरक्षित यादृच्छिक संख्या उत्पन्न नहीं करता है।

रैंडम डेटा 1,000,000 बार के साथ 4 बाइट्स की एक बफ़र भरने वाली मेरी मशीन पर एक साधारण परीक्षण, रैंडम के लिए 49 एमएस लेता है, लेकिन RNGCryptoServiceProvider के लिए 2845 एमएस। ध्यान दें कि यदि आप जिस बफर को भर रहे हैं, उसका आकार बढ़ाते हैं, तो अंतर RNGCryptoServiceProvider के लिए ओवरहेड के रूप में कम प्रासंगिक है।


2
वास्तविक परीक्षण के साथ इसे प्रदर्शित करने के लिए धन्यवाद।
लर्नकुरेव

3
आपको लगता है कि यह कठोर है, लेकिन -1 बेंचमार्क के कोड को शामिल किए बिना एक प्रदर्शन बेंचमार्क के परिणाम पोस्ट करने के लिए। यहां तक कि अगर के प्रदर्शन विशेषताओं Randomऔर RNGCryptoServiceProviderनहीं पिछले 8 वर्षों में (जो सभी के लिए मुझे पता है वे है हो सकता है) को बदल दिया है, मैं काफी देखा है एक बेंचमार्क के परिणामों जिसका कोड पर विश्वास नहीं करने स्टैक ओवरफ़्लो पर इस्तेमाल पूरी तरह से टूट मानक सार्वजनिक रूप से उपलब्ध नहीं है।
मार्क अमेरी

21

सबसे स्पष्ट कारणों का पहले ही उल्लेख किया गया है, इसलिए यहां एक अधिक अस्पष्ट है: क्रिप्टोग्राफिक PRNGs को आमतौर पर "वास्तविक" एन्ट्रॉपी के साथ निरंतर रूप से पुनर्प्राप्त करने की आवश्यकता होती है। इस प्रकार, यदि आप अक्सर CPRNG का उपयोग करते हैं, तो आप सिस्टम के एन्ट्रापी पूल को समाप्त कर सकते हैं, जो (CPRNG के कार्यान्वयन के आधार पर) या तो इसे कमजोर करेगा (इस प्रकार एक हमलावर को इसकी भविष्यवाणी करने की अनुमति देता है) या यह भरने की कोशिश करते समय अवरुद्ध हो जाएगा। इसके एंट्रॉपी पूल (इस प्रकार एक DoS हमले के लिए एक हमला वेक्टर बन रहा है)।

किसी भी तरह से, आपका एप्लिकेशन अब अन्य के लिए एक हमला वेक्टर बन गया है, पूरी तरह से असंबंधित अनुप्रयोग जो आपके विपरीत - वास्तव में vitally CPRNG के क्रिप्टोग्राफिक गुणों पर निर्भर करते हैं

यह एक वास्तविक वास्तविक विश्व समस्या है, BTW, जो हेडलेस सर्वरों पर देखी गई है (जो स्वाभाविक रूप से छोटे एंट्रोपी पूल हैं क्योंकि उनके पास लिनक्स में माउस और कीबोर्ड इनपुट जैसे एन्ट्रापी स्रोतों का अभाव है), जहाँ एप्लिकेशन गलत तरीके से /dev/randomकर्नेल CPNNG का सभी प्रकार से उपयोग करते हैं। यादृच्छिक संख्याओं का, जबकि सही व्यवहार एक छोटे बीज मान को पढ़ना /dev/urandomऔर उसका स्वयं का PRNG बीज करना होगा ।


मैं विकिपीडिया लेख और एन्ट्रापी और एन्ट्रापी कमी पर कुछ अन्य इंटरनेट स्रोतों को पढ़ता हूं, और मैं इसे काफी नहीं समझता। जब सिस्टम समय, फ्री बाइट्स की संख्या आदि के साथ यादृच्छिक संख्या जनरेटर को खिलाया जाता है, तो मैं एंट्रोपी पूल को कैसे गिरा सकता हूं? यादृच्छिक संख्या की भविष्यवाणी करने के लिए अन्य लोग इसे हमला वेक्टर के रूप में कैसे उपयोग कर सकते हैं? क्या आप एक आसान उदाहरण प्रदान कर सकते हैं? शायद यह चर्चा ऑफ़लाइन होनी चाहिए। en.wikipedia.org/wiki/Entropy_%28computing%29
Lernkurve

3
सिस्टम समय एक एन्ट्रापी स्रोत नहीं है, क्योंकि यह अनुमानित है। मैं मुफ्त बाइट्स की संख्या के बारे में निश्चित नहीं हूं, लेकिन मुझे संदेह है कि यह उच्च गुणवत्ता वाला एंट्रॉपी स्रोत है। सर्वर को अधिक अनुरोध भेजने से, हमलावर मुक्त बाइट्स की संख्या को कम करने का कारण बन सकता है, जिससे यह आंशिक रूप से नियतात्मक हो जाता है। आप एप्लिकेशन अटैक वेक्टर बन जाते हैं क्योंकि एन्ट्रापी पूल को गिराकर, यह दूसरे, सुरक्षा-महत्वपूर्ण एप्लिकेशन को कम-यादृच्छिक यादृच्छिक संख्याओं का उपयोग करने के लिए मजबूर करता है - या एंट्रोपी स्रोत के फिर से भरने तक प्रतीक्षा करें।
मात्रा_देव

मैं समझता हूं कि यदि किसी के पास 32-बिट बीज के साथ एक छद्म यादृच्छिक जनरेटर खिलाया गया है, तो एक जानवर-बल का हमला अक्सर काफी आसान होगा; यहां तक ​​कि 64-बिट बीज जन्मदिन के हमलों के अधीन हो सकता है। एक बार जब बीज उस से बहुत बड़ा हो जाता है, हालांकि, मैं काफी जोखिम नहीं देखता हूं। यदि किसी के पास एक यादृच्छिक जनरेटर है जो आउटपुट के प्रत्येक बाइट के लिए एक ब्लॉक एन्क्रिप्शन एल्गोरिथ्म के माध्यम से एक 128-बिट राज्य से गुजरता है और फिर नीचे के 8 बिट्स को आउटपुट करता है, तो एक हमलावर भी लगातार आउटपुट बाइट्स के गिग्स के साथ राज्य को कैसे खो सकता है, अनुपस्थित कमजोरियों में एन्क्रिप्शन एल्गोरिथ्म ही?
सुपरकैट

11

यदि आप एक ऑनलाइन कार्ड गेम या लॉटरी का प्रोग्रामिंग कर रहे हैं, तो आप यह सुनिश्चित करना चाहेंगे कि अनुमान लगाना असंभव है। हालांकि, यदि आप उपयोगकर्ताओं को दिखा रहे हैं, तो कहते हैं, प्रदर्शन का एक दिन सुरक्षा की तुलना में अधिक महत्वपूर्ण है।


9

यह कुछ लंबाई पर चर्चा की गई है, लेकिन अंततः, आरएनजी का चयन करते समय प्रदर्शन का मुद्दा एक माध्यमिक विचार है। वहाँ RNGs की एक विशाल सरणी है, और डिब्बाबंद Lehmer LCG कि ज्यादातर प्रणाली RNG होते हैं सबसे अच्छा है और न ही यहां तक ​​कि सबसे तेजी से जरूरी नहीं है। पुराने, धीमी प्रणालियों पर यह एक उत्कृष्ट समझौता था। यह समझौता शायद ही कभी इन दिनों वास्तव में प्रासंगिक है। यह बात वर्तमान समय की प्रणालियों में मुख्य रूप से बनी हुई है क्योंकि A) यह चीज पहले से ही निर्मित है, और इस मामले में 'पहिए को फिर से मजबूत करने' का कोई वास्तविक कारण नहीं है, और B) इसके लिए भारी मात्रा में लोग इसका उपयोग क्या करेंगे, यह है 'काफी है'।

अंतत:, एक आरएनजी का चयन रिस्क / रिवार्ड अनुपात से कम होता है। कुछ अनुप्रयोगों में, उदाहरण के लिए एक वीडियो गेम, जो भी कोई जोखिम नहीं है। एक लेहमर आरएनजी पर्याप्त से अधिक है, और छोटा, संक्षिप्त, तेज, अच्छी तरह से समझा जाता है, और 'बॉक्स में' है।

यदि आवेदन है, उदाहरण के लिए, एक ऑन-लाइन पोकर गेम या लॉटरी जिसमें वास्तविक पुरस्कार शामिल हैं और असली पैसा समीकरण के किसी बिंदु पर खेलने में आता है, तो 'बॉक्स में' लेहमर पर्याप्त नहीं है। 32-बिट संस्करण में, इसका केवल 2 ^ 32 संभव मान्य राज्यों में सबसे पहले चक्र शुरू होता है । इन दिनों, यह एक क्रूर बल के हमले के लिए एक खुला दरवाजा है। इस तरह के एक मामले में, डेवलपर कुछ प्रजातियों के बहुत लंबे समय के आरएनजी की तरह जाना चाहता है , और शायद इसे क्रिप्टोग्राफिक रूप से मजबूत प्रदाता से बीज देगा। यह गति और सुरक्षा के बीच एक अच्छा समझौता देता है। ऐसे मामले में, व्यक्ति किसी चीज़ के लिए मर्सिएन ट्विस्टर या मल्टीपल रिकर्सिव जेनरेटर की तलाश में होगा।

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


3
मुझे लगता है कि आप अपने परिमाण के बारे में गलत हैं; वित्तीय डेटा भेजने की बहुत जल्दी की जरूरत है; यदि आपका ट्रेडिंग एल्गोरिदम प्रतियोगिता की तुलना में तेज़ी से परिणाम 0.1ms प्राप्त कर सकता है, तो आप खरीद / बिक्री / स्टॉप-लॉस / उद्धरण आदेशों की कतार में बेहतर अंत करते हैं। 3 सेकंड एक अनंत काल है। यही कारण है कि व्यापारी पागल कंप्यूटरों में निवेश करते हैं। पिछला उत्तर देखें; Crypt.RNG प्रति नई संख्या केवल 0,0028 एमएस लेता है; 0.0000028 सेकंड, इसलिए आप परिमाण के 9 आदेशों से दूर हैं कि यह कितना प्रसंस्करण लेता है, और यह भी कि कितनी महत्वपूर्ण गति है।
हेनरिक

9

ध्यान दें कि C # में System.Random क्लास को गलत तरीके से कोडित किया गया है, इसलिए इससे बचना चाहिए।

https://connect.microsoft.com/VisualStudio/feedback/details/634761/system-random-serious-bug#tabs


... और ऐसा नहीं लगता कि इसे ठीक करना संभव होगा।
खर्चा

2
ऐसा लगता है कि लिंक नीचे है क्योंकि Microsoft ने "कनेक्ट" किया था।
MSeifert

4

सभी को क्रिप्टोग्राफिक रूप से सुरक्षित रैंडम नंबरों की आवश्यकता नहीं होती है, और वे एक तेज गति वाले प्रैंक से अधिक लाभ उठा सकते हैं। शायद अधिक महत्वपूर्ण बात यह है कि आप System.Random संख्याओं के लिए अनुक्रम को नियंत्रित कर सकते हैं।

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


2

अगर मुझे सुरक्षा की आवश्यकता नहीं है, यानी, मैं केवल एक अपेक्षाकृत अनिश्चित मूल्य चाहता हूं जो क्रिप्टोग्राफिक रूप से मजबूत नहीं है, तो रैंडम का उपयोग करने के लिए बहुत आसान इंटरफ़ेस है।


2

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


1
यदि केवल System.Random या तो किया .. ओह, ठीक है।
user2864740

2

Random एक यादृच्छिक संख्या जनरेटर नहीं है, यह एक नियतात्मक छद्म यादृच्छिक अनुक्रम जनरेटर है, जो ऐतिहासिक कारणों से इसका नाम लेता है।

उपयोग करने का कारण यह System.Randomहै कि यदि आप इन गुणों को चाहते हैं, अर्थात् एक नियतात्मक अनुक्रम, जो एक ही बीज के साथ आरंभीकृत होने पर परिणामों के समान अनुक्रम का उत्पादन करने की गारंटी देता है।

यदि आप इंटरफ़ेस को त्यागने के बिना "यादृच्छिकता" में सुधार करना चाहते हैं, तो आप System.Randomकई तरीकों को ओवरराइड करने से विरासत में प्राप्त कर सकते हैं ।

आप एक निर्धारक अनुक्रम क्यों चाहते हैं

सच्ची यादृच्छिकता के बजाय नियतात्मक अनुक्रम होने का एक कारण यह है कि यह दोहराव योग्य है।

उदाहरण के लिए, यदि आप एक संख्यात्मक सिमुलेशन चला रहे हैं, तो आप अनुक्रम को एक (सच्चे) यादृच्छिक संख्या के साथ शुरू कर सकते हैं, और रिकॉर्ड कर सकते हैं कि किस नंबर का उपयोग किया गया था

फिर, यदि आप सटीक समान सिमुलेशन को दोहराना चाहते हैं , उदाहरण के लिए डिबगिंग उद्देश्यों के लिए, आप रिकॉर्ड किए गए मान के साथ अनुक्रम को प्रारंभ करने के बजाय ऐसा कर सकते हैं ।

आप यह विशेष क्यों चाहते हैं, बहुत अच्छा नहीं, अनुक्रम

एकमात्र कारण जो मैं सोच सकता हूं कि मौजूदा कोड के साथ पीछे की संगतता होगी जो इस वर्ग का उपयोग करता है।

संक्षेप में, यदि आप अपने बाकी कोड को बदले बिना अनुक्रम में सुधार करना चाहते हैं, तो आगे बढ़ें।


1

मैंने एक गेम (iPhone पर क्रिस्टल स्लाइडर्स: यहां ) लिखा था जो नक्शे पर रत्नों (छवियों) की "यादृच्छिक" श्रृंखला डाल देगा और आप मानचित्र को घुमाएंगे कि आप इसे कैसे चाहते हैं और उन्हें चुनें और वे चले गए। - बेज्वेल्ड के समान। मैं रैंडम () का उपयोग कर रहा था, और यह फोन बूट होने के बाद से 100 टन की संख्या के साथ अंकुरित था, एक सुंदर यादृच्छिक बीज।

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

एक प्रयोग के रूप में - और एक अंतिम समाधान के रूप में, मैं 1985 या उसके बाद से उपयोग किए गए यादृच्छिक संख्या जनरेटर पर वापस चला गया - जो कि पूरी तरह से बेहतर है। यह तेज़ है, दोहराए जाने से पहले इसकी अवधि 1.3 * 10 ^ 154 (2 ^ 521) है। मूल एल्गोरिथ्म को 16 बिट संख्या के साथ रखा गया था, लेकिन मैंने इसे 32 बिट संख्या में बदल दिया, और प्रारंभिक बीजारोपण में सुधार किया।

मूल यहाँ है:

ftp://ftp.grnet.gr/pub/lang/algorithms/c/jpl-c/random.c

इन वर्षों में, मैंने हर यादृच्छिक संख्या परीक्षण को फेंक दिया है जो मैं इस पर सोच सकता था, और यह उन सभी को अतीत में ले गया। मुझे उम्मीद नहीं है कि यह एक क्रिप्टोग्राफिक के रूप में किसी भी मूल्य का है, लेकिन यह "रिटर्न * पी ++" के रूप में तेजी से एक संख्या देता है; जब तक यह 521 बिट्स से बाहर नहीं निकलता है, और तब यह नए यादृच्छिक बनाने के लिए बिट्स पर एक त्वरित प्रक्रिया चलाता है।

मैंने एक C # रैपर बनाया - इसे JPLRandom () ने रैंडम () के रूप में एक ही इंटरफ़ेस लागू किया और उन सभी जगहों को बदल दिया, जहाँ मैंने इसे कोड में बुलाया था।

यह अंतर काफी बेहतर था - OMG मैं चकित था - ऐसा कोई तरीका नहीं होना चाहिए जिससे मैं सिर्फ 90 या इससे अधिक रत्नों को एक पैटर्न में देख पाऊं, लेकिन मैंने इसके बाद अपने खेल की एक आपातकालीन रिलीज़ की।

और मैं कभी भी किसी भी चीज के लिए System.Random () का उपयोग कभी नहीं करूंगा। मुझे लगा कि उनके संस्करण को 30 साल पुरानी चीज़ से उड़ा दिया गया है!

-ट्रैडहट गेम्स


3
मेरा पहला अनुमान है कि आपने Randomबहुत बार विश्राम किया है। इसे केवल Nextकई बार उस उदाहरण पर कॉल करते समय बनाया जाना चाहिए । Randomबुरा है, लेकिन बुरा नहीं है । क्या आप इस समस्या को प्रदर्शित करने वाले बीजों की एक जोड़ी के साथ एक नमूना कार्यक्रम पोस्ट कर सकते हैं?
कोडइन्चोअर्स

कोड प्रत्येक स्तर की शुरुआत में एक रैंडम () बनाएगा (लेकिन यह बाद की तुलना में स्तर 1 के साथ एक बड़ी समस्या थी) कोड मोटे तौर पर निम्नानुसार था:
ट्रेडर गेम्स

Rnd = new random ((uint) GameSeed); NextGameSeed = Rnd.Next (2000000000); प्रत्येक स्तर ने एक नए रैंडम का उपयोग किया जो एक नए बीज के साथ बनाया गया था - प्रत्येक स्तर के लिए बीज को बचाया गया था, इसलिए मैं मानचित्र को फिर से बनाने में सक्षम होगा, और यादृच्छिक बीजों के अनुक्रम की भी पुष्टि कर सकता हूं। यह मुझे इस बात की पुष्टि करने की अनुमति देता है कि खेल मानचित्रों की एक वैध श्रृंखला है जिसे हल किया गया है और खेल को फिर से बनाया गया है।
ट्रेडरहट गेम्स

और प्रारंभ में, System.DateTime.Now.Ticks (या 0) के आधार पर रैंडम बनाया गया था, और फिर गेम कॉल को Rnd.Next () के रूप में एक ही कॉल का उपयोग करके चुना गया था। अगर मैं ऐसा नहीं कर सकता, तो रैंडम नंबर जनरेटर के बोने के साथ एक गंभीर समस्या है।
ट्रेडरहट गेम्स

यह मूल प्रश्न का उत्तर नहीं है!
माइक दिनेस्कु

-1

चूंकि System.Random अपने "गलतता" और पूर्वाग्रह के लिए यहाँ धराशायी है, इसलिए मैंने खुद की जाँच की।

वितरण

यह f # कोड दर्शाता है कि यह वास्तव में अच्छा व्यवहार करता है - मेरी औसत मशीन पर:

let r = System.Random()
Seq.init 1000000 (fun _ -> r.Next(0,10))
|> Seq.toList
|> Seq.groupBy id
|> Seq.map (fun (v,ls) -> v, ls |> Seq.length)
|> Seq.sortBy fst
|> Seq.iter (printfn "%A")

(0, 100208)
(1, 99744)
(2, 99929)
(3, 99827)
(4, 100273)
(5, 100280)
(6, 100041)
(7, 100001)
(8, 100175)
(9, 99522)    

फ्रेमवर्क संस्करण, मशीन, ऑपरेटिंग सिस्टम सभी में फर्क हो सकता है। अपनी मशीन पर F # इंटरेक्टिव में कोड दर्ज करें और स्वयं प्रयास करें। सीरपोग्राफी के लिए मैंने पढ़ा

let arr = [| 0uy |]
let rr = System. Security.Cryptography.RandomNumberGenerator.Create()
Seq.init 1000000 (fun _ -> rr.GetBytes(arr); arr.[0])
|> Seq.toList
|> Seq.groupBy id
|> Seq.map (fun (v,ls) -> v, ls |> Seq.length)
|> Seq.sortBy fst
|> Seq.take 10 // show first 10 bytes
|> Seq.iter (printfn "%A")

// distribution of first 10 bytes
(0uy, 3862)
(1uy, 3888)
(2uy, 3921)
(3uy, 3926)
(4uy, 3948)
(5uy, 3889)
(6uy, 3922)
(7uy, 3797)
(8uy, 3861)
(9uy, 3874)

प्रदर्शन

#time

let arr = [| 0uy |]

let r = System.Random()
Seq.init 1000000 (fun _ -> r.NextBytes(arr); arr.[0] |> int64) |> Seq.sum

Real: 00:00:00.204, CPU: 00:00:00.203, GC gen0: 45, gen1: 1, gen2: 1
val it : int64 = 127503467L

let rr = System. Security.Cryptography.RandomNumberGenerator.Create()
Seq.init 1000000 (fun _ -> rr.GetBytes(arr); arr.[0] |> int64) |> Seq.sum

Real: 00:00:00.365, CPU: 00:00:00.359, GC gen0: 44, gen1: 0, gen2: 0
val it : int64 = 127460809L

जो 1: 2 संबंध और क्रिप्टो संस्करण के कुछ हद तक अच्छे व्यवहार का सुझाव देता है।

निष्कर्ष

मुख्य रूप से इसके बहुत अच्छे एपीआई के लिए, कुछ हद तक इसके प्रदर्शन और काफी अच्छे वितरण के लिए, System.Random को पसंद किया जाता है। System.Random भी पुस्तकालय निर्भरता को कम कर सकता है और यदि एक रूपरेखा पोर्ट की जाती है, तो System.Random संभवतः क्रिप्टो वेरिएंट से पहले उपलब्ध होगा।

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