2011-03-10 19 views
17

इस विधि वापसी करता है पर विचार करें:क्यों Random.Next() हमेशा एक ही नंबर

private static int GenerateRandomNumber(int seed, int max) 
{ 
    return new Random(seed).Next(max); 
} 

मेरी मशीन पर, यह पाश को क्रियान्वित 1500 पुनरावृत्तियों के माध्यम से एक ही नंबर पैदावार:

for (int i = 0; i < 1501; i++) 
      { 
       int random = GenerateRandomNumber(100000000, 999999999); 
       Console.WriteLine(random.ToString()); 
       Console.ReadKey(); 
      } 

मैं 145156561, प्रत्येक एकल पुनरावृत्ति के लिए।

मैं एक दबाने मुद्दा नहीं है, मैं इस व्यवहार के बारे में बस उत्सुक था क्योंकि .Next (अधिकतम) कहते हैं, "एक गैर नकारात्मक यादृच्छिक संख्या निर्दिष्ट अधिकतम से कम देता है। शायद मैं कुछ बुनियादी समझ नहीं कर रहा हूँ।

+7

यह वही है जो 'बीज' का अर्थ है। – SLaks

+1

मुझे अब मिल गया है। मुझे लगता है कि कम से कम इंटेलिजेंस के माध्यम से प्रस्तुत किया गया तरीका स्पष्ट नहीं है। – kd7

उत्तर

37

आप हमेशा एक ही बीज के साथ एक नया उदाहरण बोने कर रहे हैं, और फिर पहली अधिकतम हथियाने। एक बीज का उपयोग करके आप एक ही परिणाम की गारंटी कर रहे हैं।

आप एक स्थिर, यादृच्छिक करना चाहते हैं संख्या पीढ़ी जो अलग-अलग परिणाम देती है, आपको इसे थोड़ा सा करना चाहिए। हालांकि, चूंकि रैंडम थ्रेडसेफ नहीं है, इसलिए इसे स्थिर रूप से उपयोग किए जाने पर कुछ सिंक्रनाइज़ेशन की आवश्यकता होती है। ike:

private static Random random; 
private static object syncObj = new object(); 
private static void InitRandomNumber(int seed) 
{ 
    random = new Random(seed); 
} 
private static int GenerateRandomNumber(int max) 
{ 
    lock(syncObj) 
    { 
     if (random == null) 
      random = new Random(); // Or exception... 
     return random.Next(max); 
    } 
} 
+1

यदि आपको कई यादृच्छिक संख्याओं की आवश्यकता है तो यह शायद पीसी को मार देगा :-) यदि आप सी # 4.0 के अंतर्गत हैं, तो कम से कम स्पिनलॉक का उपयोग करें या रैंडम ऑब्जेक्ट थ्रेड स्टेटिक बनाएं। – xanatos

+0

आपको डबल-चेक लॉकिंग का उपयोग करना चाहिए। – SLaks

+1

@Slaks: वास्तव में मदद नहीं करता है - Random.Next() थ्रेड सुरक्षित नहीं है, इसलिए आपको हमेशा लॉक की आवश्यकता होती है। यहां लॉक आलसी तत्कालता के लिए नहीं है ... –

6

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

यादृच्छिक संख्या पीढ़ी वास्तव में यादृच्छिक नहीं है, अधिक जानकारी के लिए this Wikipedia entry देखें।

3

छद्म-यादृच्छिक संख्या जेनरेटर आम तौर पर बीज चुनकर काम करता है, और फिर उस बीज के आधार पर एक निर्धारिक अनुक्रम उत्पन्न करता है। हर बार एक ही बीज का चयन, आप एक ही अनुक्रम उत्पन्न करते हैं।

.NET में "केवल" 2^32 विभिन्न यादृच्छिक अनुक्रम हैं।

2

सुनिश्चित नहीं है कि आंतरिक कैसे काम करते हैं .. इसके लिए विकी की जांच करें, लेकिन यह बहुत आसान है।

public class MathCalculations 
{ 
    private Random rnd = new Random(); 

    public Int32 getRandom(Int32 iMin, Int32 iMax) 
    { 
     return rnd.Next(iMin, iMax); 
    } 
} 

