मार्क का समाधान (स्वीकृत समाधान) लगभग पूर्ण है।
int x;
do {
x = rand();
} while (x >= (RAND_MAX - RAND_MAX % n));
x %= n;
संपादित करें 25 मार्च 16 को 23:16 पर
मार्क अमेरी 39k21170211
हालाँकि, यह एक चेतावनी है जो किसी भी परिदृश्य में परिणामों के 1 वैध सेट को छोड़ देता है, जहां RAND_MAX
( RM
) बहुविध N
(जहाँ N
= संभव वैध परिणामों की संख्या ) से कई गुना कम है।
यानी, जब 'मानों की गणना छोड़ दी गई' ( D
) के बराबर है N
, तो वे वास्तव में एक वैध सेट ( V)
, एक अवैध सेट नहीं है! I
)।
क्या इस का कारण बनता है कुछ बिंदु मार्क के बीच अंतर की दृष्टि खो देता है N
और Rand_Max
।
N
एक ऐसा सेट है, जिसके वैध सदस्य केवल पॉजिटिव इंटेगर शामिल होते हैं, क्योंकि इसमें उन प्रतिक्रियाओं की गिनती होती है जो मान्य होगी। (उदाहरण: सेट N
= {1, 2, 3, ... n }
)
Rand_max
हालाँकि, एक सेट है जो (हमारे उद्देश्यों के लिए परिभाषित किया गया है) में किसी भी प्रकार के गैर-नकारात्मक पूर्णांक शामिल हैं।
यह सबसे सामान्य रूप में है, जो यहां परिभाषित किया गया Rand Max
है वह सभी मान्य परिणामों का सेट है, जिसमें सैद्धांतिक रूप से नकारात्मक संख्या या गैर-संख्यात्मक मान शामिल हो सकते हैं।
इसलिए Rand_Max
बेहतर "संभावित प्रतिक्रियाओं" के सेट के रूप में परिभाषित किया गया है।
हालांकि N
मान्य प्रतिक्रियाओं के सेट के भीतर मूल्यों की गिनती के खिलाफ काम करता है, इसलिए यहां तक कि हमारे विशिष्ट मामले में परिभाषित होने के बावजूद, Rand_Max
इसमें शामिल कुल संख्या की तुलना में एक मूल्य कम होगा।
मार्क के समाधान का उपयोग करते हुए, मानों को छोड़ दिया जाता है जब: X => RM - RM% N
EG:
Ran Max Value (RM) = 255
Valid Outcome (N) = 4
When X => 252, Discarded values for X are: 252, 253, 254, 255
So, if Random Value Selected (X) = {252, 253, 254, 255}
Number of discarded Values (I) = RM % N + 1 == N
IE:
I = RM % N + 1
I = 255 % 4 + 1
I = 3 + 1
I = 4
X => ( RM - RM % N )
255 => (255 - 255 % 4)
255 => (255 - 3)
255 => (252)
Discard Returns $True
जैसा कि आप ऊपर के उदाहरण में देख सकते हैं, जब X का मान (प्रारंभिक फ़ंक्शन से प्राप्त यादृच्छिक संख्या) 252, 253, 254, या 255 है, तो हम इसे त्याग देंगे भले ही इन चार मूल्यों में लौटे मूल्यों का एक वैध सेट शामिल हो। ।
IE: जब मानों की गणना को त्याग दिया गया (I) = N (वैध परिणामों की संख्या) तो रिटर्न वैल्यूज़ का एक वैध सेट मूल फ़ंक्शन द्वारा छोड़ दिया जाएगा।
यदि हम N और RM के बीच के अंतर को D के रूप में वर्णित करते हैं, अर्थात:
D = (RM - N)
फिर जैसे-जैसे D का मान छोटा होता जाता है, इस पद्धति के कारण अनावश्यक री-रोल का प्रतिशत प्रत्येक प्राकृतिक गुणक में बढ़ता जाता है। (जब RAND_MAX एक अभाज्य संख्या के बराबर नहीं है तो यह वैध चिंता का विषय है)
ईजी:
RM=255 , N=2 Then: D = 253, Lost percentage = 0.78125%
RM=255 , N=4 Then: D = 251, Lost percentage = 1.5625%
RM=255 , N=8 Then: D = 247, Lost percentage = 3.125%
RM=255 , N=16 Then: D = 239, Lost percentage = 6.25%
RM=255 , N=32 Then: D = 223, Lost percentage = 12.5%
RM=255 , N=64 Then: D = 191, Lost percentage = 25%
RM=255 , N= 128 Then D = 127, Lost percentage = 50%
चूँकि Rerolls के प्रतिशत में वृद्धि होती है, N के RM के करीब आता है, यह कई अलग-अलग मूल्यों पर वैध चिंता का विषय हो सकता है, क्योंकि वह उस कोड को चलाने वाले सिस्टम की बाधाओं और मूल्यों की तलाश में होता है।
इसे नकारने के लिए हम एक सरल संशोधन कर सकते हैं जैसा कि यहाँ दिखाया गया है:
int x;
do {
x = rand();
} while (x > (RAND_MAX - ( ( ( RAND_MAX % n ) + 1 ) % n) );
x %= n;
यह सूत्र का एक अधिक सामान्य संस्करण प्रदान करता है जो आपके अधिकतम मूल्यों को परिभाषित करने के लिए मापांक का उपयोग करने की अतिरिक्त विशिष्टताओं के लिए खाता है।
RAND_MAX के लिए एक छोटे मूल्य का उपयोग करने के उदाहरण जो कि एन का गुणक है।
Mark'original संस्करण:
RAND_MAX = 3, n = 2, Values in RAND_MAX = 0,1,2,3, Valid Sets = 0,1 and 2,3.
When X >= (RAND_MAX - ( RAND_MAX % n ) )
When X >= 2 the value will be discarded, even though the set is valid.
सामान्यीकृत संस्करण 1:
RAND_MAX = 3, n = 2, Values in RAND_MAX = 0,1,2,3, Valid Sets = 0,1 and 2,3.
When X > (RAND_MAX - ( ( RAND_MAX % n ) + 1 ) % n )
When X > 3 the value would be discarded, but this is not a vlue in the set RAND_MAX so there will be no discard.
इसके अतिरिक्त, उस स्थिति में जहां N को RAND_MAX में मानों की संख्या होनी चाहिए; इस स्थिति में, आप N = RAND_MAX +1 सेट कर सकते हैं, जब तक कि RAND_MAX = INT_MAX।
लूप-वार आप केवल एन = 1 का उपयोग कर सकते हैं, और एक्स के किसी भी मूल्य को स्वीकार किया जाएगा, हालांकि, और अपने अंतिम गुणक के लिए एक IF स्टेटमेंट डाल सकते हैं। लेकिन शायद आपके पास कोड है जो फ़ंक्शन 1 को n = 1 के साथ कॉल करने पर एक वैध कारण हो सकता है ...
तो 0 का उपयोग करना बेहतर हो सकता है, जो सामान्य रूप से एक डिव त्रुटि प्रदान करेगा, जब आप n = RAND_MAX 1 चाहते हैं
सामान्यीकृत संस्करण 2:
int x;
if n != 0 {
do {
x = rand();
} while (x > (RAND_MAX - ( ( ( RAND_MAX % n ) + 1 ) % n) );
x %= n;
} else {
x = rand();
}
इन दोनों समाधानों ने समस्या का समाधान अनावश्यक रूप से खारिज किए गए वैध परिणामों के साथ किया है जो तब होगा जब आरएम + 1 एन का एक उत्पाद है।
जब आप RAND_MAX में निहित मानों के कुल संभव सेट के बराबर n की आवश्यकता होती है, तो दूसरा संस्करण भी एज केस परिदृश्य को कवर करता है।
दोनों में संशोधित दृष्टिकोण समान है और मान्य यादृच्छिक संख्या प्रदान करने और त्याग किए गए मूल्यों को कम करने की आवश्यकता के लिए एक अधिक सामान्य समाधान की अनुमति देता है।
बार बार कहना:
बेसिक जनरल सॉल्यूशन जो निशान के उदाहरण का विस्तार करता है:
// Assumes:
// RAND_MAX is a globally defined constant, returned from the environment.
// int n; // User input, or externally defined, number of valid choices.
int x;
do {
x = rand();
} while (x > (RAND_MAX - ( ( ( RAND_MAX % n ) + 1 ) % n) ) );
x %= n;
विस्तारित सामान्य समाधान जो RAND_MAX + 1 = n के एक अतिरिक्त परिदृश्य की अनुमति देता है:
// Assumes:
// RAND_MAX is a globally defined constant, returned from the environment.
// int n; // User input, or externally defined, number of valid choices.
int x;
if n != 0 {
do {
x = rand();
} while (x > (RAND_MAX - ( ( ( RAND_MAX % n ) + 1 ) % n) ) );
x %= n;
} else {
x = rand();
}
कुछ भाषाओं में (विशेष रूप से व्याख्या की गई भाषाओं में) समतुल्य स्थिति के बाहर तुलना-संचालन की गणना करते हुए तेजी से परिणाम प्राप्त हो सकते हैं क्योंकि यह एक बार की गणना है, चाहे कितने भी प्रयास की आवश्यकता हो। YMMV!
// Assumes:
// RAND_MAX is a globally defined constant, returned from the environment.
// int n; // User input, or externally defined, number of valid choices.
int x; // Resulting random number
int y; // One-time calculation of the compare value for x
if n != 0 {
y = RAND_MAX - ( ( ( RAND_MAX % n ) + 1 ) % n)
do {
x = rand();
} while (x > y);
x %= n;
} else {
x = rand();
}
RAND_MAX%n == n - 1
है(RAND_MAX + 1) % n == 0
। कोड पढ़ते समय, मैं% something == 0
इसकी गणना करने के अन्य तरीकों की तुलना में "समान रूप से विभाज्य" के रूप में आसानी से समझ सकता हूं । बेशक, अगर आपके C ++ stdlibRAND_MAX
के समान मूल्य हैINT_MAX
, तो(RAND_MAX + 1)
निश्चित रूप से काम नहीं करेगा; इसलिए मार्क की गणना सबसे सुरक्षित कार्यान्वयन है।