2011-11-29 15 views
11

संभव डुप्लिकेट बनाना:
Why does it appear that my random number generator isn't random in C#?
How can I generate truly (not pseudo) random numbers with C#?एक सच्चे यादृच्छिक

मैं एक पासा खेल है जहाँ पासा एक प्रतिशतक, 1-100 पर आधारित है बना लिया है।

public static void Roll() 
{ 
    Random rand = new Random((int)DateTime.Now.Ticks); 
    return rand.Next(1, 100); 
} 

लेकिन मुझे ऐसा नहीं लगता कि यह वर्तमान समय के आधार पर एक वास्तविक यादृच्छिक है।

अगर मैं

for (int i = 0; i < 5; i++) 
{ 
    Console.WriteLine("#" + i + " " + Roll()); 
} 

कर वे सब, एक ही मान होगा क्योंकि DateTime.Now.Ticks परिवर्तन नहीं किया है, यह एक ही नंबर वरीयता प्राप्त।

मैं सोच रहा था मैं एक नया यादृच्छिक बीज उत्पन्न कर सकता है, तो बीज वर्तमान समय की वजह से ही था, लेकिन यह एक ईमानदार "फिर से रोल"

क्या मैं कोशिश करने के लिए क्या करना चाहिए का मन नहीं करता और वास्तविक/ईमानदार पासा रोल के करीब एक प्रतिलिपि बनाएँ? क्या मुझे रोल बनाने के लिए RNGCryptoServiceProvider कक्षा का उपयोग करना चाहिए? इसलिए यदि आपको लगता है कि अधिभार के साथ एक Random एक 16ms "स्लॉट" वे सभी एक ही मूल्य के साथ वरीयता प्राप्त हो जाएगा के अंतर्गत कई बार बना सकते हैं और इसलिए आप उसी क्रम मिल जाएगा

+0

मैं इसे पढ़ने का सुझाव देता हूं: http://csharpindepth.com/Articles/Chapter12/Random.aspx – Oded

+1

