2009-05-31 14 views
19

मैं माइक्रोसॉफ्ट विजुअल सी # 2008 एक्सप्रेस में काम कर रहा हूं।ऐसा क्यों लगता है कि मेरा यादृच्छिक संख्या जेनरेटर सी # में यादृच्छिक नहीं है?

मैं कोड के इस स्निपेट पाया:

public static int RandomNumber(int min, int max) 
    { 
     Random random = new Random(); 

     return random.Next(min, max); 
    } 

समस्या यह है कि मैं इसे 100 से अधिक बार चलाने गया है, और यह मुझे हमेशा एक ही जवाब देने है जब मेरी मिनट = 0 और अधिकतम = 1। मुझे हर बार 0 मिलता है। (मैंने इसे चलाने के लिए एक टेस्ट फ़ंक्शन बनाया - वास्तव में - मुझे हर बार 0 मिल रहा है)। मुझे विश्वास है कि यह एक संयोग है ... क्या यह जांचने या परीक्षण करने के लिए मैं कुछ और कर सकता हूं? (मैंने मिनट = 0 और अधिकतम = 10 और पहले 50ish बार के साथ परीक्षण फिर से चलाया, परिणाम हमेशा "5" था, दूसरा 50ish बार, परिणाम हमेशा "9" था।

?? I ।। वीबी में कुछ और भी अधिक लगातार यादृच्छिक ...

-Adeena

+16

किसी कारण से मुझे लगता है कि "लगातार यादृच्छिक" वास्तव में मजाकिया है। – jcollum

+0

मैं अपनी गर्दन को चिपकाना चाहता हूं, जो कि आपके आवेदन के उद्देश्य के आधार पर है - छद्म-यादृच्छिक का उपयोग करना हमेशा (कम से कम सैद्धांतिक रूप से) आपके एप्लिकेशन को हैक करने योग्य बना देगा। –

उत्तर

47

न्यूनतम = 0 और अधिकतम = 1 के साथ समस्या यह है कि न्यूनतम समावेशी है और अधिकतम अनन्य है। ताकि संयोजन के लिए ही संभव मूल्य 0.

+0

मामलों को और अधिक भ्रमित करने के लिए, दस्तावेज़ बताता है कि maxValue अधिक होना चाहिए minValue के बराबर या बराबर। इसलिए, आप यादृच्छिक रूप से पास कर सकते हैं। अगला (0,0) और यह बिल्कुल यादृच्छिक के समान कार्य करेगा। अगला (0,1) ने सोचा कि निर्दिष्ट संख्या पैरामीटर से मेल खाने वाली कोई संख्या नहीं है। – Kevin

-2

मैं हमेशा यादृच्छिक करें() फ़ंक्शन के साथ शुरू की जरूरत है बस यादृच्छिक करें (कहते हैं) तो अपने यादृच्छिक समारोह चलाने मैं भी निम्न कार्य करें:

Function RandomInt(ByVal lower As Integer, ByVal upper As Integer) As Integer 
    Return CInt(Int((upper - lower + 1) * Rnd() + lower)) 
End Function 

उम्मीद है कि यह मदद करता है! :)

+0

यह क्यों चिह्नित किया गया है? मैं लगातार इस से यादृच्छिक संख्या प्राप्त करता हूं ... – Jason

+1

क्योंकि हम सी # – TheSoftwareJedi

+1

पर चर्चा कर रहे हैं क्या आप असली हैं? क्या आप जानते हैं कि मुझे वीबी सवालों के सी # उत्तरों कितने बार मिले हैं और यह पता लगाने में सक्षम था कि मैं क्या गलत कर रहा था? यह अवधारणा है, आदमी, वाक्यविन्यास नहीं ... jeezz ... – Jason

32
random = new Random(); 

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

+5

रैंडम() कन्स्ट्रक्टर के लिए प्रलेखन इस समस्या का वर्णन लगभग क्रियात्मक है: http://msdn.microsoft.com/en-us/library/h343ddh9.aspx – las3rjock

7

अगला की अधिभार() देता है यही कारण है:

एक 32-बिट से पूर्णांक अधिक से अधिक या MINVALUE के बराबर है और कम पर हस्ताक्षर किए MAXVALUE से; यानी, वापसी मूल्यों की सीमा में minValue शामिल है लेकिन MaxValue नहीं है। यदि minValue maxValue के बराबर है, minValue वापस आ गया है।

0 लौटने के लिए यह एकमात्र संभावित मूल्य है। शायद आप यादृच्छिक चाहते हैं। अगला डबल(), जो 0 और 1.

18

के बीच दोहराएगा, अगला के लिए एक रैपर विधि न बनाएं। यह रैंडम क्लास का एक नया उदाहरण बनाने वाले चक्रों को बर्बाद करता है। बस एक ही प्रयोग करें!

Random myRand = new Random(); 

for(int i = 0; i < 10; i++) 
{ 
    Console.WriteLine(myRand.Next(0, 10).ToString()); 
} 

