【问题标题】:JavaScript biased results?JavaScript 有偏见的结果?
【发布时间】:2017-05-29 13:50:39
【问题描述】:

假设我在一个数组中有两个项目,例如:

["a", "b"]

现在假设我有一个名为 random 的函数,它从这个数组中选择一个随机项目,例如:

function random() {
  // do awesome random stuff here...
  return random_choice;
}

如何让random 函数在 80% 的时间和 20% 的时间返回 "a""b"

我不太确定这叫什么,但例如,如果我运行 console.log(random()); 10 次,结果应该看起来像这样:

>>> "a"
>>> "a"
>>> "a"
>>> "a"
>>> "a"
>>> "a"
>>> "a"
>>> "a"
>>> "b"
>>> "b"

"a" 得到 8/10 次返回,"b" 得到 2/10 次返回。

注意:上面的“结果”只是一个例子,我知道它们并不总是那么完美,也不必如此。

【问题讨论】:

    标签: javascript jquery arrays random


    【解决方案1】:

    最快的答案是:

    var result = Math.random() >= 0.2 ? "a" : "b";
    

    【讨论】:

    • 因为 0 包含在内而 1 不包含在内,所以您的 Math.random() > 0.2 ? 'a':'b' 表示有 79% 的机会选择 a 和 21% 的机会选择 b。我认为您的意思是>=,这将使其达到 OP 中所需的 80/20。
    • @vol7ron 我猜它会更像 79.9999999999999999% 但你说得对:)
    • @MichałSałaciński 是的,这会影响到 ;​​)
    【解决方案2】:

    任意数量值的广义解

    function biasedRandomSelection(values, probabilities) {
        // generate random number (zero to one).
        var rand = Math.random();
    
        // cumulative probability, starting at 0
        var cumulativeProb = 0;
    
        // loop through the raw `probabilities` array
        for(var i=0; i<probabilities.length; i++) {
            // increment cumulative probability
            cumulativeProb += probabilities[i];
    
            // test for `rand` being less than the cumulative probaility;
            // when true, return return the corresponding value.
            if(rand < cumulativeProb) return values[i];
        }
    }
    

    这里的诀窍是针对从原始概率得出的滚动“累积概率”进行测试。

    示例调用:

    biasedRandomSelection(['a', 'b'], [0.8, 0.2]); // as per the question
    biasedRandomSelection(['a', 'b'], [0.2, 0.8]); // reversed probailities
    biasedRandomSelection(['a', 'b', 'c', 'd', 'e'], [0.4, 0.1, 0.2, 0.2, 0.1]); // larger range of values/probailities
    

    Demo

    正如所写,biasedRandomSelection() 不执行范围检查。

    更安全的版本会检查:

    • valuesprobabilities 是一致的
    • probabilities 的总和为 1。

    【讨论】:

      【解决方案3】:

      Math.random() 在 [0;1) 中返回一个数字。只需使用 p &lt; 0.2 / p &lt; 0.8 来获得有偏见的结果,而不是使用无偏见的 p &lt; 0.5

      如果您希望前 N 个结果具有确定性,则可以使用简单的计数器 i++ &lt; N

      【讨论】:

      • 感谢您抽出宝贵时间回答,不胜感激。
      • 仅供参考: [0;1) ,这是否意味着包含 0,不包含 1? (在我的国家,它会写成 [0;1[ ...这就是我问的原因)
      • @Jonasw 是的,就是这个意思。
      【解决方案4】:

      有点扩展:

      var array="a".repeat(8)+"b".repeat(2);
      var random=()=>array[Math.floor(Math.random()*array.length)];
      
      alert(random());
      

      这也适用于两个以上的结果和所有不同类型的概率。

      请注意,数组并不是真正的数组,而是查找字符串 ..

      http://jsbin.com/besapetidi/edit?console

      【讨论】:

      • 这是让您说“我不敢相信我没有想到这一点”的原因之一?感谢您抽出宝贵时间回答。跨度>
      • @mango 恭喜!您赢得了SO 上最友好、最有动力的 OP! ... ;)
      • 哈哈? 谢谢!这是真的漫长的一天,我能得到的任何帮助都只是WOW
      • 4 as 和 1 b 就足够了。
      • @xufox 这个答案不关注性能,而是关注可理解性......
      猜你喜欢
      • 2017-11-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-03-07
      • 1970-01-01
      • 2017-06-15
      • 1970-01-01
      相关资源
      最近更新 更多