JavaScript 模拟具有不同概率的事件

例子

有时,您可能只需要模拟具有两个结果(可能具有不同概率)的事件,但是您可能会发现自己处于需要许多具有不同概率的可能结果的情况下。假设您要模拟一个事件,该事件具有六个同样可能的结果。这很简单。

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

// 模拟公平死亡
console.log("滚了 "+(simulateEvent(6)+1));  // 滚了 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;
        }
    }
    
    // 除非概率之和小于1,否则永远不会达到
    // 由于全部为零或某些为负概率
    return -1;
}

// 模拟加权骰子,其中6的概率是其他任何面孔的两倍
// 使用可能性的倍数
console.log("滚了 "+(simulateEvent([1,1,1,1,1,2])+1));  // 滚了 1

// 使用概率
console.log("滚了 "+(simulateEvent([1/7,1/7,1/7,1/7,1/7,2/7])+1));  // 滚了 6

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

var rewards = ["gold coin","silver coin","diamond","god sword"];
var likelihoods = [5,9,1,0];
// 最不可能拿到神剑的人(0/15 = 0%,永不),
// 最有可能获得银币的机会(9/15 = 60%,超过一半的时间)

// 模拟事件,记录奖励
console.log("你得到一个 "+rewards[simulateEvent(likelihoods)]);  // 你得到一个 silver coin