आपको दस यादृच्छिक मूल्य देना चाहिए।

जैसा कि कहा गया है - यादृच्छिक छद्म-यादृच्छिक है (जैसा कि सभी कार्यान्वयन हैं), और यदि आप एक ही बीज के साथ 100 उदाहरण बनाते हैं, तो आपको एक ही परिणाम के 100 उदाहरण मिलेंगे। सुनिश्चित करें कि आप कक्षा का पुन: उपयोग कर रहे हैं।

साथ ही, जैसा कि लोगों ने कहा है, सावधान रहें कि मिनवैल्यू समावेशी है और मैक्सवेल्यू अनन्य है। आप जो चाहते हैं उसके लिए, myRand.Next (0, 2) करें।

+0

इसे 10 या अधिक बार करना सिर्फ परीक्षण था ... मुझे एहसास नहीं हुआ कि "अधिकतम" अनन्य था। – adeena

+1

कभी-कभी आप रैंडम के लिए एक रैपर विधि (या अधिकतर एक रैपर क्लास) चाहते हैं ताकि आप इसे नकल कर सकें। – BlackWasp

+0

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

3

0-1 अंक के अलावा अन्य उत्तरों में पहले से ही उल्लेख किया गया है, तो आपकी समस्या एक असली है जब आप 0-10 रेंज की तलाश में हैं और पंक्ति में 50 बार समान परिणाम प्राप्त करते हैं।

new Random() टाइमर (वर्तमान सेकेंड) से शुरू किए गए बीज के साथ एक यादृच्छिक संख्या वापस करना है, लेकिन जाहिर है कि आप इस कोड को 50 बार एक बार कॉल कर रहे हैं। MSDN सुझाव देता है: "प्रदर्शन को बेहतर बनाने के लिए, एक यादृच्छिक संख्या उत्पन्न करने के लिए बार-बार एक नया रैंडम बनाने के बजाय, समय के साथ कई यादृच्छिक संख्याएं उत्पन्न करने के लिए एक यादृच्छिक बनाएं।" यदि आप विधि के बाहर एक बार अपना यादृच्छिक जनरेटर बनाते हैं, तो उसे आपकी "गैर-यादृच्छिकता" समस्या को ठीक करना चाहिए और साथ ही प्रदर्शन में सुधार करना चाहिए।

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

1

दूसरों के रूप में उल्लेख किया है, रैंडम प्रति सेकंड कई बार बनाया जा रहा बीज के रूप में ही दूसरे का उपयोग करता है, तो मैं अपने पाश बाहर रैंडम निर्माता डाल चाहते हैं, और, एक पैरामीटर के रूप में यह पारित इस तरह:

public static int RandomNumber(Random random, int min, int max) 
{ 
    return random.Next(min, max); 
} 

अन्य लोगों द्वारा उल्लिखित अनुसार, अधिकतम अनन्य है, इसलिए यदि आप 0 या 1 चाहते हैं, तो आपको [0,2] अपने [मिनट, अधिकतम], या कुछ बड़े अधिकतम के रूप में उपयोग करना चाहिए और फिर बाइनरी करना चाहिए और फिर 1.

public static int RandomOneOrZero(Random random) 
{ 
    return random.Next(0, int.MaxValue) & 1; 
} 
+1

रैंडम ऑब्जेक्ट को स्थैतिक चर के रूप में भी घोषित किया जा सकता है, इसलिए इसे हर बार विधि में पारित करने की आवश्यकता नहीं है। – Whatsit

+0

मुझे RandomOneOrZero विधि पसंद है। क्या आप इसका उपयोग कर रहे हैं क्योंकि आप इसे [0,2] या किसी अन्य कारण से अधिक यादृच्छिक मानते हैं? –

+0

@ मैट: यह समय की यादृच्छिकता की एक ही राशि होगी। मैंने बस इसे अपने सिर के ऊपर से मार दिया। @Whatsit: अच्छा बिंदु। मुझे यकीन नहीं था कि उसका उपयोग मामला क्या था, इसलिए मैंने बस अनुमान लगाया। एक स्थैतिक या आवृत्ति चर शायद अधिक उपयुक्त होगा। –

6

आप हमेशा 0 प्राप्त कर रहे हैं क्योंकि Random.Next पूर्णांक देता है। आप इस तरह, अपने रैंडम उदाहरण पुनः उपयोग करना चाहिए Random.NextDouble कॉल करने के लिए है, जो भी 0 और 1. बीच की एक संख्या वापस आ जाएगी की जरूरत है,: आप क्रिप्टोग्राफी द्वारा सुरक्षित यादृच्छिक संख्या चाहते हैं

[ThreadStatic] 
static Random random; 
public static Random Random { 
    get { 
     if (random == null) random = new Random(); 
     return random; 
    } 
} 
public static int RandomInteger(int min, int max) 
{ 
    return Random.Next(min, max); 
} 
public static double RandomDouble() //Between 0 and 1 
{ 
    return Random.NextDouble(); 
} 

