【问题标题】:How is randomness achieved with Math.random in javascript?javascript 中的 Math.random 如何实现随机性?
【发布时间】:2011-01-21 14:33:19
【问题描述】:

如何在 JavaScript 中使用 Math.random 实现随机性?我做了一些随机选择大约 50 个不同选项的东西。我想知道使用 Math.random 来获得随机性应该有多舒服。

【问题讨论】:

  • @David:你知道这不是真正的随机性。归因于 John von Neumann:“任何考虑产生随机数字的算术方法的人当然都处于犯罪状态。” 他们使用的是 PRNG。伪随机数生成器。
  • @cocotwo:这并不意味着所有的 JS 都必须是伪随机的,从下面 Bob 发布的规范来看,它可以是真正的随机。使用真正的 RNG 取决于实现,这不像以前那么困难。
  • 正如下面的一些答案所说,这真的取决于你想做什么。我怀疑 99% 的情况,Math.random 没问题,但它可能是可以预测的。

标签: javascript random


【解决方案1】:

来自规格:

随机():

返回一个带正数的数值 符号,大于或等于 0 但 小于 1,随机或伪选择 随机与近似均匀 在该范围内分布,使用 依赖于实现的算法或 战略。这个函数不需要 论据。

所以答案是这取决于您使用的 JavaScript 引擎。

我不确定是否所有浏览器都使用相同的策略,或者不幸的是该策略是什么

对于您的目的应该没问题。只有当你做大量的数字时,你才会开始看到一个模式

【讨论】:

  • @cocotow 等人。我想知道天气是否伪随机性好不好?就像我猜想它对维加斯或科学来说不够好,但它足以满足日常需求吗? (我做了一些事情,它将根据可能的决定列表为我做出决定。
  • 对于日常需求来说已经足够好了,这就是 Javascript 的 Math.random() 的用途。没关系。
  • @JohnFeminella 请定义“日常需求”
  • @Bob 这只是关于种子的。不是它使用的引擎。
  • @user877329:如果您想要一个不会用作熵源的随机数(例如用于加密目的,或者您绝对需要保证随机性,例如在赌场),那么@987654322 @很好。否则,不要使用它。
【解决方案2】:

100% 随机,足以满足您的目的。它是按时间播种的,所以每次运行它都会得到不同的结果。

将此粘贴​​到您的浏览器地址栏中...

javascript:alert(Math.random() * 2 > 1);

然后按 [Enter] 几次...我得到“真、假、假、真” - 足够随机 :)

【讨论】:

  • 您的代码示例没有显示随机生成器的随机性,因为您引入了倾斜。它将导致比真值更多的假值。一个非常细微的区别,但仍然是一个例子,说明如何通过错误的使用来降低随机性的质量。
  • 是的...但是如果我有 50 个复选框...即使是我提供的 sample 也足以解决 David 的问题。
【解决方案3】:

具体的实现当然会因浏览器而有所不同,但它们都使用某种伪随机数生成器。虽然它不是真正随机的,但对于所有一般用途来说肯定足够好。

如果您将它用于需要非常好的随机性的事情(例如加密或模拟游戏中的机会游戏),您应该只担心随机性,但无论如何您几乎不会使用 Javascript。

【讨论】:

    【解决方案4】:

    这有点矫枉过正......但是,我无法抗拒这样做:)

    您可以在浏览器地址栏中执行此操作。它生成一个介于 0 和 4 之间的随机数,100000 次。并输出每个数字生成的次数以及一个随机数跟随另一个随机数的次数。

    我在 Firefox 3.5.2 中执行了这个。所有的数字似乎都差不多——表明没有偏差,并且数字的生成方式没有明显的模式。

    javascript:
    var max = 5;
    var transitions = new Array(max);
    var frequency = new Array(max);
    for (var i = 0; i < max; i++)
    {
         transitions[i] = new Array(max);
    }
    var old = 0, curr = 0;
    for (var i = 0; i < 100000; i++)
    {
       curr = Math.floor(Math.random()*max);
       if (frequency[curr] === undefined) 
       {
          frequency[curr] = -1;
       }
       frequency[curr] += 1;
       if (transitions[old][curr] === undefined)
       {
          transitions[old][curr] = -1;
       }
       transitions[old][curr] += 1;
       old = curr;
    }
    alert(frequency);
    alert(transitions);
    

    【讨论】:

    • 这一点也不夸张——完全不够。查看分布并不能告诉您太多关于熵质量的信息,正如其他人所说,确切的行为取决于实现,因此测试 Firefox 3.5.2 并不能说明一般情况。
    【解决方案5】:

    如果您不集中合并和使用结果,例如用于 OAuth,则使用 Math.random() 很好。

    例如,我们的网站使用 Math.random() 生成随机“nonce”字符串以用于 OAuth。最初的 JavaScript library 通过使用 Math.random() 从预定列表中选择一个字符来做到这一点:即

    for (var i = 0; i < length; ++i) {
        var rnum = Math.floor(Math.random() * chars.length);
        result += chars.substring(rnum, rnum+1);
    }
    

    问题是,用户得到重复的 nonce 字符串(即使使用 10 个字符长度 - 理论上 ~10^18 个组合),通常在几秒钟内。我猜这是由于 Math.random() 从时间戳播种,正如其他海报之一提到的那样。

    【讨论】:

    • +1 用于描述基于时间戳的播种如何在并发环境中生成重复数字。
    猜你喜欢
    • 2010-11-06
    • 2014-04-30
    • 2015-08-18
    • 2016-10-28
    • 1970-01-01
    • 1970-01-01
    • 2020-09-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多