Функция Javascript для генерации случайных целых чисел с неоднородными вероятностями
В javascript (или jquery) есть простая функция, которая имеет четыре целых числа со своими значениями вероятности: 1 | 0,41, 2 | 0,29, 3 | 0,25, 4 | 0,05
как я могу сгенерировать эти четыре числа с учетом их вероятностей?
Этот вопрос очень похож на тот, который размещен здесь:генерировать случайные целые числа с вероятностями
ОДНАКО решение размещено там:
function randomWithProbability() {
var notRandomNumbers = [1, 1, 1, 1, 2, 2, 2, 3, 3, 4];
var idx = Math.floor(Math.random() * notRandomNumbers.length);
return notRandomNumbers[idx];
}
говорится в комментарии "динамически создавать notRandomNumbers (учитывая числа и их вес / вероятность)"
Этого недостаточно для моих нужд. Это хорошо работает, когда вероятности, скажем, 10%, 20%, 60%, 10%.
В этом случае создание notRandomNumbers с требуемым распределением легко, а размер массива небольшой. Но в общем случае, когда вероятности могут быть примерно 20,354%, 30,254% и т. Д., Размер массива был бы огромным, чтобы правильно смоделировать ситуацию.
Есть ли чистое решение этой более общей проблемы?
РЕДАКТИРОВАТЬ: Спасибо, Георг, решение принято, вот моя окончательная версия, что может быть полезно для других. Я разделил вычисление совокупного в отдельную функцию, чтобы избежать дополнительных сложений при каждом вызове, чтобы получить новое случайное число.
function getRandomBinFromCumulative(cumulative) {
var r = Math.random();
for (var i = 0; i < cumulative.length; i++) {
if (r <= cumulative[i])
return i;
}
}
function getCummulativeDistribution(probs) {
var cumulative = [];
var sum = probs[0];
probs.forEach(function (p) {
cumulative.push(sum);
sum += p;
});
// the next 2 lines are optional
cumulative[cumulative.length - 1] = 1; //force to 1 (if input total was <>1)
cumulative.shift(); //remove the first 0
return cumulative;
}
function testRand() {
var probs = [0.1, 0.3, 0.3, 0.3];
var c = getCummulativeDistribution(probs);
console.log(c);
for (var i = 0; i < 100; i++) {
console.log(getRandomBinFromCumulative(c));
}
}