SO पर इस प्रश्न के कई भिन्नताएं हैं। यहां उनमें से एक है ... [ऐसा क्यों लगता है कि मेरा यादृच्छिक संख्या जेनरेटर सी # में यादृच्छिक नहीं है?] (Http://stackoverflow.com/questions/932520/why-does-it-appear-that-my- यादृच्छिक-संख्या-जनरेटर-isnt-random-in-c) ... डुप्ली के रूप में चिह्नित करना। (आपके पास प्रत्येक रोल के लिए एक नए रैंडम की बजाय आपके रैंडम का केवल एक स्थिर उदाहरण होना चाहिए) – spender

+0

"असली यादृच्छिक" क्या है? – Sandy

उत्तर

10

DateTime.Now.Ticks केवल approximately 16ms के एक संकल्प है।

अपने पाश के बाहर अपने Random प्रारंभ, इसलिए किसी एक Random अनुक्रम का उत्पादन किया है, बल्कि यह पाश के भीतर हर बार बनाने की तुलना में जो Randoms में परिणाम सकता है एक ही मूल्य के साथ वरीयता प्राप्त किया जा रहा है और इसलिए उसी क्रम का उत्पादन।

अद्यतन

मेरे पिछले मुद्दा यह है कि डिफ़ॉल्ट निर्माता सीपीयू टिक साथ Random प्रारंभ गलत थी, तो डिफ़ॉल्ट निर्माता वास्तव में Environment.TickCount जो है का उपयोग करता है:

एक 32-बिट पर हस्ताक्षर किए पूर्णांक राशि युक्त मिलीसेकंड में समय है जो कंप्यूटर के आखिरी बार शुरू होने के बाद से पारित हो गया है।

जो अभी भी कम संकल्प है। यदि आप त्वरित उत्तराधिकार में Random के कई उदाहरण बनाते हैं, तो उन्हें आसानी से एक ही समय स्लॉट के भीतर बनाया जा सकता है और इसलिए एक ही बीज मान है, और समान अनुक्रम बनाते हैं। Random का एक उदाहरण बनाएं और इसका उपयोग करें।

अद्यतन

अपनी टिप्पणी के लिए आगे

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

https://codeblog.jonskeet.uk/2009/11/04/revisiting-randomness

+0

डिफ़ॉल्ट यादृच्छिक() बीज वर्तमान सीपीयू टिक है? – Kyle

+0

@ केली मैंने अपना जवाब अपडेट किया है। –

+0

धन्यवाद। ^।^मुझे नहीं पता कि मुझे अभी भी यादृच्छिक उपयोग करना चाहिए क्योंकि मैं धागे का उपयोग करता हूं। मैंने यादृच्छिक पढ़ा है धागा सुरक्षित नहीं है। अगर मैं फ़ंक्शन के बाहर यादृच्छिक() प्रारंभ करता हूं तो मुझे लगता है कि इससे समस्याएं पैदा होंगी। – Kyle

4

आपको अपने रोल फ़ंक्शन के बाहर केवल एक बार अपनी यादृच्छिक कक्षा बनाना चाहिए और इसे एक अद्वितीय मूल्य के साथ बीज बनाना चाहिए।

हर बार जब आप रोल कहते हैं तो आप अपने यादृच्छिक पुनर्निर्माण कर रहे हैं जो 'यादृच्छिक संख्या नहीं' का कारण बनता है।

+0

इसे पहचानने के लिए धन्यवाद। ^^ – Kyle

0

मुझे लगता है कि आप Roll() विधि को इतनी जल्दी कॉल कर रहे हैं कि Now.Ticks समान है?

इस पर जाने का सबसे आसान तरीका एक नया Random() उदाहरण बनाने के बजाय होगा जब आप Roll()Random() का एक उदाहरण रखने के लिए एक स्थिर चर बनाते हैं।

+0

हां यह मुद्दा था। सहायता के लिए धनयवाद। – Kyle

1

क्या मुझे इसके बजाय रोल उत्पन्न करने के लिए RNGCryptoServiceProvider क्लास का उपयोग करना चाहिए?

यदि यह धन के साथ एक गंभीर खेल है तो हां।

+1

पैसा हिस्सेदारी पर नहीं है। मैं यथार्थवादी रोल दोहराना चाहता था। तो जब लोग इसे खेलते हैं तो ऐसा लगता है कि वे वास्तव में एक पासा रोलिंग कर रहे हैं। – Kyle

+0

यादृच्छिक पर्याप्त से अधिक होगा, लेकिन बीजिंग के बारे में अन्य जवाब पढ़ें। –

+0

मैं इसका उपयोग करूँगा क्योंकि यादृच्छिक() धागा सुरक्षित नहीं है। मैंने आज यादृच्छिक() के बारे में कुछ और बातें सीखी हैं। – Kyle

0

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

जब आप इसे नीचे प्राप्त करते हैं, तो कंप्यूटर पर वास्तविक यादृच्छिक संख्या पीढ़ी जैसी कोई चीज नहीं है, केवल बीज पर आधारित छद्म यादृच्छिक अनुक्रम। हालांकि, मनुष्य यादृच्छिकता की पहचान करने में भयानक हैं, इसलिए यह आमतौर पर ठीक है।

+0

lol @ इंसान यादृच्छिकता की पहचान करते हैं। सहायता के लिए धन्यवाद। ^^ – Kyle

7

छद्म यादृच्छिक Random की तरह संख्या जनरेटर केवल एक बार, तो वरीयता प्राप्त किया जाना चाहिए:

private static Random _rand = new Random(); 
public static int Roll() 
{ 
    return _rand.Next(1, 100); 
} 

(ध्यान दें मैं वापसी मान int बजाय void बनाया; सवाल परिणाम में उद्धृत Roll समारोह एक वाक्यविन्यास त्रुटि में।)

लेकिन आपका शीर्षक "एक वास्तविक यादृच्छिक बनाना" कहता है। Random आपके लिए ऐसा नहीं करेगा, यह pseudo-random संख्या जनरेटर है, जिसका अर्थ है कि यह निर्धारक है, भविष्यवाणी करना मुश्किल है कि क्या आप बीज को नहीं जानते हैं। आमतौर पर यह अधिकांश उद्देश्यों के लिए पर्याप्त है, लेकिन यदि आपको वास्तविक यादृच्छिकता की आवश्यकता है, तो आपको एंट्रॉपी स्रोत की आवश्यकता है। http://random.org एक लोकप्रिय है।

+1

इसका उल्लेख करने के लिए धन्यवाद। मैं स्मृति पर आधारित धागे में इसे फिर से लिख रहा था यह एक वाक्यविन्यास त्रुटि थी। सहायता के लिए धनयवाद। – Kyle

संबंधित मुद्दे