为什么Math.floor(Math.random()* n)优于Date.now()%n在[0,n]之间选择一个随机数?

时间:2019-03-10 23:48:05

标签: javascript random

多年来,我一直在使用Math.floor(Math.random() * someArray.length)在数组中选择随机元素。我一直想知道为什么它比Date.now() % someArray.length更好。在我看来,后者似乎更不容易出错,并且必须更快(不过,我实际上尚未对其进行基准测试)。

注意:

  1. 我不需要重复性。
  2. 这不是循环运行的,因此在整个应用程序中会随机调用该函数。
  3. 这不是用于模拟,因此“或多或少”的随机性就足够了。

1 个答案:

答案 0 :(得分:1)

  

我一直想知道为什么它比Date.now()%someArray.length更好

日期远比Math.random复杂得多-Math.random专门为设计的用于创建随机数的方法,并且速度更快:

const p0 = performance.now();
const n = 3;
for (let i = 0; i < 1e6; i++) {
  (Date.now() % 3)
}
const p1 = performance.now();
console.log(p1 - p0);

vs

const p0 = performance.now();
const n = 3;
for (let i = 0; i < 1e6; i++) {
  Math.floor(Math.random() * 3)
}
const p1 = performance.now();
console.log(p1 - p0);

使用日期时会有一些明显的开销-再加上日期并不是完全随机的。例如,如果您尝试选择一个介于1到1000之间的数字,并且用户碰巧尝试每1秒生成一个数字,则结果数字很可能全部都靠在一起,这可能是不希望的。 (最好不要指望用户输入的时间是随机的)

如果您的项目的目标不是半样的随机性,安全性和性能(在小型的临时脚本中可以理解),那么您可以自由使用{{1} }相反,它不会受到太大的伤害,这只是一件不寻常的事情,并且不会是随机的。如果您想要精确,安全的随机性,请使用Crypto.getRandomValues()而不是Date.now()