Утворіть двійковий десятковий знак. Замість того, щоб чітко зберігати його, просто слідкуйте за мінімальними та максимальними можливими значеннями. Як тільки ці значення лежать в одному цілому цілому, поверніть це ціле число. Ескіз коду нижче.
(Редагувати) Пояснення Фуллера: Скажіть, що ви хочете генерувати випадкове ціле число від 1 до 3 включно з 1/3 ймовірності кожного. Ми робимо це, генеруючи випадкову двійкову десяткову реальність, x в діапазоні (0, 1). Якщо x <1/3, поверніть 1, інакше, якщо x <2/3 поверніть 2, інакше поверніть 3. Замість генерування цифр для x явно, ми просто відстежуємо мінімальні та максимально можливі значення x. Спочатку мінімальне значення x дорівнює 0, а максимум - 1. Якщо ви перевернете голову спочатку, то перша цифра x за десятковою комою (у двійковій формі) дорівнює 1. Мінімальне можливе значення x (у двійковій формі) тоді стає 0,100000 = 1/2, а максимум - 0,111111111 = 1. Тепер, якщо ваш наступний фліп - хвости, х починається з 0,10. Мінімальне можливе значення - 0,1000000 = 1/2, а максимальне - 0,1011111 = 3/4. Мінімальне можливе значення х становить 1/2, щоб ви знали, що там ' s немає шансів повернути 1, оскільки для цього потрібно x <1/3. Ще можна повернути 2, якщо х закінчується як 1/2 <x <2/3 або 3, якщо 2/3 <x <3/4. Тепер припустимо, що третій фліп - це хвости. Тоді х треба починати з 0,100. Мін = 0,10000000 = 1/2 і макс = 0,100111111 = 5/8. Тепер, оскільки 1/3 <1/2 <5/8 <2/3 ми знаємо, що х повинен потрапляти в інтервал (1/3, 2/3), тому ми можемо перестати генерувати цифри x і просто повернути 2.
Код робить це по суті, за винятком того, що генерує x між 0 і 1, він генерує x між a і b, але принцип той же.
def gen(a, b):
min_possible = a
max_possible = b
while True:
floor_min_possible = floor(min_possible)
floor_max_possible = floor(max_possible)
if max_possible.is_integer():
floor_max_possible -= 1
if floor_max_possible == floor_min_possible:
return floor_max_possible
mid = (min_possible + max_possible)/2
if coin_flip():
min_possible = mid
else:
max_possible = mid
Зауваження: я перевірив цей код на метод прийняття / відхилення і обидва рівномірні розподіли. Цей код вимагає менших перевернень монети, ніж прийняття відхилення, за винятком випадків, коли b - a близький до наступної потужності 2. Наприклад, якщо ви хочете генерувати a = 0, b = 62, то краще приймати / відхиляти. Мені вдалося довести, що цей код може в середньому використовувати не більше 2-х перевернутих монет, ніж прийняти / відхилити. З мого читання, схоже, Кнут і Яо (1976) дали метод вирішення цієї проблеми і довели, що їх метод є оптимальним при очікуваній кількості монетних переворотів. Вони також довели, що очікувана кількість обертів повинна бути більшою, ніж ентропія Шеннона розподілу. Я не зміг знайти копію тексту статті, і мені було б цікаво дізнатися, що це за метод. (Оновлення: щойно знайдено експозицію Кнут Яо 1976 року тут:http://www.nrbook.com/devroye/Devroye_files/chapter_fifteen_1.pdf, але я її ще не читав). Хтось також згадував Хан Хоші в цій нитці, яка здається більш загальною, і вирішує її за допомогою упередженої монети. Дивіться також http://paper.ijcsns.org/07_book/200909/20090930.pdf від Pae (2009) для гарного обговорення літератури.