अब तक के सभी उत्तर गणितीय रूप से गलत हैं। रिटर्निंग rand() % N
एक समान रूप से रेंज में एक नंबर नहीं देता है [0, N)
जब तक N
कि अंतराल की लंबाई को विभाजित नहीं करता है जिसमें rand()
रिटर्न (यानी 2 की शक्ति) है। इसके अलावा, किसी को भी पता नहीं है कि क्या rand()
स्वतंत्र हैं: यह संभव है कि वे जाएं 0, 1, 2, ...
, जो एक समान हो लेकिन बहुत यादृच्छिक न हो। एकमात्र धारणा जिसे बनाना उचित लगता है, वह यह है कि rand()
एक पॉइसन वितरण होता है: समान आकार के कोई भी दो नॉनओवरलैपिंग सबइंटरवल समान रूप से संभावित और स्वतंत्र होते हैं। मूल्यों के एक निश्चित सेट के लिए, यह एक समान वितरण का तात्पर्य करता है और यह भी सुनिश्चित करता है कि मूल्य rand()
अच्छी तरह से बिखरे हुए हैं।
इसका मतलब यह है कि सीमा को बदलने का एकमात्र सही तरीका rand()
इसे बक्से में विभाजित करना है; उदाहरण के लिए, यदि RAND_MAX == 11
और आप एक सीमा चाहते हैं 1..6
, तो आपको {0,1}
1, {2,3}
2, और इसी तरह से असाइन करना चाहिए । ये असमान हैं, समान रूप से अंतराल हैं और इस प्रकार समान रूप से और स्वतंत्र रूप से वितरित किए जाते हैं।
फ्लोटिंग-पॉइंट डिवीजन का उपयोग करने का सुझाव गणितीय रूप से प्रशंसनीय है, लेकिन सिद्धांत रूप में गोल मुद्दों से ग्रस्त है। शायद double
यह काम करने के लिए उच्च-पर्याप्त परिशुद्धता है; शायद नहीं। मैं नहीं जानता और मुझे इसका पता नहीं लगाना है; किसी भी मामले में, जवाब प्रणाली पर निर्भर है।
सही तरीका पूर्णांक अंकगणित का उपयोग करना है। यही है, आप निम्नलिखित की तरह कुछ चाहते हैं:
#include <stdlib.h> // For random(), RAND_MAX
// Assumes 0 <= max <= RAND_MAX
// Returns in the closed interval [0, max]
long random_at_most(long max) {
unsigned long
// max <= RAND_MAX < ULONG_MAX, so this is okay.
num_bins = (unsigned long) max + 1,
num_rand = (unsigned long) RAND_MAX + 1,
bin_size = num_rand / num_bins,
defect = num_rand % num_bins;
long x;
do {
x = random();
}
// This is carefully written not to overflow
while (num_rand - defect <= (unsigned long)x);
// Truncated division is intentional
return x/bin_size;
}
लूप पूरी तरह से समान वितरण प्राप्त करने के लिए आवश्यक है। उदाहरण के लिए, यदि आपको 0 से 2 तक रैंडम नंबर दिए गए हैं और आप केवल 0 से 1 तक ही चाहते हैं, तो आप बस तब तक खींचते रहेंगे जब तक आपको 2 नहीं मिलते; यह जांचना मुश्किल नहीं है कि यह समान संभावना के साथ 0 या 1 देता है। इस पद्धति का वर्णन उस लिंक में भी किया गया है, जो उनके उत्तर में दिया गया था, हालांकि अलग तरीके से कोडित किया गया था। मैं इसके random()
बजाय उपयोग कर रहा हूं rand()
क्योंकि इसका बेहतर वितरण है (जैसा कि मैन पेज के लिए नोट किया गया है rand()
)।
यदि आप डिफ़ॉल्ट रेंज के बाहर यादृच्छिक मान प्राप्त करना चाहते हैं [0, RAND_MAX]
, तो आपको कुछ मुश्किल करना होगा। शायद सबसे समीचीन एक समारोह को परिभाषित करने के लिए है random_extended()
कि खींचती n
बिट्स (का उपयोग कर random_at_most()
में) और रिटर्न [0, 2**n)
, और फिर लागू random_at_most()
साथ random_extended()
के स्थान पर random()
(और 2**n - 1
के स्थान पर RAND_MAX
) की तुलना में कम एक यादृच्छिक मूल्य खींचने के लिए 2**n
, यह सोचते हैं आप एक संख्यात्मक प्रकार है कि इस तरह के पकड़ कर सकते हैं एक कीमत। अंत में, निस्संदेह, आप नकारात्मक मूल्यों सहित, [min, max]
उपयोग करने में मान प्राप्त कर सकते हैं min + random_at_most(max - min)
।