LINUX.ORG.RU

Генерировать числа с заданной вероятностью

 , , , ,


0

1

Допустим есть вектор с целыми числами от 0 до 6 включая. У меня есть гуй где напротив каждого числа от 0 до 6 включая стоит число от 0.00 до 1 (вероятности) причем в сумме эти 7 чисел дают 1цу. Как сделать генератор чтобы выдавал числа от 0 до 6 включая с этими заданными вероятностями и как бы еще сделать чтобы гуй при изменении чисел вероятностей в ячейках как-то нормировал сумму всех вероятностей в 1цу?



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

Как сделать генератор чтобы выдавал числа от 0 до 6 включая с этими заданными вероятностями

Рассматривай это как последовательные интервалы от 0 до единицы. Тогда обычный равномерный рандом от 0 до 1 даст нужный эффект.

Т.е. пусть A наступает с вероятностью 0,1, B - 0,3 и C - 0,6. Тогда если random дает от 0 до 0,1, то выпало A. Если random дает от 0,1 до 0,4, то это B. Если random дает от 0,4 до 1, то C.

kss ★★★★★
()

Просто генерируете рандомайзером список чисел, например пусть будет .5, .3, .8; затем их складываете, получается число большее единицы, в данном случае 1.6, и затем делите .5/1.6 , .3/1.6 и т.д, таким образом сумма полученных результатов будет равна 1.00.

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

Ещё может быть вариант, что у двух чисел одинаковая вероятность, скажем А и Б - 0.25.

Тут нужен массик вероятнсотей.

И каждая вероятность это массив значений, которые могу выпасть.

Т.е. в начале рандом вероятности, потом рандом номера значения в массиве, если число значений одно - возвращай его.

kostik87 ★★★★★
()
Последнее исправление: kostik87 (всего исправлений: 2)
Ответ на: комментарий от kostik87

А без разницы, алгоритм тот же. A и Б по 0,25, В - 0,5. Тогда для A random от 0 до 0,25, а для Б – от 0,25 до 0,5. В, соответственно, от 0,5 до 1. Тут единственная проблема – сообразить как корректно концы отрезков включать/не включать, чтобы не было двойного счёта и никакое число из отрезка не выпало.

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

Ты упрошаешь.

Смотри, допусти, А - 0.1, Б - 0.12, С - 0.03, В - 0.25, Г - 0.2, Д - 0.25, Е - 0.05.

И что ты все это будешь пересчитывать?

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

Тут единственная проблема – сообразить как корректно концы отрезков включать/не включать, чтобы не было двойного счёта и никакое число из отрезка не выпало.

Если будет массив вероятностей с массовом значений, то и соображать не придется, включать или ее включать.

UPD:

Хотя да, ты прав. То, что я предложил неправильно.

Твой вариант правильнее.

Включать верхнюю границу нужно к текущему диапазону.

kostik87 ★★★★★
()
Последнее исправление: kostik87 (всего исправлений: 2)
Ответ на: комментарий от kss

Рассматривай это как последовательные интервалы от 0 до единицы. Тогда обычный равномерный рандом от 0 до 1 даст нужный эффект.

Т.е. пусть A наступает с вероятностью 0,1, B - 0,3 и C - 0,6. Тогда если random дает от 0 до 0,1, то выпало A. Если random дает от 0,1 до 0,4, то это B. Если random дает от 0,4 до 1, то C.

Поддержу.

Когда-то занимался вопросами моделирования, а там получить генератор с нужным распределением - обычная задача. Типовое решение - на основе равномерного генератора путем функционального преобразования получаешь нужное.

Psilocybe ★★★★
()
Последнее исправление: Psilocybe (всего исправлений: 1)
Ответ на: комментарий от kss

Всё правильно, единственное, генератор должен быть равномерным, по-хорошему надо тестировать. Особенно если значений мало и вероятности заданные пользователем малы. Ну и это, Вихрь Мерсенна (а это он лежит в большинстве случаев внутри библиотек), хоть и хорош, но, например, для криптографии не годится, так что в зависимости от того куда его случайные числа нужны, надо требования к ним составить и проверить на то как результат им соответствует.

