【问题标题】:JS generate random booleanJS 生成随机布尔值
【发布时间】:2016-08-13 20:54:56
【问题描述】:

简单的问题,但我对这里的细微差别很感兴趣。

我正在使用我自己提出的以下方法生成随机布尔值:

const rand = Boolean(Math.round(Math.random()));

每当random() 出现时,似乎总会有一个陷阱——它不是真正随机的,它被某种东西或其他东西所破坏,等等。所以,我想知道:

a) 以上是最佳实践方法吗?

b) 我是不是想太多了?

c) 我是不是在想事情?

d) 有没有更好/更快/更优雅的方式我不知道?

(如果 B 和 C 互斥,也有点兴趣。)

更新

如果有什么不同,我会用它来移动 AI 角色。

【问题讨论】:

  • const rand = Math.random() < 0.5 等效且更简单。
  • 实际上没有什么是随机的,目标是尽可能接近随机。
  • 如果你有 50/50 的机会,math.random 应该足够了。只需为您的种子使用毫秒。
  • 我认为访问网站的时间很随机:D 所以我有这个想法...Boolean(+Date.now()%2)
  • 带 lodash - !!_.random(1)

标签: javascript random boolean


【解决方案1】:

您可以直接比较Math.random()0.5,因为Math.random() 的范围是[0, 1)(这意味着'在0 到1 的范围内,包括0,但不包括1')。您可以将范围分为[0, 0.5)[0.5, 1)

var random_boolean = Math.random() < 0.5;

// Example
console.log(Math.random() < 0.1); //10% probability of getting true
console.log(Math.random() < 0.4); //40% probability of getting true
console.log(Math.random() < 0.5); //50% probability of getting true
console.log(Math.random() < 0.8); //80% probability of getting true
console.log(Math.random() < 0.9); //90% probability of getting true

【讨论】:

  • 我喜欢这个解决方案,因为它可以让你调整真/假的概率
  • 为什么不只使用&lt; 而不是&gt;=Math.random() &lt; 0.5 不包括低半部分的 0.5 和高半部分的 1 - 所以它仍然是 50% 的机会。另外,它更短。在我看来,Math.random() &lt; 0.1Math.random() &gt;= 0.9 更直观地理解为“10% 的可能性”。我想这很挑剔。很好的答案。
  • 我将答案修改为使用&lt;= 运算符而不是&gt;= 以使答案更直观。
  • 现在的答案在语义上不是错误的吗?正如@Aaron Plocharczyk 所描述的,0.5 不应该属于上半部分的概率吗? 0.0 属于下半部分,1.0 不在Math-random() 的 [0,1) 范围内。所以请把&lt;=改成&lt;
  • @bjrne 你是对的;最后一个编辑这个答案的人犯了这个错误。我继续更新答案以反映您的建议,并从 &gt;= 转向 &lt;
【解决方案2】:

如果您的项目有lodash,那么您可以:

_.sample([true, false])

您也可以使用自己的示例函数 (source):

const sample = arr => arr[Math.floor(Math.random() * arr.length)];

【讨论】:

    【解决方案3】:

    要获得更安全的密码值,您可以在现代浏览器中使用crypto.getRandomValues

    示例:

    var randomBool = (function() {
      var a = new Uint8Array(1);
      return function() {
        crypto.getRandomValues(a);
        return a[0] > 127;
      };
    })();
    
    var trues = 0;
    var falses = 0;
    for (var i = 0; i < 255; i++) {
      if (randomBool()) {
        trues++;
      }
      else {
        falses++;
      }
    }
    document.body.innerText = 'true: ' + trues + ', false: ' + falses;

    请注意,crypto 对象是一个 DOM API,因此它在 Node 中不可用,但在 there is a similar API for Node 中可用。

    【讨论】:

    • Math.random() 在很多方面都是出了名的非随机,很好的替代建议
    • 我只是要在这里添加一个小修正,因为我在运行 50 000 000 次后发现它平均生成了 0.78% 左右的零:return a[0]
    • @AmundMidtskog 好电话。我应该输入:a[0] &gt; 127
    • 顺便说一下,您通常可能希望生成比 255 个更多的样本。相反,为了减少数据中的噪声,大约 100,000 甚至数千万,正如其他评论中所建议的那样,如果您希望看到小至 0.78% 的错误。
    【解决方案4】:
    !Math.round(Math.random());
    

    【讨论】:

    • 请格式化这个更有帮助的 (stackoverflow.com/editing-help) 并添加一些解释。仅代码的答案不太受欢迎。添加解释将有助于消除 StackOverflow 是免费代码编写服务的误解。
    • 以上评论没有帮助。
    【解决方案5】:

    Kelvin's answer 给我留下了深刻的印象,我想提出一个非常相似但略有增强的解决方案。

    var randomBoolean = Math.random() < 0.5;
    

    这个解决方案读起来更明显一些,因为&lt;右侧的数字告诉你得到true的概率,而不是得到false的概率,这更容易理解。同样&lt;&gt;= 短一个符号;

    【讨论】:

      【解决方案6】:

      可能更快的解决方案...

      按位运算符方法我只是想到了Math.random() + .5 &gt;&gt; 0~~(Math.random() + .5)。这是一个performance test,供您自行判断。

      let randomBoolean = Math.random() + .5 >> 0;                 //chance of true
      const randomBoolean = chance => Math.random() + chance >> 0; //chance of true
      

      在这种情况下,按位运算符与使用Math.trunc()Math.floor() 基本相同,因此Math.trunc(Math.random() + .5) 也是可行的。

      let randomBoolean = Math.trunc(Math.random() + .5);
      const randomBoolean = chance => Math.trunc(Math.random() + chance);
      

      其他更常见的解决方案

      更常见的获取随机布尔值的方法可能是比较方法,例如 Kelvin's answer 中的 Math.random() &gt;= .5Arthur Khazbs's answer 中的 Math.random() &lt; .5;,它们实际上输出的是真假,而不是 1 和 0。

      let randomBoolean = Math.random() >= .5;                 //chance of false
      const randomBoolean = chance => Math.random() >= chance; //chance of false
      
      let randomBoolean = Math.random()  < .5;                 //chance of true
      const randomBoolean = chance => Math.random() < chance;  //chance of true
      

      使用Math.round(Math.random()) 方法的唯一原因是简单和懒惰。

      【讨论】:

      • 我不确定这是否值得指出,但(.49999999999999997 &gt;= .5) != (.49999999999999997+ .5 &gt;&gt; 0)
      【解决方案7】:

      这个怎么样?

      return Math.round((Math.random() * 1) + 0) === 0;
      

      【讨论】:

      • OP表示他已经用过类似的方法了,不需要发这个了。
      • 为什么要乘以一?
      猜你喜欢
      • 2017-09-05
      • 2023-03-28
      • 2014-10-06
      • 2013-10-12
      • 1970-01-01
      • 2017-10-30
      • 1970-01-01
      • 2012-01-15
      相关资源
      最近更新 更多