模拟具有不同概率的事件

有时你可能只需要模拟具有两种结果的事件,可能具有不同的概率,但你可能会发现自己处于需要具有不同概率的许多可能结果的情况。让我们假设你想模拟一个有六个同样可能结果的事件。这很简单。

function simulateEvent(numEvents) {
    var event = Math.floor(numEvents*Math.random());
    return event;
}

// simulate fair die
console.log("Rolled a "+(simulateEvent(6)+1));  // Rolled a 2

但是,你可能不希望同样可能的结果。假设你有三个结果的列表,表示为百分比或可能性倍数的概率数组。这样的例子可能是加权骰子。你可以重写以前的函数来模拟这样的事件。

function simulateEvent(chances) {
    var sum = 0;
    chances.forEach(function(chance) {
        sum+=chance;
    });
    var rand = Math.random();
    var chance = 0;
    for(var i=0; i<chances.length; i++) {
        chance+=chances[i]/sum;
        if(rand<chance) {
            return i;
        }
    }
    
    // should never be reached unless sum of probabilities is less than 1
    // due to all being zero or some being negative probabilities
    return -1;
}

// simulate weighted dice where 6 is twice as likely as any other face
// using multiples of likelihood
console.log("Rolled a "+(simulateEvent([1,1,1,1,1,2])+1));  // Rolled a 1

// using probabilities
console.log("Rolled a "+(simulateEvent([1/7,1/7,1/7,1/7,1/7,2/7])+1));  // Rolled a 6

你可能已经注意到,这些函数返回一个索引,因此你可以将更多描述性结果存储在数组中。这是一个例子。

var rewards = ["gold coin","silver coin","diamond","god sword"];
var likelihoods = [5,9,1,0];
// least likely to get a god sword (0/15 = 0%, never),
// most likely to get a silver coin (9/15 = 60%, more than half the time)

// simulate event, log reward
console.log("You get a "+rewards[simulateEvent(likelihoods)]);  // You get a silver coin