public class Main 
{ 
    MathCalculations mathCalculations = new MathCalculations(); 
    for (int i = 0; i < 6; i++) 
    { 
     getRandom(0,1000); 
    } 
} 

नंबर_1, नंबर_2, Number3, Number4, Number5, Number6 उत्पन्न होगा (1 बीज, कई नंबरों की 1 अनुक्रम, यादृच्छिक * वास्तव में नहीं है, लेकिन लगभग *।)

अगर आप फिर भी ऐसा करते हैं:

public class MathCalculations 
{ 
    public Int32 getRandom(Int32 iMin, Int32 iMax) 
    { 
     Random rnd = new Random(); 
     return rnd.Next(iMin, iMax); 
    } 
} 

public class Main 
{ 
    MathCalculations mathCalculations = new MathCalculations(); 
    for (int i = 0; i < 6; i++) 
    { 
     getRandom(0,1000); 
    } 
} 

अब आप .. (1 बीज, कई संख्या के 6 बराबर दृश्यों, हमेशा एक बराबर अनुक्रम से ही शुरू नंबर लेने) संख्या 1, संख्या 1, संख्या 1, संख्या 1, संख्या 1, संख्या 1 मिल जाएगा कुछ बिंदु संख्या 1 पर अलग होगा, क्योंकि बीज समय के साथ बदलता है .. लेकिन आपको कुछ टीआई इंतजार करना होगा इसके लिए, फिर भी, आप अनुक्रम से नंबर 2 कभी नहीं चुनते हैं।

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

यह सुनिश्चित नहीं है कि यह यादृच्छिक जनरेटर के अंतर्निहित तरीकों से तकनीकी रूप से सही है, लेकिन इस तरह यह व्यवहार करता है।

7

डिल्बर्ट 2001 में एक ही समस्या का सामना किया:

http://dilbert.com/strips/comic/2001-10-25/

संयोग?

मुझे ऐसा नहीं लगता है।

और random.org इससे सहमत हैं: http://www.random.org/analysis/

+4

SO में वास्तव में हास्य के लिए कोई जगह नहीं है, वास्तव में? – dbrin

+0

हालांकि यह लिंक प्रश्न का उत्तर दे सकता है, लेकिन यहां उत्तर के आवश्यक हिस्सों को शामिल करना बेहतर है और संदर्भ के लिए लिंक प्रदान करना बेहतर है। लिंक किए गए पृष्ठ में परिवर्तन होने पर लिंक-केवल उत्तर अमान्य हो सकते हैं। - [समीक्षा से] (/ समीक्षा/कम गुणवत्ता वाली पोस्ट/18480 9 28) – jv42

+0

सभी उचित सम्मान @ jv42 के साथ, लेकिन मैं कॉमिक स्ट्रिप सामग्री को पुन: पेश नहीं कर सकता, इसलिए इस मामले में एक लिंक उचित है। – dbrin

0

घटना में है कि किसी को भी एक "त्वरित और गंदी" "समाधान" की तलाश में है (और मैं सावधानी के साथ उस शब्द का उपयोग) तो यह सबसे अधिक के लिए पर्याप्त होगा।

int secondsSinceMidnight = Convert.ToInt32(DateTime.Now.Subtract(DateTime.Today).TotalSeconds); 
Random rand = new Random(secondsSinceMidnight); 
var usuallyRandomId = rand.Next(); 

कृपया आमतौर पर यादृच्छिक रूप से मेरा उपयोग ध्यान दें। मैं मानता हूं कि उत्तर के रूप में चिह्नित आइटम यह करने का एक और सही तरीका है।

1

सभी को सलाम, वैसे यह मुझे पागल भी चला गया। उत्तर सीधा है। यादृच्छिक उत्पन्न करने से पहले बीज बदलें।

उदाहरण: मैं 10

Random rnd = new Random(DateTime.Now.Seconds); 
int random_number = rnd.Next(10); 

को 1 के बीच यादृच्छिक संख्या उत्पन्न यह एक पाश अंदर रखो और यह तीन बार चलाना चाहते हैं। यह नीचे यादृच्छिक संख्या देगा 10.

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