peregrine ★★★★★
()
Последнее исправление: peregrine (всего исправлений: 1)
Ответ на: комментарий от kostik87

Включать верхнюю границу нужно к текущему диапазону.

«Зачем / почему»? Не включать проще - в лоб ложится на lower_bound(), только единицу правильно обработать остаётся.

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

Если диапазон от 1 до 100 0 верхняя граница.

Если диапазон от 0 до 99, то верхняя граница минус 1.

kostik87 ★★★★★
()

Т.е нужно сгенерировать массив в 100 элементов из массива в 700 элементов (от 0 до 6, каждого по сто)

$random = Get-Random ((0..6) * 100) -Count 100

### Проверка
$random | Group-Object | ft Count, Name

Count Name
----- ----
   12 0
   13 1
   12 2
   20 3
   14 4
   14 5
   15 6
dmitry237 ★★★★
()
Ответ на: комментарий от dmitry237

а может сделать всего 100 элементов где например 20 нулей, 25 единиц и т.д. откуда у нуля будет вероятность 0.2, у единицы 0.25 и уже из этих 100 элементов выбирать равновероятностно?

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

Ну тогда это будет статическая вероятность. Можно конечно 25 нулей, 19 единиц и т.д, чтобы в результате было 100 элементов. Кстати это не гарантирует большую вероятность выбора, иногда из семи цифр несколько раз подряд выпадает одна и та же. Можно вообще сделать так, чтобы выпадала одна и таже последовательнось, например:

$seed = 1                      
$a = [random]::new($seed)
0..9 | % { $a.next(0,6) }

# т.е. сид (seed) уже заранее предопределяет "произвольность"
# это рандомность по-Net'овски
1
0
2
4
3
2
2
5
0
3
dmitry237 ★★★★
()
Ответ на: комментарий от bad_master

мне на плюсах надо или на крайняк на СИ

Там делов то на 5 копеек: вектор (или массивчик) из N-1 элементов, drand48() + lower_bound(). А вы тут развели непонятно что.

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

Так это же и есть нормирование по теории обработки информации или цифровой обработки сигналов

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

на СИ

Сименс Ангстрем Моль Сантиметр Ом Зиверт Джоуль Ампер Йоттапаскаль

i-rinat ★★★★★
()
Ответ на: комментарий от bad_master

ну всё таки на плюсцах бы, я пьяный два дня не могу вникать в ваши комменты и кодить

Дык - а кто здесь «трезвый» :) Потом почитаете. Всё тривиально. Вам уже несколько раз подсказали (не только я) «что делать и как дальше жить».

ПыСы. тынц

ПыПыСы. А вот «домашку» я за Вас делать не собираюсь.

bugfixer ★★★★★
()
Последнее исправление: bugfixer (всего исправлений: 2)

У меня для Вас гораздо более интересная задачка:

Колода карт. Каждый раз когда вытягивают «красную» - Вам рубль, «чёрную» - с Вас рубль. Вопрос - когда остановиться? @AntonI - молчи :)

ПыСы: возможно Вы не осознаёте, но задачка со вполне себе практическим применением. Так многие вещи price’ятся…

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

Я тож не въехал зачем lower_bound:-(

Мы люди простые, обычно rand_r с правильным множителем хватает. Правда если копнуть глубже то конечно не хватает, есть всякие изощренные алгоритмы со сложными аффторами, никак запомнить не могу - старый стал. Но там и диапазон из коробки задается.

Вообеще я не злой и могу для ТС это сделать на плюсцах. Но это будет очень дорого стоить:-)

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

Я анекдот расскажу от Виктора Соломоновича Рябенького.

