Генерировать случайное число между 1 и x, где более низкое число более вероятно, чем более высокое

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

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

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

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

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

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

Итак, как лучше всего это сделать?

Ответ 1

Создайте случайное число между 0 и случайным числом!

Ответ 2

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

Ответ 3

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

Ответ 4

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

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

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

Ответ 6

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

rand(1, rand(1, n))

Ответ 8

Что вам нужно сделать, так это генерировать случайное число на большем интервале (предпочтительно с плавающей запятой) и отображать его на [1,10] неравномерно. Точно, какой способ зависит от как, гораздо более вероятно, что вы хотите, чтобы 1 был чем 9 или 10.

Для решений на языке C см. эти библиотеки. Вы можете найти для это в PHP.

Ответ 9

Вообще говоря, похоже, вы хотите нарисовать случайное число из распределение Пуассона, а не [равномерное распределение] (http://en.wikipedia.org/wiki/Uniform_distribution_(continuous)). На цитированной выше странице вики есть раздел, в котором конкретно указывается, как вы можете использовать непрерывное распространение для генерации псевдопуассоновского распределения... проверьте его. Обратите внимание, что вы можете протестировать разные значения λ, чтобы обеспечить, чтобы распределение работало так, как вы хотите.

Ответ 10

Это зависит от того, какое распределение вы хотите иметь точно, т.е. какое число должно появиться с какой вероятностью.

Например, для четного n вы можете сделать следующее: сгенерировать одно целое случайное число x между 1 и n/2 и сгенерировать второе число между 1 и n + 1. Если y > x, вы генерируете x, иначе вы генерируете n-x + 1. Это должно дать вам распределение в вашем примере.

Ответ 11

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

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

Ответ 12

Подумайте о том, как ваша идея массива изменяет вероятности. Обычно каждый элемент от 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, где я - номер, который вы проверяете. Это означает, что теперь мы имеем функцию вероятности любого элемента при 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]

Теперь, когда у нас есть это кумулятивное распределение, сгенерируйте число я от 0 до 1 (double, а не int. Мы можем проверить, находится ли я между 0 и c [0], return 1. если я находится между c [ 1] и c [2] возвращают 2... вплоть до neg


for(j=0; j < n=1;j++)
   if(i %lt;= c[j]) return i+1

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

Ответ 13

<?php 
//get random number between 1 and 10,000
$random = mt_rand(1, 10000); 
?>