【问题标题】:Will Math.random repeat?Math.random 会重复吗?
【发布时间】:2015-01-24 23:54:53
【问题描述】:

对于Math.random的不同JavaScript实现:

抛开内存和长度问题不谈,以下是否最终会有一个永远重复的数字序列(例如,它仅依赖于内部种子,当该种子回绕到其起点时,数字会重复)?

sequence = Math.random();
while(true){
    sequence += ', ' + Math.random();
}

每个客户端是否具有相同的重复序列(例如,客户端不会将特定于客户端的数据合并到随机数生成过程中)?


我问是因为如果可能的数字序列是一个有限的子集,像generating UUIDs with Math.random 这样的东西会有更大的冲突机会。

【问题讨论】:

  • 我不认为每个客户端都可以有相同的重复序列,假设序列意味着一系列数字。您最终可能会得到一个重复的数字,但序列重复似乎不太可能
  • 嗯,有可能两个客户端拥有完全相同的种子(它们的时间戳完全相同),但可能性很小......当然。我想知道 Spidermonkey 和 V8 的种子生成器是什么...
  • 是的,保证重复,并在给定相同种子的情况下重复相同的序列。不要使用 Math.random() 来生成 UUID——你需要一个加密的 RNG。

标签: javascript random


【解决方案1】:

来自阅读MDN

注意:Math.random() 不提供加密安全的随机数。不要将它们用于与安全相关的任何事情。改用 Web Crypto API,更准确地说是 window.crypto.getRandomValues() 方法。

我会假设,碰撞最终是可能的。

【讨论】:

    【解决方案2】:

    This mdn doc for Math.random() 表示您不能依靠它来确保真正的安全。

    但您仍然可以尝试建议的替代方案 window.crypto.getRandomValues(),但在我写这篇文章时,它仍处于试验阶段。

    实现选择初始种子为随机数 生成算法;用户不能选择或重置它。

    注意:Math.random() 不提供加密安全随机 数字。不要将它们用于与安全相关的任何事情。使用网络 取而代之的是 Crypto API,更准确地说是 window.crypto.getRandomValues() 方法。

    【讨论】:

      【解决方案3】:

      它主要取决于底层系统的种子生成器。如果两个客户端具有相同的确切种子,那么序列最终将是相同的......通常。不同实现之间可能存在细微差别,但默认使用 Java 中的实现:Dig this SO question for additional info

      一般来说,种子比时间戳要“好一点”,也就是稍微“更随机”。

      具体来说:

      Windows 上的V8 将使用两个不同的s_rand 调用和位运算来获取生成器的种子。如果/dev/urandom 存在,它将使用它。 urandom 非常好,因为它不仅使用 unix 时间戳,还使用环境噪声。如果这两个选项都不可用,V8 将只使用不同的时间戳并将它们进行数学组合。但是,随机数序列并不是直接从 Java 中提取的,并且可能不会具有与 FireFox 客户端完全相同的序列,因为获取下一个随机数使用不同的数学公式。

      Firefox 做了非常相似的事情,看起来他们从 Java 中提升了定义。至于种子,同样,它的生成与 V8 的生成非常相似,当它可用时在 windows /dev/urandom 上使用 s_rand,当两者都不可用时使用时间戳。

      总而言之,生成是“伪随机”,如果下一个随机数的计算是相同的(Chrome 和 Firefox 在这方面略有不同)并且两个序列以相同的确切种子开始,那么当然,这两个客户端将具有完全相同的数字序列。从统计上看,这种情况发生的可能性微乎其微,但可以想象,它确实会发生。

      挖掘以下资源以获得更深入的统计、数学优势。

      来源:

      1. Firefox implementation of math_random
      2. V8's implementation
      3. Breaking the Java random number generator
      4. Predicting the Seed in JS

      【讨论】:

        【解决方案4】:

        所有随机数生成器都需要一个种子;否则它们只是一个看似随机但最终会重复的数字列表。 Javascripts Math.Random() 不接受种子作为参数,而是依赖于内置的种子生成器。即使它是一个伪随机数生成器,因为没有人可以控制种子实际从哪里开始,Math.random() 不应该有任何可预测的模式。

        查看http://bocoup.com/weblog/random-numbers/ 了解更多信息。

        【讨论】:

          【解决方案5】:

          不,虽然计算中没有什么是真正随机的,但用于创建这些“随机”数字的算法使其看起来是随机的,因此您永远不会得到重复的模式。大多数(我不确定 Math.random)随机函数将获取当前时间戳并将其用作其过程的一部分,这是在这种情况下您不会获得重复数据的主要原因之一。

          【讨论】:

          • 我假设如果伪随机生成器是用相同的种子构造的,那么生成的随机数将完全相同。每个客户端之间的底层功能不会改变,唯一的区别是种子,对吧?因此,拥有相同的种子会产生相同的序列。我想最终种子生成是这个问题的关键。
          • 是的,这完全取决于种子的生成方式,例如,某些函数可能会使用标头参数以及时间来使其更加随机,但是与任何数学方程式一样,如果您输入相同的输入你得到相同的输出。
          猜你喜欢
          • 1970-01-01
          • 2015-09-24
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多