真或更好的 Javascript 随机数

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12673691/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 10:59:27  来源:igfitidea点击:

True or better Random numbers with Javascript

javascriptrandom

提问by rlb.usa

I have all kinds of resources that rely on javascript random numbers. However, I've been seeing a lot of problems where random isn't so random because of the way I'm generating random numbers.

我有各种依赖 javascript 随机数的资源。但是,由于我生成随机数的方式,我看到了很多问题,其中随机不是那么随机。

Is there any javascript resource for me to generate true, or just better random numbers?

是否有任何 javascript 资源可供我生成真实的或更好的随机数?

I know that I can interface with Random.org, but what other options do I have?

我知道我可以与 Random.org 交互,但我还有什么其他选择?

I'm using:

我正在使用:

function rand( lowest, highest){
    var adjustedHigh = (highest - lowest) + 1;       
    return Math.floor(Math.random()*adjustedHigh) + parseFloat(lowest);
}

采纳答案by Phil H

Assuming you're not just seeing patterns where there aren't any, try a Mersenee Twister (Wikipedia article here). There are various implementations like this one on github.

假设您不只是看到没有任何模式的模式,请尝试使用 Mersenee Twister(此处为 Wikipedia 文章)。在 github 上有各种像这样的实现。

Similar SO question:

类似的问题:

Seedable JavaScript random number generator

可种子 JavaScript 随机数生成器

If you want something closer to truly random, then consider using the random.org APIto get truly random numbers, although I would suggest only using that to seed, not for every number, as you need to abide by their usage limits.

如果你想要更接近真正随机的东西,那么考虑使用random.org API来获得真正的随机数,尽管我建议只使用它来播种,而不是每个数字,因为你需要遵守它们的使用限制。

回答by David Cary

Tweaking numbers so they "look random"

调整数字使它们“看起来随机”