, RNGCryptoServiceProvider वर्ग का उपयोग करें; देख this article

संपादित करें: थ्रेड सुरक्षा

+2

-1 क्योंकि यह कोड खतरनाक रूप से गलत है। यादृच्छिक थ्रेड-सुरक्षित नहीं है और आप किसी भी लॉकिंग या प्रति-थ्रेड आवृत्ति प्रदान किए बिना साझा किए गए इंस्टेंस तक पहुंच रहे हैं। –

+0

फिक्स्ड; सलाह के लिए धन्यवाद – SLaks

+0

कूल, -1 हटा दिया गया। –

1

यह कोई जवाब का एक परिशिष्ट है, के रूप में इस विशिष्ट सवाल का जवाब है सीमा होना चाहिए (0, 2) (1 0) नहीं।

हालांकि, यदि आप एक स्थिर रैपर विधि का उपयोग करना चाहते हैं, तो आपको याद रखना चाहिए कि Random थ्रेड-सुरक्षित नहीं है, इसलिए आपको या तो अपनी सिंक्रनाइज़ेशन तंत्र प्रदान करने या प्रति-थ्रेड आवृत्ति प्रदान करने की आवश्यकता है।

public static class ThreadSafeRandom 
{ 
    private static readonly Random seed = new Random(); 

    [ThreadStatic] 
    private static Random random; 

    public static int Next(int min, int max) 
    { 
     if (random == null) 
     { 
      lock (seed) 
      { 
       random = new Random(seed.Next()); 
      } 
     } 

     return random.Next(min, max); 
    } 

    // etc. for other members 
} 
+0

पर्यावरण। टिककाउंट (डिफ़ॉल्ट बीज) बीज के लिए पर्याप्त है; अलग बीज उदाहरण बनाने में कोई बात नहीं है। – SLaks

+1

@SLaks - यदि आप पर्यावरण पर भरोसा करते हैं। तोककाउंट तो आप संभवतः प्रत्येक प्रति-थ्रेड इंस्टेंस के लिए एक ही बीज प्राप्त करेंगे, जिससे उन्हें छद्म-यादृच्छिक मानों का एक ही अनुक्रम उत्पन्न होगा। मुझे बहुत संदेह है कि यह वही है जो आप चाहते हैं। उन्हें एक स्पष्ट रूप से अलग बीज देकर, आप इस व्यवहार पैटर्न को होने से रोकते हैं। –

0

कई पोस्टर ने कहा है कि यादृच्छिक() सिस्टम घड़ी और किसी भी अन्य पर वर्तमान दूसरे के आधार पर एक बीज का उपयोग करता है: यह एक बड़े पैमाने पर गैर-अवरुद्ध कार्यान्वयन जो प्रत्येक प्रति-धागा जनरेटर बीज के एक जनरेटर का उपयोग करता है उसी सेकेंड में बनाए गए रैंडम का उदाहरण एक ही बीज होगा। यह गलत है। रैंडम के पैरामीटर रहित कन्स्ट्रक्टर के लिए बीज टिक गणना के बाद टिक गिनती, या मिलीसेकंड की संख्या पर आधारित है। यह मान लगभग 15 मिलीसेकंड के अधिकांश सिस्टम पर अपडेट किया जाता है लेकिन यह हार्डवेयर और सिस्टम सेटिंग्स के आधार पर भिन्न हो सकता है।

0

मैं सिर्फ वर्तमान दिनांक मिलीसेकेंड के अंतिम दो अंक लेकर यादृच्छिक संख्या उत्पन्न करने के लिए एक बहुत ही सरल है, लेकिन प्रभावी रास्ता मिल गया:

int seed = Convert.ToInt32(DateTime.Now.Millisecond.ToString().Substring(1, 2)); 
    int cnr = new Random(seed).Next(100); 

यह कच्चे तेल की है, लेकिन यह काम करता है! :-)

बेशक यह सांख्यिकीय रूप से प्रत्येक सौ बार समान संख्या उत्पन्न करेगा। वैकल्पिक रूप से, आप सभी तीन अंक ले सकते हैं या सेकेंड या अन्य जैसे अन्य डेटाटाइम मानों के साथ संयोजित कर सकते हैं।

1

आप "random.ext (min, max)" पंक्ति को गलत समझ रहे हैं।"न्यूनतम" सबसे कम संख्या के स्थान पर यादृच्छिक रूप से उत्पन्न होने की अनुमति है। जबकि "अधिकतम" सबसे कम संख्या के स्थान पर उत्पन्न होने की अनुमति नहीं है, यह तैयार होने की अनुमति देने वाली सबसे बड़ी संख्या के स्थान पर नहीं है। तो जब लाइन यादृच्छिक है। अगला (0, 1) आप मूल रूप से केवल 0 को खींचे जाने की अनुमति दे रहे हैं।

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