Если вам известна вероятность каждого события, вам нужно отобразить эти вероятности в диапазоне от 0 до 100 (или от 0 до 1, если вы хотите использовать действительные числа и вероятности).
Итак, в приведенном выше примере 12 Cs. С1 составляет 4/12 или ~ 33%,
C2 составляет 2/12 от ~ 17%, C3 составляет 5/12 или ~ 42% и C4 составляет 1/12 или ~ 8%.
Обратите внимание, что все это составляет до 100%. Поэтому, если мы выберем случайное число от 0 до 100, мы можем отобразить C1 на 0-33, C2 на 33-50 (на 17 больше значения C1), C3 на 50-92 и C4 на 92-100.
Оператор if может сделать выбор:
r = rand() # between 0-100
if (r <33)
return "C1"
elsif (r < 50)
return "C2"
elsif (r < 92)
return "C3"
elsif (r < 100)
return "C4"
Если вы хотели больше точности, чем 1 из 100, просто перейдите от 1 до 1000 или любого другого диапазона. Вероятно, лучше использовать целые числа и масштабировать их, чем использовать числа с плавающей запятой, поскольку с плавающей запятой может возникнуть странное поведение, если разброс между значениями становится большим.
Если вы хотите пойти по пути биннинга, как показано выше, вы можете попробовать что-то вроде этого (в ruby, хотя идея более общая):
a = ["C1"]*4 + ["C2"]*2 + ["C3"]*5 + ["C4"]
# ["C1", "C1", "C1", "C1", "C2", "C2",
# "C3", "C3", "C3", "C3", "C3", "C4"]
a[rand(a.length)] # => "C1' w/ probability 4/12
Биннинг будет медленнее, поскольку вам нужно создать массив, но будет проще добавлять альтернативы, поскольку вам не нужно будет каждый раз пересчитывать вероятности.
Вы также можете сгенерировать вышеприведенный код if из представления массива, так что вы просто один раз нажмете на предварительную обработку при создании кода, а затем получите быстрый ответ из созданного кода.