I agree with Phil H that humans are so good at finding patterns that they often think they see patterns even in "perfectly random" sequences of numbers (clustering illusion, apophenia, gambler's fallacy, etc).

我同意 Phil H 的观点,即人类非常善于发现模式,以至于他们经常认为即使在“完全随机”的数字序列中也能看到模式(聚类错觉、失信症、赌徒谬论等)。

Plots of true random positions generally have lots of clumps and points that "coincidentally" fall very close together, which looks pretty suspicious.

真正随机位置的图通常有很多“巧合”地非常靠近的团块和点,这看起来很可疑。

Artists often take completely randomly generated patterns and "nudge" them to make them appear"more random", even though that careful nudging actually makes the pattern lessrandom (a), (b), (c), (d), etc.

艺术家经常采用完全随机生成的模式并“轻推”它们以使它们看起来“更随机”,即使仔细轻推实际上使模式不那么随机(a)(b)(c)(d)等。

Alternatively, a low-discrepancy sequencesometimes "looks better" than a true random sequence and is much faster to generate.

或者,低差异序列有时比真正的随机序列“看起来更好”,并且生成速度要快得多。

Fast random number generators

快速随机数生成器

There are many "random number generators" across a whole spectrum from "extremely fast" to "relatively slow" and from "easy for even a human to see patterns" to "unlikely that unassisted humans could ever see any patterns" to "cryptographically secure and, after seeded with adequate amounts of entropy, as far as we can tell, indistinguishable from random to any attacker using less than all the energy produced by humanity for a month."

从“极快”到“相对较慢”,从“即使是人类也很容易看到模式”到“无人协助的人不可能看到任何模式”到“密码安全”,整个范围内有许多“随机数生成器”并且,在播种了足够数量的熵之后,据我们所知,对于任何使用少于人类一个月产生的全部能量的攻击者来说,这与随机无法区分。”

Non-cryptographic-strength random number generators that still give excellent output (unlikely that unassisted humans could ever see any patterns) include the Mersenne twister, multiply-with-carry, Lagged Fibonacci generator, Well equidistributed long-period linear, Xorshift, etc.

非加密强度的随机数生成器仍然提供优良的输出(不太可能无助的人类可能永远看不到任何模式)包括梅森捻线机乘用携带的滞后的斐波那契数生成器那么equidistributed长周期线性Xorshift等。

Cryptographic random number techniques that work with some browsers

适用于某些浏览器的加密随机数技术

I hear that Cryptocatand other JavaScript applications use the convenient window.crypto.getRandomValues()or window.msCrypto.getRandomValues()or SubtleCrypto.generateKey()functions that are designed to generate cryptographic random numbers. Unfortunately, that function is not available in IE 11 and below.

我听说Cryptocat和其他 JavaScript 应用程序使用方便的window.crypto.getRandomValues()orwindow.msCrypto.getRandomValues()SubtleCrypto.generateKey()旨在生成加密随机数的函数。不幸的是,该功能在 IE 11 及以下版本中不可用。

Since web browsers use random numbers all the time (for every "https://" page they fetch), it's quite likely that these functions (where available) may run faster than most random number generators written in JavaScript -- even non-cryptographic algorithms.

由于网络浏览器一直使用随机数(对于它们获取的每个“https://”页面),这些函数(如果可用)很可能比大多数用 JavaScript 编写的随机数生成器运行得更快——即使是非加密的算法。

Cryptographic random number techniques compatible with ancient and modern browsers

与古今浏览器兼容的加密随机数技术

One way to generate true random numbers in JavaScript is to capture mouse events and add them into a pool of entropy, keeping track of some (hopefully conservative) estimate of the entropy added. Once the pool is "full" (estimates indicate that at least 128 bits of entropy have been added), use some cryptographically secure random number generator to generate random numbers from the pool -- typically by using a one-way hash so that a sequence of a few thousand output numbers are not enough to deduce the state of the entropy pool and hence predict the next output number.

在 JavaScript 中生成真正随机数的一种方法是捕获鼠标事件并将它们添加到熵池中,跟踪添加的熵的一些(希望是保守的)估计。一旦池“满”(估计表明至少添加了 128 位熵),使用一些加密安全的随机数生成器从池中生成随机数——通常使用单向散列,以便序列几千个输出数字不足以推断熵池的状态并因此预测下一个输出数字。

One implementation: http://lightsecond.com/passphrase.html

一种实现:http: //lightsecond.com/passphrase.html

Further reading

进一步阅读

回答by Pawel

you can generate a pool of random numbers just by requesting some data asynchronously because performance.now() gives you time precision up to microseconds. Then use the response time as a salt in a randomising algorithm,

您可以通过异步请求一些数据来生成随机数池,因为 performance.now() 为您提供高达微秒的时间精度。然后使用响应时间作为随机算法中的盐,

var randomNumbers = [];
for(var i = 0; i < 10; i++) {
  setTimeout(function () {
    var timeStart = performance.now();
    xhttp = new XMLHttpRequest();
    xhttp.open('GET', 'https://cdn.polyfill.io/v2/polyfill.min.js?rand=' + Math.random(), true);
    xhttp.onload = function () {
      var timeEnd = performance.now() - timeStart;
      var rNumber = parseInt(timeEnd.toString().replace('.', ''));
      randomNumbers.push(rNumber)
    };
    xhttp.send();
  }, i * 10);
}

There are many factors that will affect this time:

影响这个时间的因素有很多:

  • browser speed
  • route one way
  • server response time
  • route back
  • 浏览器速度
  • 以一种方式走
  • 服务器响应时间
  • 返回路线

It's not good to generate millions of numbers this way but a few. Maybe concatenate a few results to get a good, long random number.

以这种方式生成数百万个数字并不好,而是生成一些。也许连接几个结果以获得一个好的、长的随机数。

回答by LukStorms

While looking for an alternative for Math.random I stumbled on this question.

在寻找 Math.random 的替代方案时,我偶然发现了这个问题。

While those are valid answers, the solution that worked for me was simply using Math.random twice.
And use a modulus on the decimals of the float.
Basically to increase the randomness.

虽然这些都是有效的答案,但对我有用的解决方案只是使用 Math.random 两次。
并在浮点数的小数上使用模数。
基本上是为了增加随机性。

Maybe it might be usefull for some who were guided by google to this question.

也许它可能对一些在谷歌指导下解决这个问题的人有用。

Here's a snippet with the function, and one that runs it a million times.

这是该函数的一个片段,它运行了一百万次。

function rand(min, max){
    return (Math.floor(Math.pow(10,14)*Math.random()*Math.random())%(max-min+1))+min;
}

// testing rand
function rollRands(min, max, rolls) {
    let roll = 0, n = 0;
    let counts = {};
    
    for(let i = min; i <= max; i++){
        counts[i]=0
    }

    while (roll < rolls){
        roll++;
        counts[rand(min,max)]++;
    }
    return counts;
}
  
console.log(rollRands(36, 42, 1000000));

回答by Randomness

I made a JavaScript library that uses cosine and sine functions to generate random numbers using Date.now() and new Date().getTime(). For each random number, I test to see if the number has been used. If it has, I repeat the process until I get a new number. If I get a new number, I add the number to the used list and then return the value. In the same library, I also added a randomness tester which loops through a random number generator and looks for patterns. It's nice this way since it loads numbers quickly (I timed it with console.time) without unnecessarily contacting other pages.

我制作了一个 JavaScript 库,它使用余弦和正弦函数使用 Date.now() 和 new Date().getTime() 生成随机数。对于每个随机数,我会测试该数字是否已被使用。如果有,我会重复这个过程,直到我得到一个新号码。如果我得到一个新号码,我将该号码添加到已用列表中,然后返回该值。在同一个库中,我还添加了一个随机性测试器,它循环遍历随机数生成器并查找模式。这种方式很好,因为它可以快速加载数字(我使用 console.time 对其进行计时),而不会不必要地联系其他页面。

You can find the library here: punbb.atspace.cc/scripts/libraries/random.js

您可以在此处找到该库:punbb.atspace.cc/scripts/libraries/random.js