【问题标题】:Javascript function to generate random integers with nonuniform probabilities用于生成具有非均匀概率的随机整数的 Javascript 函数
【发布时间】:2015-04-04 05:10:18
【问题描述】:

在 javascript(或 jquery)中是否有一个简单的函数具有四个整数及其概率值:1|0.41、2|0.29、3|0.25、4|0.05

如何在考虑概率的情况下生成这四个数字?

此问题与此处发布的问题非常相似:generate random integers with probabilities

但是那里发布的解决方案:

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% 等的一般情况下,数组大小会很大,无法正确建模。

对于这个更普遍的问题是否有一个干净的解决方案?

编辑:感谢 Georg,解决方案已接受,这是我的最终版本,可能对其他人有用。我已将累积的计算拆分为一个单独的函数,以避免在每次调用时额外添加以获得新的随机数。

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));
    }
}

【问题讨论】:

  • 是的,计算累积分布函数并使用基于其值的区间来获得各个随机数。

标签: javascript jquery random probability


【解决方案1】:

只需累积概率并返回 current_sum &gt;= random_number 的项目:

probs = [0.41, 0.29, 0.25, 0.05];

function item() {
    var r = Math.random(), s = 0;
    for(var i = 0; i < probs.length; i++) {
        s += probs[i];
        if(r <= s)
            return i;
    }
}

// generate 100000 randoms

a = [];
c = 0;
while(c++ < 100000) {
    a.push(item());
}

// test actual distibution

c = {}
a.forEach(function(x) {
    c[x] = (c[x] || 0) + 1;
});

probs.forEach(function(_, x) {
    document.write(x + "=" +  c[x] / a.length + "<br>")
});

【讨论】:

    【解决方案2】:

    创建具有相应权重的第二个并行数组,并使用“轮”算法获取索引。

    function randomWithProbability()
    {
        var notRandomNumbers = [1,2,3,4];
    
        var w = [0.41, 0.29, 0.25, 0.05];
        var placehldr = 0;
        var maxProb = 0.41;
        var index = Math.floor(Math.random() * w.length);
        var i = 0;
    
         placehldr = Math.random() * (maxProb * 2);
        while(placehldr > index )
        {
            placehldr -= w[index];
            index = (index + 1) % w.length
        }
    
        return (notRandomNumbers[index]);
    
    }
    

    这个视频很好地解释了它的工作原理,通过视觉表示更容易理解。 https://www.youtube.com/watch?v=wNQVo6uOgYA

    【讨论】:

      【解决方案3】:

      由于 AJ Walker (Electronics Letters 10, 8 (1974), 127-128; ACM Trans. Math Software 3 (1977), 253-256) 和 Knuth 中的描述,有一个优雅的解决方案只需要一次比较, TAOCP 卷。 2,120-121。 你也可以在这里找到描述,generate random numbers within a range with different probabilities

      【讨论】:

        猜你喜欢
        • 2017-07-16
        • 2014-02-04
        • 2012-02-11
        • 2011-08-23
        • 1970-01-01
        • 1970-01-01
        • 2011-05-31
        • 2012-03-18
        相关资源
        最近更新 更多