对于Math.random
的不同JavaScript实现:
抛开记忆和长度问题,以下最终会有一个永远重复的数字序列(例如,它只取决于内部种子,当种子回到它的起始点时,数字会重复)?
sequence = Math.random();
while(true){
sequence += ', ' + Math.random();
}
每个客户端是否具有相同的重复序列(例如,客户端不将特定于客户端的数据合并到随机数生成过程中)?
我问,因为如果可能的数字序列是一个有限的子集,像generating UUIDs with Math.random这样的事情将有更大的碰撞机会。
答案 0 :(得分:5)
阅读MDN:
注意:Math.random()不提供加密安全随机数。不要将它们用于与安全相关的任何事情。改为使用Web Crypto API,更确切地说是window.crypto.getRandomValues()方法。
我认为,碰撞最终是可能的。
答案 1 :(得分:2)
This mdn doc for Math.random()
说你不能依靠这是真正的安全。
但是你仍然可以尝试另一种建议的window.crypto.getRandomValues()
,但在我写这篇文章时,它仍然是实验性的。
实现选择随机数的初始种子 生成算法;它不能被用户选择或重置。
注意:Math.random()不提供加密安全随机 数字。不要将它们用于与安全相关的任何事情。使用网络 相反,加密API,更确切地说是 window.crypto.getRandomValues()方法。
答案 2 :(得分:2)
它主要取决于底层系统的种子生成器。如果两个客户端具有相同的确切种子,则序列将最终相同...通常。不同的实现之间可能存在细微差别,但默认情况下依赖于Java中的实现:Dig this SO question for additional info。
一般来说,种子是“更好一点”,也就是说比一个时间戳稍微“更随机”。
具体做法是:
Windows上的 V8
将使用两个不同的s_rand
调用和位算术来获取生成器的种子。如果存在/dev/urandom
,则会使用它。 urandom
非常好,因为它不仅仅使用unix时间戳而是环境噪音。如果两个选项都不可用,V8将只使用不同的时间戳并以数学方式组合它们。但是,随机数的序列不是直接从Java中提取的,并且可能与FireFox客户端的序列完全相同,因为下一个随机数使用不同的数学公式。
Firefox做的事情非常相似,看起来他们从Java中解除了这个定义。至于种子,它的生成与V8的生成非常相似,当它可用时在s_rand
上使用/dev/urandom
,当它们都不可用时,使用时间戳回落。
总而言之,这一代是“伪随机”,如果下一个随机数的计算是相同的(Chrome和Firefox略有不同),并且两个序列以相同的精确种子开始,那么当然,这两个客户将拥有完全相同的数字序列。从统计数据来看,这种情况发生的可能性微不足道,但可以想象,它确实可能发生。
挖掘以下来源以获得更深入的统计数据,数学上的善良。
来源:
答案 3 :(得分:0)
所有随机数发生器都需要种子;否则它们只是一个似乎有点随机但最终会重复的数字列表。 Javascripts Math.Random()不接受种子作为参数,而是依赖于内置的种子生成器。即使它是一个伪随机数生成器,因为没有人能控制种子实际启动的位置,Math.random()不应该有任何可预测的模式。
答案 4 :(得分:-1)
不,虽然计算中的任何内容都不是真正随机的,但用于创建这些“随机”数字的算法会让它看起来像是随机的,所以你永远不会得到重复模式。大多数(我不确定Math.random)随机函数将得到当前时间戳并将其作为其过程的一部分使用,这是在这种情况下您不会重复数据的主要原因之一。