Расширить случайный диапазон от 1-5 до 1-7 - PullRequest
0 голосов
/ 25 февраля 2011

Расширение случайного диапазона от 1–5 до 1–7

int i;
do
{
  i = 5 * (rand5() - 1) + rand5();  // i is now uniformly random between 1 and 25
} while(i > 21);
// i is now uniformly random between 1 and 21
return i % 7 + 1;  // result is now uniformly random between 1 and 7

Почему я не могу просто поставить

i = 6*(rand5()-1);

есть? почему нам нужны операции "*" и "+"

Ответы [ 3 ]

4 голосов
/ 25 февраля 2011

(rand5 () - 1) возвращает число от 0 до 4. Если вы умножите любое из этих чисел на 6, вы получите одно из 5 чисел (0, 6, 12, 18 или 24).

Если сделать это другим способом, то каждое возможное целое число от 1 до 21 может появиться в выходных данных (с одинаковой вероятностью).

EDIT:

5 * (rand5 () - 1) даст вам одно из (0, 5, 10, 15, 20). К этому мы затем добавляем другое случайное целое число от 1 до 5, таким образом заполняя пробелы. Теперь у нас есть случайное целое число от 1 до 25 с одинаковой вероятностью. Поскольку нам нужен диапазон от 1 до 21, мы отклоняем все, что больше 21, и пытаемся снова.

1 голос
/ 25 февраля 2011

Дело в том, что rand5 () имеет значение random , и каждый вызов в исходном выражении возвращает свой ответ. Вот почему rand5() + rand5() - это не то же самое, что 2*rand5().

Аналогично: 5 * (rand5() - 1) + rand5() - это 5*rand5() + rand5() - 5, но не то же самое, что и 6*rand5() - 5, поскольку каждый раз при вызове rand5 () выдается другой результат.

0 голосов
/ 26 февраля 2011

Вот процедура на python с эмпирическим тестом на однородность.

Сначала случайный генератор целых чисел в диапазоне 1..5:

>>> def r5(): return randrange(5) + 1

>>> bins = dict((i, 0) for i in range(9))
>>> pp(bins)
{0: 0, 1: 0, 2: 0, 3: 0, 4: 0, 5: 0, 6: 0, 7: 0, 8: 0}
>>> for i in range(999999): bins[r5()] += 1

>>> pp(bins)
{0: 0, 1: 199752, 2: 200378, 3: 200452, 4: 199580, 5: 199837, 6: 0, 7: 0, 8: 0}

Обратите внимание на то, что бин имеет значение длязначения 1..5.

Используемый алгоритм состоит в том, что, если вы сгенерируете два числа r5 () по порядку, то их 5 * 5 = 25 возможных перестановок, которые имеют равную вероятность появления.если мы возьмем какую-либо константу 21 из этих перестановок, мы сможем увидеть, находится ли сгенерированная нами пермь в этой 21 и превратить каждые три значения в одно из семи целых чисел для возврата.Если мы генерируем перестановку не в 21, то нам нужно получить еще два значения r5 () и повторить.

Код для r7 зависит от некоторых констант, которые я сделал глобальными для скорости:

>>> list5 = [1,2,3,4,5]
>>> perm21 = [(x,y) for x in list5 for y in list5 ][:21]
>>> set21 = set(perm21)
>>> def r7():
    r = (6,6)
    while r not in set21:
        r = (r5(), r5())
    return (perm21.index(r) // 3) + 1

>>> bins = dict((i, 0) for i in range(9))
>>> for i in range(999999): bins[r7()] += 1

>>> pp(bins)
{0: 0,
 1: 142857,
 2: 143558,
 3: 143046,
 4: 142699,
 5: 142786,
 6: 142439,
 7: 142614,
 8: 0}
>>> 

Давайте попробуем взглянуть на разброс в 10 раз больше проб:

>>> bins = dict((i, 0) for i in range(9))
>>> for i in range(9999999): bins[r7()] += 1

>>> pp(bins)
{0: 0,
 1: 1429821,
 2: 1429851,
 3: 1427350,
 4: 1428478,
 5: 1425243,
 6: 1429618,
 7: 1429638,
 8: 0}

Мне кажется, хорошо: -)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...