सैद्धांतिक रूप से इष्टतम एल्गोरिथ्म
यहाँ मेरे द्वारा पोस्ट किए गए दूसरे उत्तर का सुधार है। अन्य उत्तर का यह लाभ है कि एक असतत वितरण को दूसरे से उत्पन्न करने के अधिक सामान्य मामले तक विस्तार करना आसान है। वास्तव में, अन्य उत्तर हान और होशी के कारण एल्गोरिथ्म का एक विशेष मामला है।
यहाँ मैं जिस एल्गोरिथ्म का वर्णन करूँगा वह नूथ और याओ (1976) पर आधारित है। अपने पेपर में, उन्होंने यह भी साबित किया कि यह एल्गोरिथ्म सिक्का के न्यूनतम संभावित अपेक्षित संख्या प्राप्त करता है।
इसे समझने के लिए, अन्य उत्तरों द्वारा वर्णित अस्वीकृति नमूना पद्धति पर विचार करें। एक उदाहरण के रूप में, मान लें कि आप 5 में से एक संख्या को समान रूप से उत्पन्न करना चाहते हैं [0, 4]। 2 की अगली शक्ति 8 है, इसलिए आप 3 बार सिक्का फ्लिप करें और 8. तक एक यादृच्छिक संख्या उत्पन्न करें। यदि संख्या 0 से 4 है, तो इसे वापस लौटाएं। अन्यथा, आप इसे फेंक देते हैं और 8 तक एक और संख्या उत्पन्न करते हैं और फिर से प्रयास करते हैं जब तक कि आप सफल न हों। लेकिन जब आप संख्या बाहर फेंकते हैं, तो आप बस कुछ एन्ट्रोपी बर्बाद करते हैं। आप भविष्य में सिक्का की संख्या को कम करने के लिए आपके द्वारा फेंके गए नंबर पर शर्त के बजाय इसकी अपेक्षा कर सकते हैं। लगातार, एक बार जब आप संख्या [0, 7] उत्पन्न करते हैं, अगर यह [0, 4] है, तो वापस लौटें। अन्यथा, यह 5, 6 या 7 है, और आप प्रत्येक मामले में कुछ अलग करते हैं। यदि यह 5 है, तो सिक्के को फिर से फ्लिप करें और फ्लिप के आधार पर या तो 0 या 1 वापस करें। अगर यह 6 है, सिक्का पलटें और 2 या 3 लौटें। यदि यह 7 है, तो सिक्का पलटें; यदि यह सिर है, तो 4 लौटें, अगर यह पूंछ शुरू हो।
हमारे शुरुआती असफल प्रयास से बचे हुए प्रवेश ने हमें 3 मामले (5, 6 या 7) दिए। यदि हम इसे बाहर फेंक देते हैं, तो हम log2 (3) सिक्का निकालते हैं। हम इसके बजाय इसे रखते हैं, और इसे 6 संभावित मामलों (5H, 5T, 6H, 6T, 7H, 7T) को उत्पन्न करने के लिए एक और फ्लिप के परिणाम के साथ जोड़ते हैं, जो हमें तुरंत सफलता की संभावना 5/6 के साथ एक अंतिम उत्तर उत्पन्न करने के लिए फिर से कोशिश करते हैं। ।
यहाँ कोड है:
# returns an int from [0, b)
def __gen(b):
rand_num = 0
num_choices = 1
while True:
num_choices *= 2
rand_num *= 2
if coin.flip():
rand_num += 1
if num_choices >= b:
if rand_num < b:
return rand_num
num_choices -= b
rand_num -= b
# returns an int from [a, b)
def gen(a, b):
return a + __gen(b - a)