模擬具有不同概率的事件

有時你可能只需要模擬具有兩種結果的事件,可能具有不同的概率,但你可能會發現自己處於需要具有不同概率的許多可能結果的情況。讓我們假設你想模擬一個有六個同樣可能結果的事件。這很簡單。

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