真或更好的 Javascript 随机数

IT技术 javascript random
2021-03-11 15:49:22

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

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

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

我正在使用:

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

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

类似的问题:

可种子 JavaScript 随机数生成器

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

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

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

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

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

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

快速随机数生成器

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

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

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

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

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

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

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

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

进一步阅读

一个想法是创建一个已经随机选择的条目数组。然后返回新随机项目的函数将忽略那些已经选择过的项目,并轮到尚未选择的项目。直到所有项目至少被挑选一次。
2021-05-01 15:49:22

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

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

也许它可能对一些被谷歌引导到这个问题的人有用。

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

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));

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网站查看即可

两件非常不同的事情之间似乎存在轻微的混淆:

  • 随机数;
  • 伪随机数。

向那些已经知道这一点的人道歉,但两者是天壤之别。伪随机数看起来是随机的,甚至可能通过复杂的随机性测试,但它们是确定性的。因此,它们对密码学毫无用处,并且可能存在需要真正随机性的其他缺陷。

真正的随机性是不确定的,因此是不可预测的。这里的一个关键概念是熵之一,或包含的非冗余信息的数量。获得真正随机数据的方法数量有限。“好”来源是:

  1. 放射性衰变——通常很难做到;
  2. 背景无线电噪声——与人们普遍认为的相反,这主要与大爆炸的背景微波辐射无关,但更为狭隘;
  3. 电子在反向偏置齐纳二极管上移动的噪声:实际上非常有用且易于在实践中实现,电路简单。

其他“随机性来源”,如鼠标移动和计算机磁盘计时的内部变化等,通常会被利用,但可能并不完美。一般来说,我发现在 Linux 系统上访问熵池比在 Windows 下更容易,但这可能只是个人偏见。

如果您只想要随机出现的数字,那么是的,使用 Mersenne twiner 是一个可行的选择。它像疯了一样跳来跳去。如果您生成随机数用作例如第 4 版 UUIDs,那么您需要更加小心。如果它不存在,您不能简单地“添加熵”,即使应用确定性加密函数也是如此。

如果您打算将您的随机性用于密码学,您还应该强烈意识到您的随机性来源可能受到损害的多种方式。例如,如果您使用的是基于 Internet 的“随机性来源”,谁能利用它?