我有各种依赖javascript随机数的资源。但是,由于我生成随机数的方式,我一直看到很多随机因素不随机的问题。
是否有任何javascript资源可供我生成真实或更好的随机数?
我知道我可以与Random.org交互,但我还有其他选择吗?
我正在使用:
function rand( lowest, highest){
var adjustedHigh = (highest - lowest) + 1;
return Math.floor(Math.random()*adjustedHigh) + parseFloat(lowest);
}
答案 0 :(得分:15)
假设您不仅仅看到没有任何模式的模式,请尝试使用Mersenee Twister(Wikipedia article here)。有许多实现,如this one on github。
类似的问题:
Seedable JavaScript random number generator
如果你想要更接近真正随机的东西,那么考虑使用random.org API获得真正随机的数字,虽然我建议只使用它来播种,而不是每个数字,因为你需要遵守它们的用法限制。
答案 1 :(得分:12)
我同意Phil H的观点,即人类非常善于发现他们常常认为他们会看到模式的模式,即使是在“完全随机”的数字序列中(clustering illusion,也许是恐惧,赌徒的谬误等)。
真正的随机位置图通常有很多团块和点“巧合地”非常接近,这看起来很可疑。
艺术家经常采用完全随机生成的模式并“轻推”它们以使它们显示“更随机”,即使仔细轻推实际上使模式更少随机{ {3}},(a),(b),(c)等
或者,(d)有时“看起来比真正的随机序列更好”,生成速度要快得多。
在从“极快”到“相对慢”的整个范围内有很多“随机数发生器”,从“甚至人类容易看到模式”到“不太可能无人帮助的人看不到任何模式” “加密安全,并且在我们能够分辨出足够数量的熵后,与任何使用人类产生的能量少于一个月的任何攻击者无法区分。”
仍然提供出色输出的非加密强度随机数生成器(无人帮助的人类可能看不到任何模式)包括low-discrepancy sequence,Mersenne twister,multiply-with-carry,{{3 },Lagged Fibonacci generator等等。
我听说Well equidistributed long-period linear和其他JavaScript应用程序使用方便的window.crypto.getRandomValues()
或window.msCrypto.getRandomValues()
或SubtleCrypto.generateKey()
函数来设计加密随机数。不幸的是,该功能在IE 11及以下版本中不可用。
由于网络浏览器一直使用随机数(对于他们提取的每个“https://”页面),这些功能(如果可用)很可能比用JavaScript编写的大多数随机数生成器运行得更快 - 甚至非加密算法。
在JavaScript中生成真正的随机数的一种方法是捕获鼠标事件并将它们添加到熵池中,跟踪一些(希望是保守的)增加的熵估计。一旦池“满”(估计表明已添加至少128位熵),使用一些加密安全随机数生成器从池中生成随机数 - 通常通过使用单向散列使得序列几千个输出数字不足以推断出熵池的状态,从而预测下一个输出数字。
一项实施:Xorshift
答案 2 :(得分:1)
您可以通过异步请求某些数据来生成随机数池,因为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);
}
有很多因素会影响这个时间:
用这种方式生成数百万个数字并不好,只有少数。也许连接几个结果以得到一个好的,长的随机数。
答案 3 :(得分:1)
在寻找Math.random的替代方案时,我偶然发现了这个问题。
虽然这些是有效的答案,但对我有用的解决方案只是使用Math.random两次。
并在浮点数的小数点上使用系数。
基本上可以增加随机性。
对于某些由google指导该问题的人来说,也许有用。
这是该函数的代码片段,可以运行一百万次。
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));
答案 4 :(得分:1)
更好的是,您可以使用量子密码术来生成很难预测的随机性。您可以使用ANU Quantum Random Numbers API进行某种随机性,将其强制转换为Math.random
类似输出的数字。
答案 5 :(得分:1)
Rando.js是加密安全的。基本上,window.crypto.getRandomValues()
使用window.msCrypto.getRandomValues()
作为故障保护,而Math.random()
作为最后的故障保护使用,但是它更易于实现和使用。这是一个基本的密码安全随机[0,1)数字:
console.log(rando());
<script src="https://randojs.com/2.0.0.js"></script>
又好又容易。如果这就是您想要的一切,那么您就很好了。如果您希望它为您做更多的事情,它还可以满足以下所有要求:
console.log(rando(5)); //an integer between 0 and 5 (could be 0 or 5));
console.log(rando(5, 10)); //a random integer between 5 and 10 (could be 5 or 10));
console.log(rando(5, "float")); //a floating-point number between 0 and 5 (could be exactly 0, but never exactly 5));
console.log(rando(5, 10, "float")); //a floating-point number between 5 and 10 (could be exactly 5, but never exactly 10));
console.log(rando(true, false)); //either true or false
console.log(rando(["a", "b"])); //{index:..., value:...} object representing a value of the provided array OR false if array is empty
console.log(rando({a: 1, b: 2})); //{key:..., value:...} object representing a property of the provided object OR false if object has no properties
console.log(rando("Gee willikers!")); //a character from the provided string OR false if the string is empty. Reoccurring characters will naturally form a more likely return value
console.log(rando(null)); //ANY invalid arguments return false
//Prevent repetitions by grabbing a sequence and looping through it
console.log(randoSequence(5)); //an array of integers from 0 through 5 in random order
console.log(randoSequence(5, 10)); //an array of integers from 5 through 10 in random order
console.log(randoSequence(["a", "b"])); //an array of {index:..., value:...} objects representing the values of the provided array in random order
console.log(randoSequence({a: 1, b: 2})); //an array of {key:..., value:...} objects representing the properties of the provided object in random order
console.log(randoSequence("Good gravy!")); //an array of the characters of the provided string in random order
console.log(randoSequence(null)); //ANY invalid arguments return false
<script src="https://randojs.com/2.0.0.js"></script>
它也支持使用jQuery元素,但是我在本演示中省略了它,因此我不必从jQuery中获取资源。如果需要,只需在GitHub或website上签出即可。
答案 6 :(得分:0)
在这两个非常不同的事物之间似乎有些困惑:
对已经知道这一点的人表示歉意,但两者是天壤之别。伪随机数出现是随机的,甚至可以通过复杂的随机性测试,但是它们是确定性的。因此,它们对于密码学毫无用处,并且在需要真正随机性的地方可能还有其他缺陷。
真正的随机性是不确定的,因此是不可预测的。此处的关键概念是熵之一,即所包含的非冗余信息量。获得真正随机数据的方法数量有限。 “好”来源是:
通常会利用其他“随机性源”,例如鼠标移动和计算机磁盘时序的内部变化等,但效果可能不尽人意。通常,我发现在Linux系统上访问熵池比在Windows下更容易,但是这可能只是个人偏见。
如果您只想要随机出现的数字,那么可以,使用梅森捻线器是可行的选择。它像疯了似的跳来跳去。如果您要生成随机数以用作例如version 4 UUIDs,那么您需要更加小心。即使不存在熵,也不能简单地“添加熵”,即使应用确定性密码功能也是如此。
如果您打算将随机性用于加密,则还应该强烈意识到随机性源受到破坏的许多方式。例如,如果您使用的是基于Internet的“随机性来源”,谁可以利用它?
答案 7 :(得分:-6)
我创建了一个JavaScript库,它使用余弦和正弦函数使用Date.now()和new Date()。getTime()生成随机数。对于每个随机数,我测试是否已使用该数字。如果有,我会重复这个过程,直到我得到一个新号码。如果我得到一个新号码,我将该号码添加到使用的列表中,然后返回该值。在同一个库中,我还添加了一个随机性测试程序,它循环遍历随机数生成器并查找模式。这样很好,因为它可以快速加载数字(我用console.time定时),而不会不必要地联系其他页面。
你可以在这里找到这个库:punbb.atspace.cc/scripts/libraries/random.js