генерировать случайное число от 1 до x, где более низкое число более вероятно, чем более высокое - PullRequest
13 голосов
/ 21 июля 2010

Это больше вопрос математики / общего программирования, но я программирую на PHP, и это имеет значение.

Я думаю, что самый простой способ объяснить это на примере.

Если диапазон находится в диапазоне от 1 до 10.

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

Единственный способ, которым я могу думать, - это генерироватьмассив с 10 элементами, равными 1, 9 элементами, равными 2, 8 элементами, равными 3 ..... 1 элемент, равный 10. Затем генерируется случайное число на основе количества элементов.

Проблемая потенциально имею дело с 1 - 100000, и этот массив будет смехотворно большим.

Так как лучше это сделать?

Ответы [ 13 ]

25 голосов
/ 21 июля 2010

Генерация случайного числа от 0 до случайного числа!

11 голосов
/ 21 июля 2010

Генерирует число от 1 до foo (n), где foo запускает алгоритм над n (например, логарифмическая функция). Затем измените foo () на результат.

4 голосов
/ 21 июля 2010

Создайте число n, которое равно 0 <= n < 1, умножьте его на себя, затем умножьте на x, запустите слово на нем и добавьте 1. Извините, я давно использовал php toooo, чтобы написать код в нем

3 голосов
/ 21 июля 2010

Быстро и просто:

rand(1, rand(1, n))
3 голосов
/ 21 июля 2010

Существует два (или более?) Способа сопоставить равномерную плотность с любой функцией распределения: Выборка обратного преобразования и Выборка отклонения .Я думаю, что в вашем случае вы должны использовать первый.

3 голосов
/ 21 июля 2010

Вы могли бы сделать

$rand = floor(100000 * (rand(0, 1)*rand(0, 1)));

Или что-то в этом роде

2 голосов
/ 21 июля 2010

Я думаю, это может быть то, что вы ищете:

Случайный по весу

0 голосов
/ 09 марта 2015
<?php 
//get random number between 1 and 10,000
$random = mt_rand(1, 10000); 
?>
0 голосов
/ 21 июля 2010

Давайте подумаем о том, как идея вашего массива изменяет вероятности. Обычно каждый элемент от 1 до n имеет вероятность 1 / n и, таким образом, одинаково вероятен.

Поскольку у вас есть n записей для 1, n-1 записей для 2 ... 1 записи для n, то общее количество записей, которые у вас есть, представляет собой арифметический ряд. Сумма арифметического ряда от 1 до n равна n (1 + n) / 2. Итак, теперь мы знаем, что вероятность каждого элемента должна использовать это как знаменатель.

Элемент 1 имеет n записей, поэтому его вероятность равна n / n (1 + n) / 2. Элемент 2 равен n-1 / n (1 + n) / 2 ... n равен 1 / n (1 + n) / 2. Это дает общую формулу числителя в виде n + 1 -i, где i - номер, который вы проверяете. Это означает, что теперь у нас есть функция для вероятности любого элемента как n-i + 1 / n (1 + n) / 2. все вероятности находятся в диапазоне от 0 до 1, а по определению сумма равна 1, и это является ключом к следующему шагу.

Как мы можем использовать эту функцию, чтобы искажать число раз, когда элемент появляется? Это проще с непрерывным распределением (т.е. удваивается вместо целых), но мы можем это сделать. Сначала давайте создадим массив наших вероятностей, назовем его c, составим их текущую сумму (cumsum) и сохраним обратно в c. Если это не имеет смысла, это просто цикл вроде


for(j=0; j < n-1; j++)
   if(j) c[j]+=c[j-1]

Теперь, когда у нас есть это кумулятивное распределение, сгенерируйте число i от 0 до 1 (двойное число, а не целое число. Мы можем проверить, находится ли i между 0 и c [0], вернуть 1. если i находится между c [ 1] и c [2] возвращают 2 ... вплоть до отрицательного <pre> for(j=0; j < n=1;j++) if(i %lt;= c[j]) return i+1

Это распределит целые числа в соответствии с вычисленными вами вероятностями.

0 голосов
/ 21 июля 2010

Я думаю, что это должно дать запрошенный дистрибутив:

Генерация случайного числа в диапазоне 1 .. х. Создайте еще один в диапазоне 1 .. х + 1. Верните минимум из двух.

...