сгенерируйте случайное число от 1 до x, где меньшее число более вероятно, чем большее
Это скорее вопрос математики/общего программирования, но я программирую на PHP, и это имеет значение.
Я думаю, что самый простой способ объяснить это на примере.
Если диапазон составляет от 1 до 10.
Я хочу сгенерировать число от 1 до 10, но, скорее всего, оно меньше, чем высокое.
Единственный способ, который я могу придумать, - это создать массив из 10 элементов, равных 1, 9 элементов, равных 2, 8 элементов, равных 3.....1 элемент, равный 10. Затем сгенерируйте случайное число на основе количества элементов.
Проблема в том, что я потенциально имею дело с 1-100000, и этот массив был бы смехотворно большим.
Итак, как лучше всего это сделать?
13 answers
Сгенерируйте случайное число от 0 до случайного числа!
Сгенерируйте число от 1 до foo(n), где foo выполняет алгоритм над n (например, логарифмическую функцию). Затем переверните foo() на результат.
Сгенерируйте число n
, которое равно 0 <= n < 1
, умножьте его на себя, затем умножьте на x
, запустите его и добавьте 1. Извините, что я слишком давно использовал php для написания кода в нем
Вы могли бы сделать
$rand = floor(100000 * (rand(0, 1)*rand(0, 1)));
Или что-то в этом роде
В основном существует два (или больше?) способы отображения равномерной плотности на любую функцию распределения: Выборка обратного преобразования и Выборка отбраковки . Я думаю, что в вашем случае вам следует использовать первое.
Быстро и просто:
rand(1, rand(1, n))
Я думаю, что это может быть то, что вы ищете:
Что вам нужно сделать, так это сгенерировать случайное число с большим интервалом (предпочтительно с плавающей запятой) и отобразить его в [1,10] неравномерным образом. Какой именно способ зависит от насколько гораздо более вероятно, что вы хотите, чтобы 1 был, чем 9 или 10.
Для решений на языке C см. эти библиотеки . Вы можете найти применение для этого в PHP.
Вообще говоря, похоже, что вы хотите получить случайное число из распределения Пуассона , а не из [равномерного распределения](http://en.wikipedia.org/wiki/Uniform_distribution_ (непрерывный)). На вики-странице, упомянутой выше, есть раздел, в котором конкретно указано, как вы можете использовать непрерывное распределение для создания псевдо-пуассоновского распределения... проверьте это. Обратите внимание, что вы можете захотеть проверить различные значения λ, чтобы обеспечить распределение работает так, как вы хотите.
Это зависит от того, какое распределение вы хотите иметь точно, т. Е. Какое число должно появиться с какой вероятностью.
Например, для четного n вы могли бы сделать следующее: сгенерировать одно целое случайное число x от 1 до n/2 и сгенерировать второе число от 1 до n+1. Если y > x, вы генерируете x, в противном случае вы генерируете n-x+1. Это должно дать вам распределение в вашем примере.
Я думаю, что это должно дать запрошенное распределение:
Сгенерируйте случайное число в диапазоне 1.. x. Сгенерируйте другое число в диапазоне 1..x+1. Верните минимум из двух.
Давайте подумаем о том, как ваша идея массива изменяет вероятности. Обычно каждый элемент от 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, и это является ключом к следующему шагу.
Как мы можем использовать эту функцию, чтобы исказить количество появлений элемента? Это проще с непрерывными распределениями (т. е. удваивается вместо ints), но мы можем это сделать. Сначала давайте составим массив наших вероятностей, назовем его c, составим их текущую сумму (cumsum) и сохраним ее обратно в c. Если это не имеет смысла, это просто цикл, подобный
for(j=0; j < n-1; j++)
if(j) c[j]+=c[j-1]
Теперь, когда у нас есть это кумулятивное распределение, сгенерируйте число i от 0 до 1 (двойное, а не int. Мы можем проверить, находится ли я между 0 и c[0], верните 1. если я нахожусь между c[1] и c[2], верните 2...вплоть до n. например
{[1]}
Это будет распространять целые числа в соответствии с рассчитанными вами вероятностями.
<?php
//get random number between 1 and 10,000
$random = mt_rand(1, 10000);
?>