简体   繁体   English

Math.random会重复吗?

[英]Will Math.random repeat?

For the different JavaScript implementations of Math.random : 对于Math.random的不同JavaScript实现:

Putting aside memory and length issues, will the following eventually have an eternally repeating sequence of numbers (eg It only depends on an internal seed, and when that seed wraps back to its starting point the numbers will repeat)? 抛开记忆和长度问题,以下最终会有一个永远重复的数字序列(例如,它只取决于内部种子,当种子回到它的起始点时,数字会重复)?

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

Will each client have the same repeating sequence (eg Clients don't incorporate client-specific data into the random number generation process)? 每个客户端是否具有相同的重复序列(例如,客户端不将特定于客户端的数据合并到随机数生成过程中)?


I ask because if the possible sequence of numbers is a limited subset, things like generating UUIDs with Math.random will have a much greater chance of collision. 我问,因为如果可能的数字序列是一个有限的子集,那么像使用Math.random生成UUID这样的事情将有更大的碰撞机会。

From reading MDN : 从阅读MDN

Note: Math.random() does not provide cryptographically secure random numbers. 注意:Math.random()不提供加密安全随机数。 Do not use them for anything related to security. 不要将它们用于与安全相关的任何事情。 Use the Web Crypto API instead, and more precisely the window.crypto.getRandomValues() method. 使用Web Crypto API,更确切地说是window.crypto.getRandomValues()方法。

I would assume, that collisions are eventually possible. 我认为,碰撞最终是可能的。

This mdn doc for Math.random() says that you can not rely on this to be truly secure. Math.random()这个mdn doc说你不能依赖它来真正安全。

But you could still try the alternative suggested window.crypto.getRandomValues() but at the time I write this, it is still experimental. 但你仍然可以尝试使用另一种建议的window.crypto.getRandomValues()但在我写这篇文章时,它仍然是实验性的。

The implementation selects the initial seed to the random number generation algorithm; 该实现选择初始种子到随机数生成算法; it cannot be chosen or reset by the user. 它不能被用户选择或重置。

Note: Math.random() does not provide cryptographically secure random numbers. 注意:Math.random()不提供加密安全随机数。 Do not use them for anything related to security. 不要将它们用于与安全相关的任何事情。 Use the Web Crypto API instead, and more precisely the window.crypto.getRandomValues() method. 使用Web Crypto API,更确切地说是window.crypto.getRandomValues()方法。

It, mostly, depends on the seed generator of the underlying system. 它主要取决于底层系统的种子生成器。 If two clients have the same exact seed, then the sequence will end up being the same...generally. 如果两个客户端具有相同的确切种子,则序列将最终相同...通常。 There may be slight differences between the different implementations but the default falls back on the implementation in Java: Dig this SO question for additional info . 不同的实现之间可能存在细微差别,但默认情况下是Java中的实现: 挖掘这个问题以获取更多信息

Generally the seed is a "bit better", aka slightly "more random" than just a timestamp. 通常种子是“更好一点”,也就是说比一个时间戳稍微“更随机”。

Specifically: 特别:

V8 on Windows will use two different s_rand calls and bit arithmetic to get the seed for the generator. Windows上的V8将使用两个不同的s_rand调用和位算术来获取生成器的种子。 If /dev/urandom exists, it will use it instead. 如果/dev/urandom存在,它将使用它。 urandom is farely good as it does not simply use a unix timestamp but environmental noise. urandom非常好,因为它不仅仅使用unix时间戳而是环境噪音。 If both options are not available, V8 will just use different time stamps and mathematically combine them. 如果两个选项都不可用,V8将只使用不同的时间戳并以数学方式组合它们。 However, the sequence of random numbers is not directly pulled from Java, and will probably not have the exact same sequence as a FireFox client as getting the next random number uses a different mathematical formula. 但是,随机数的序列不是直接从Java中提取的,并且可能与FireFox客户端的序列完全相同,因为下一个随机数使用不同的数学公式。

Firefox does something very similarly and it looks like they lifted the definition from Java. Firefox做了类似的事情,看起来他们从Java中解除了定义。 As for the seed, again, its generation is very similar to that of V8, using s_rand on windows /dev/urandom when it is available, and falling back on timestamps when neither are available. 至于种子,它的生成与V8的生成非常相似,当它可用时在windows /dev/urandom上使用s_rand ,并且当它们都不可用时回落到时间戳上。

All in all, the generation is "pseudo-random" and if the calculation of the next random number is the same(Chrome and Firefox differ slightly on this) and the two sequences are started with the same exact seed, then of course, the two clients will have the exact same sequence of numbers. 总而言之,这一代是“伪随机的”,如果下一个随机数的计算是相同的(Chrome和Firefox略有不同),并且两个序列以相同的精确种子开始,那么当然,两个客户端将具有完全相同的数字序列。 Statistically, the chances of this happening are insignificant, but conceivably, it indeed can happen. 从统计数据来看,这种情况发生的可能性微不足道,但可以想象,这确实可能发生。

Dig the following sources for some more in depth statistical, mathematical goodness. 挖掘以下来源以获得更深入的统计数据,数学优势。

Sources: 资料来源:

  1. Firefox implementation of math_random Firefox实现math_random
  2. V8's implementation V8的实施
  3. Breaking the Java random number generator 打破Java随机数生成器
  4. Predicting the Seed in JS 在JS中预测种子

All random number generators need a seed; 所有随机数发生器都需要种子; otherwise they are just a list of numbers that seem kind of random but will repeat eventually. 否则它们只是一个似乎有点随机但最终会重复的数字列表。 Javascripts Math.Random() does not accept a seed as an argument and instead relies on a built-in seed generator. Javascripts Math.Random()不接受种子作为参数,而是依赖于内置的种子生成器。 Even though it is a psuedo-random number generator, because no one has control over where the seed actually starts, Math.random() shouldn't have any kind of predictable pattern. 即使它是一个伪随机数生成器,因为没有人能控制种子实际启动的位置,Math.random()不应该有任何可预测的模式。

Check http://bocoup.com/weblog/random-numbers/ for a bit more on this. 有关详细信息,请访问http://bocoup.com/weblog/random-numbers/

No, while nothing in computing is truly random, the algorithms that are used to create these "random" numbers are make it seem random so you will never get a repeating pattern. 不,虽然计算中的任何内容都不是真正随机的,但用于创建这些“随机”数字的算法会使它看起来是随机的,因此您永远不会得到重复模式。 Most (I'm not sure about Math.random) randomising functions will get the current timestamp and use that as part of it's process and this is one of the main reasons you will not get repeating data in this case. 大多数(我不确定Math.random)随机函数将获得当前时间戳并将其用作其进程的一部分,这是在这种情况下您不会重复数据的主要原因之一。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM