У вас есть одна монета. Вы можете перевернуть его столько раз, сколько захотите.
Вы хотите сгенерировать случайное число такое, чтогде.
Распределение чисел должно быть равномерным.
Это легко, если :
r = a + binary2dec(flip n times write 0 for heads and 1 for tails)
Что если ?
algorithms
probability-theory
randomness
random-number-generator
Пратик Деогхаре
источник
источник
Ответы:
То, что вы ищете, основано на выборке Rejection или методе accept-reject (обратите внимание, что страница Wiki немного техническая).
Этот метод полезен в таких ситуациях: вы хотите выбрать некоторый случайный объект из набора (случайное целое число в наборе в вашем случае), но вы не знаете, как это сделать, но вы Можно выбрать некоторый случайный объект из большего набора, содержащего первый набор (в вашем случае [ a , 2 k + a ] для некоторого k такого, что 2 k + a ≥ b ; это соответствует k броскам монет).[a,b] [a,2k+a] k 2k+a≥b k
В таком сценарии вы просто продолжаете выбирать элементы из большего набора, пока не выберете случайный элемент из меньшего набора. Если ваш меньший набор достаточно велик по сравнению с вашим большим набором (в вашем случае содержит самое большее в два раза больше целых чисел, чем [ a , b ] , что достаточно хорошо), это эффективно.[a,2k+a] [a,b]
Альтернативный пример: предположим, что вы хотите выбрать случайную точку внутри круга с радиусом 1. Теперь не совсем легко придумать прямой метод для этого. Обратимся к методу принятия-отклонения: мы выбираем точки в квадрате 1x1, охватывающем окружность, и проверяем, лежит ли нарисованное число внутри окружности.
источник
(технические характеристики: ответ соответствует выбору числа )a ≤ x < b
Так как вам разрешено подбрасывать свою монету столько раз, сколько вы хотите, вы можете получить свою вероятность как можно ближе к униформе, выбрав дробь (используя двоичный ось: вы переворачиваете монеты за каждую цифру после точки) и умножьте r на b - a, чтобы получить число от 0 до [ba-1] (округление до целого числа). Добавьте это число к и вы сделали.r ∈ [ 0 , 1 ] р б - а a
Пример : скажем, . 1/3 в двоичном виде - 0,0101010101 .... Тогда, если ваш флип находится в диапазоне от 0 до 0,010101 ... ваш выбор b . если это beween 0.010101 .. и 0.10101010 ... ваш выбор будет + 1 , а в противном случае она будет + 2 .б - а = 3 б + 1 + 2
Если вы перевернете свою монету раз, то каждое число между a и b будет выбрано с вероятностью 1T a б .1б - а± 2- ( т + 1 )
источник
Выберите число в следующей большей степени диапазона 2 и отбросьте ответы, превышающие .b−a
источник
Никто не говорил об этом, так что позвольте мне формально доказать , что если является областью, размер которого не является степенью двойки, то конечное число бросков справедливой монеты не достаточно , чтобы создать равномерно случайный член D . Предположим , вы используете K монеты для создания члена D . Для каждого д ∈ D , вероятность того, что ваш алгоритм генерируется д имеет вид А / 2 к для некоторого целого числа А . Основная теорема арифметики показывает, что A / 2 k ≠ 1 / | D | ,D D k D d∈D d A/2k A A/2k≠1/|D|
Если вы хотите сгенерировать независимых одинаковых выборок D , то ожидаемое количество бросков монет (по оптимальному алгоритму) примерно равно n log 2 | D | , В более общем смысле, если вы хотите генерировать из распределения энтропии H , вам нужно примерно n H случайных битов в ожидании. Алгоритм достижения этого - арифметическое декодирование, применяемое к (якобы) бесконечной последовательности случайных битов.n D nlog2|D| H nH
источник
Если ba не является степенью 2, вам, возможно, придется перевернуть много монет, чтобы получить результат. Вы можете даже никогда не получить результат, но это вряд ли в крайности.
методы
Самый простой способ - это сгенерировать число в [a, a + 2 ^ n), где 2 ^ n> = ba, пока не произойдет приземление в [a, b). Вы выбрасываете много энтропии с этим методом.
Более дорогой метод позволяет вам сохранить всю энтропию, но становится очень дорогим в вычислительном отношении, так как количество бросков монет / бросков игральных костей увеличивается. Интуитивно это похоже на обработку бросков монеты как цифр двоичного числа справа от десятичной точки, преобразование этого числа из основания 2 в основание ab и возвращение цифр этого числа по мере их «залипания».
пример
Следующий код преобразует рулоны правильного n-стороннего штампа в рулоны хорошего m-стороннего штампа (в вашем случае n = 2, m = ab) с увеличением предельных издержек по мере увеличения числа рулонов. Обратите внимание на необходимость использования рационального числа с произвольной точностью. Хорошим свойством является то, что преобразование из n-стороннего в m-двустороннее и обратно в n-стороннее вернет исходный поток, хотя, возможно, задерживается парой бросков из-за того, что цифры застревают.
источник
Генерация двоичного десятичного числа. Вместо того, чтобы хранить это явно, просто следите за минимальными и максимальными возможными значениями. Как только эти значения лежат в одном и том же целом числе, вернуть это целое число. Эскиз кода ниже.
(Изменить) Более полное объяснение: допустим, вы хотите сгенерировать случайное целое число от 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. Теперь, если ваш следующий бросок - это хвосты, x начинается с 0,10. Минимальное возможное значение составляет 0,1000000 = 1/2, а максимальное - 0,1011111 = 3/4. Минимально возможное значение x равно 1/2, так что вы знаете, что нет шансов вернуть 1, так как для этого требуется х <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, мы знаем, что x должен попадать в интервал (1/3, 2/3), поэтому мы можем прекратить генерировать цифры x и просто вернуть 2.
Код делает это по существу, за исключением того, что вместо генерации x между 0 и 1 он генерирует x между a и b, но принцип тот же.
Примечание: я проверил этот код по методу принятия / отклонения, и оба получили равномерное распределение. Этот код требует меньше бросков монеты, чем прием отклонения, за исключением случаев, когда 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) для хорошего обсуждения литературы.
источник
Простой ответ?
источник
Это предлагаемое решение для случая, когда b - a не равно 2 ^ k. Предполагается, что он работает с фиксированным числом шагов (не нужно выбрасывать кандидатов, которые находятся за пределами ожидаемого диапазона).
Однако я не уверен, что это правильно. Пожалуйста, критикуйте и помогите описать точную неравномерность в этом генераторе случайных чисел (если есть) и как его измерить / измерить.
Сначала перейдем к эквивалентной задаче генерации равномерно распределенных случайных чисел в диапазоне [0, z-1], где z = b - a.
Кроме того, пусть m = 2 ^ k будет наименьшей степенью 2> = z.
Согласно приведенному выше решению, у нас уже есть равномерно распределенный генератор случайных чисел R (m) в диапазоне [0, m-1] (это можно сделать, подбросив k монет, по одной на каждый бит).
Цикл while выполняется максимум 3 раза, давая следующее случайное число с фиксированным числом шагов (лучший случай = наихудший случай).
Смотрите программу испытаний для чисел [0,2] здесь: http://pastebin.com/zuDD2V6H
источник
Теоретически оптимальный алгоритм
Вот улучшение другого ответа, который я отправил. Другой ответ имеет то преимущество, что его легче распространить на более общий случай генерации одного дискретного распределения из другого. На самом деле, другой ответ является частным случаем алгоритма из-за Хана и Хоши.
Алгоритм, который я опишу здесь, основан на Кнуте и Яо (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 ,
Вот код:
источник