Расширить случайный диапазон целых чисел, используя распределение вероятностей - PullRequest
0 голосов
/ 18 декабря 2018

Я пытался решить классическую проблему генерации случайного целого числа от 1 до 7, учитывая функцию, которая генерирует случайное целое число от 1 до 5. Мой подход состоял в том, чтобы добавить результат 2 вызовов в rand5 (), эффективно поворачиваяэто в "сумме бросков кубиков" проблема.Вероятность выпадения суммы кубиков довольно легко вычислить, поэтому я использовал ее здесь.Объяснение этому после кода

Мой вопрос: как я могу рассчитать, какими должны быть значения счетчика?Текущие значения неверны, что подтверждено экспериментом.Существуют ли целочисленные значения, которые удовлетворяют вероятности?И есть ли лучший способ решить эту проблему с помощью этого подхода?

def rand5():
    return random.randint(1,5)

def rand7():
    counter = [1,2,3,4,5,4,3]
    while 0 not in counter:
        sum = rand5() + rand5() - 2
        if sum <= 6:
            counter[sum] -= 1
    return counter.index(0) + 1

Для справки следующий код создается для создания случайного распределения.

test_counter = [0,0,0,0,0,0,0,0,0,0,0,0]
for i in range(500000):
    test_counter[rand5() + rand5() - 2] += 1

test_counter[0] *= 60
test_counter[1] *= 30
test_counter[2] *= 20
test_counter[3] *= 15
test_counter[4] *= 12
test_counter[5] *= 15
test_counter[6] *= 20
test_counter[7] *= 0
test_counter[8] *= 0

print(test_counter)

Объяснение вероятности:Вероятность бросков костей можно рассчитать, перечислив возможные комбинации костей.Для этой проблемы числа, сгенерированные каждым die (функция rand5) будут:

{(1,1), (1,2), (1,3), (1,4), (1,5), (2,1), (2,2), ..., (5,5)}

Вероятность каждой суммы - это число способовсумма появляется в списке, разделенная на общее количество элементов в списке.В списке всего 5 ^ 2 = 25 элементов.Например, сумма 4 может быть достигнута с помощью следующих комбинаций {(1,3), (2,2), (3,1)}, поэтому вероятность суммы 4 равна 3 / 25.

Тогда вероятность каждого результата равна:

1/25 2/25 3/25 4/25 5/25 4 /25 3/25 2/25 1/25

Я попытался использовать это распределение для генерации равномерного распределения, имеяболее распространенные из них должны быть сгенерированы несколько раз, и это сохраняется в счетчике.

1 Ответ

0 голосов
/ 18 декабря 2018

Не уверен, что прохождение игры в кости - хорошая идея.В общем, если у вас есть источник случайных битов, но короткие последовательности, лучше объединить и нарезать биты, чтобы составить более длинную последовательность случайных битов.Вдоль линий

import random

def rand5():
    return random.randint(1, 5)

def twobits():
    q = rand5() - 1 # [0...5) range
    while q == 4: # dropping high bit
        q = rand5() - 1
    return q # [0...3) range, two random bits

def onebit():
    return twobits() & 1

def rand7():
    q = onebit() << 2 | twobits() # here we have [0...8) range
    while q == 0:                 # and dropping 0
        q = onebit() << 2 | twobits()
    return q

counter = 8*[0]

for i in range(500000):
    counter[rand7()] += 1

print(counter)

получено равномерное в [1 ... 8) выборке

[0, 71592, 71352, 71071, 71543, 71600, 71388, 71454]

Возьмите два бита из одного семпла, один бит из другого семпла, объедините их, некоторые отклоненияи вуаля!

...