LINUX.ORG.RU

Сгенерировать случайные числа с неравномерным распределением

 rand,


0

1

Из-за пробелов в математическом образовании туплю уже час и ничего не могу придумать. У меня есть некоторый упорядоченный набор чисел, скажем S = [32, 16, 8, 4]. Я хочу случайным образом получить (целочисленный) индекс в интервале [0,3], но так, чтобы вероятность его получения была взвешена соответственно S. То есть чтобы из 60-ти раз я 32 раза получил 0, 16 раз 1 и т. д. Реализовывать буду на C, но это не существенно.



Последнее исправление: float (всего исправлений: 1)

Делаешь массив Z где элемент i равен сумме от S0 до S_i. Генерируешь случайное число в интервале [Z_0;Z_n] смотришь в какой интервал оно попало, это и будет индекс.

crowbar
()
Ответ на: комментарий от crowbar

Я когда отправил пост, пошел покурить, и не успел выйти на улицу, как стало ясно, что надо генерировать обычный rand() от 0 до 60 и смотреть, не оказался ли он например между 0 и 31. Действительно тривиально. Сейчас надо придумать что-то вместо перебора всех интервалов. И идти спать, наконец.

float
() автор топика
Ответ на: комментарий от float

Ну если их в самом деле всего 60, то можно тупо статический массив завести на 60 элементов и генерить индекс.

anonymous
()

из 60-ти раз я 32 раза получил 0, 16 раз 1 и т. д.

примерно сие называется равномерным распределением, только чуть подшаманить с коэффициентами.

arkhnchul ★★★
()
Ответ на: комментарий от float

Можно постооить аналитическую функцию, если начальные веса заданы функцией а не таблицей.

AIv ★★★★★
()
Ответ на: комментарий от unikum

Парсить ещё один чужой проект? Не, спасибо :-)

float
() автор топика
Ответ на: комментарий от quickquest

Т.к. оказалось, что относительные частоты заданы необязательно упорядоченно, а их сортировка связана с некоторыми побочными эффектами, то по этой ссылке на первый взгляд описывается как раз то чему я не знал названия, сенькью.

float
() автор топика

То есть чтобы из 60-ти раз я 32 раза получил 0, 16 раз 1 и т. д

может из 64х раз

32 раза 0,

16 раз 1

8 раз 2

4 раза 3

2 раза 4

1 раз 5

не? Ты уж определись, да?

Ну и это реализуется присваиванием каждому диапазону своего вес и суммой. Вот простой пример:

из 3х раз:

0 два раза

1 один раз

получаем число 0,1,2

если 0 или 1 =>0

иначе =>1.

emulek
()
Ответ на: комментарий от float

Я когда отправил пост, пошел покурить, и не успел выйти на улицу, как стало ясно, что надо генерировать обычный rand() от 0 до 60 и смотреть, не оказался ли он например между 0 и 31. Действительно тривиально. Сейчас надо придумать что-то вместо перебора всех интервалов. И идти спать, наконец.

вот только число 60 непонятно откуда у тебя... А так всё правильно.

emulek
()
Ответ на: комментарий от float

в общем случае

1. для каждого диапазона считается вес

2. считается сумма всех весов sum

3. считается сл. число 0..sum =>x

4. в цикле обходим все веса и суммируем их в sum2 до тех пор, пока sum2 < x.

emulek
()
Ответ на: комментарий от LeninGad

двоичный поиск.

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

emulek
()
Ответ на: комментарий от crowbar

ты про то, что 32+16+8+4==60? я в курсе. Это кривое распределение, и не имеет смысла IRL. Наверное ТС его как пример привёл, да?

emulek
()
Ответ на: комментарий от anonymous

Объёмный материал, пушка для моего воробья, но выглядит вроде толково. Некруткин крут. Положил в закрома, вдруг пригодится для кругозора. Спасибо.

float
() автор топика
Ответ на: комментарий от float

стало ясно, что надо генерировать обычный rand() от 0 до 60

Лучше не используйте rand(). Системный jrand48() генерирует существенно более качественный ряд. Правда, и он не во всех случаях может подойти.

Sorcerer ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.