В казино лас вегаса приходит платиновая блондинка с кукольным личиком, подходит к рулетке и ставит все что есть на 22. Выигрывает, ставит весь выигрыш на 22, выигрывает, там уже дофига так. Опять ставит все что есть на 22. Крупье говорит – мадмуазель, с точки зрения теории вероятности третий подряд выигрышь исключен, подумайте! – нет говорит блондинка, все на 22!

Снова выигрывает, все в шоке. Выходит владелец, говорит – мадмуазель, это казино Ваше и все у меня есть тоже Ваше, я сейчас пойду и застрелюсь, Вы мне только объясните - КАК? КАК ВЫ ЭТОГО ДОБИЛИСЬ?!

Все просто - говорит блондинка - сегодня седьмое число, я остановилась в седьмом номере и ехала сюда на такси номер семь. – Ну и что?! – Ну как вы не понимаете, ведь семью три двадцать два!

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

Вообсче то ТС не этого хочет:-)

Чего товарищ хочет - вне пределов моего разума. Либо всё слишком просто, либо я чего то не понимаю…

bugfixer ★★★★★
()
Последнее исправление: bugfixer (всего исправлений: 1)
Ответ на: комментарий от bugfixer

А, я сходу задачу ТС неправильно понял. Она оказывается не такая простая, можно и помочь:-)

Для шести чисел можно и перебором искать, а ты предлагаешь половинным делением? Для произвольного распределения емнип мы конечно половинное деление юзали.

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

А, я сходу задачу ТС неправильно понял. Она оказывается не такая простая

Ок. Я это вижу как отбражение. Может чего неправильно прочитал…

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

ТС хочет любви и взаимопонимания генератор случайных чисел с заданным из гуя распределением (произвольным).

Делается это просто - распределение интегрируется (берется первообразная) а затем от него строится обратная функция, в которую уже подсовывается чиселка с равномерным распределением. Но обратная функция разумеется получается на неравномерной сетке и вот тут самый цирк.

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

Фсе правильно, это я затупил сначала.

AntonI ★★★★★
()

Если ооочень в в лоб то как то так, только доработай проверку чтобы значения не были нулевыми, а то будет ошибка деления на ноль. Вероятность сам прикрутишь. Нормировать стоит как и ниже у тебя есть 1,0 вычитаешь из него всё что наизменял, остаток распределяешь как ниже по остальным.

#include <stdio.h>
#include <time.h>
#include <stdlib.h>


int main(int argc, char *argv[])
{
     srand(time(NULL));
     int a1 = random() % 100;
     int a2 = (100 - a1);
     int a3 = random() % a1; a1-=a3;
     int a4 = random() % a2; a2-=a4;
     int a5 = random() % a3; a3-=a5;
     int a6 = random() % a4; a4-=a6;
     int a7 = random() % a1; a1-=a7;

     int div = 100;

     float f1 = (float)a1 / div;
     float f2 = (float)a2 / div;
     float f3 = (float)a3 / div;
     float f4 = (float)a4 / div;
     float f5 = (float)a5 / div;
     float f6 = (float)a6 / div;
     float f7 = (float)a7 / div;


     printf("%d %d %d %d %d %d %d [%d]\n"
             "%f %f %f %f %f %f %f [%f]\n",
     a1,a2,a3,a4,a5,a6,a7,a1+a2+a3+a4+a5+a6+a7,f1,f2,f3,f4,f5,f6,f7,
     f1+f2+f3+f4+f5+f6+f7
            );
    return 0;
}

dron@gnu:~$ gcc cc.c
dron@gnu:~$ ./a.out 
Исключение в операции с плавающей точкой
dron@gnu:~$ ./a.out 
26 5 36 2 25 3 3 [100]
0.260000 0.050000 0.360000 0.020000 0.250000 0.030000 0.030000 [1.000000]
dron@gnu:~$ 
LINUX-ORG-RU ★★★★★
()
Последнее исправление: LINUX-ORG-RU (всего исправлений: 1)
Ответ на: комментарий от LINUX-ORG-RU

без комментариев в коде не очень понятно

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