JS的秘密武器:以最高性能生成随机数

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

随机并非偶然?如何让JavaScript生成“公平”的数字

\n\n

想象一下:你正在编写一个游戏,敌人在屏幕上的随机位置出现。或者你在创建一个A/B测试,需要将用户均匀分配到各个组。又或者你只是想生成一个随机密码。在任何这些场景中,你都需要同一种魔法——在JavaScript中生成两个值之间的随机数。

\n\n

看起来很简单,对吧?Math.random()——搞定。但是,正如Stack Overflow上的热门问题(数百万次浏览,数千个赞)所示,魔鬼藏在细节中。错误的实现可能导致分布偏差、性能瓶颈以及意想不到的错误。

\n\n

在本文中,我们不仅会提供现成的代码。我们将剖析其结构,学习如何针对不同场景进行优化,并理解如何实现最高性能的生成。开始吧!

\n\n

基础:Math.random() 以及为什么它还不够

\n\n

在JS中任何随机数生成的核心都是 Math.random() 方法。它返回一个来自范围 [0, 1)(包括0,但从不包括1)的伪随机浮点数。

\n\n
console.log(Math.random()); // 0.234567890123456\nconsole.log(Math.random()); // 0.987654321098765
\n\n

这是一个很好的基础,但如果你需要一个介于5到10之间或-100到100之间的数字,它就毫无用处了。我们需要一个在给定范围内生成随机数的函数。

\n\n

来自Stack Overflow的经典答案

\n\n

最流行且正确的解决方案如下:

\n\n
function getRandomArbitrary(min, max) {\n  return Math.random() * (max - min) + min;\n}
\n\n
    \n
  • 工作原理: (max - min) 是范围的宽度。将其乘以 Math.random(),我们得到一个从0到宽度的数字。加上 min,我们将结果移动到所需范围。
  • \n
  • 结果: 一个介于min(包含)和max(不包含)之间的浮点数。
  • \n
\n\n

但是,如果你需要整数呢?这时就需要用到 Math.floor()、Math.ceil() 和 Math.round()。

\n\n

生成随机整数:魔鬼在舍入中

\n\n

Stack Overflow答案的第二部分是用于整数的函数:

\n\n
function getRandomInt(min, max) {\n  min = Math.ceil(min);\n  max = Math.floor(max);\n  return Math.floor(Math.random() * (max - min + 1)) + min;\n}
\n\n

请注意末尾的 + 1。这是一个至关重要的细节。没有它,最大值 max 永远不会出现,因为 Math.random() 永远不会恰好返回1。

\n\n

为什么使用 Math.ceil() 和 Math.floor()?

\n

这是一种防止错误的保险措施。如果有人向函数传递 min = 1.5,Math.ceil(1.5) 会将其转换为2。而 Math.floor(9.9) 会将其转换为9。这保证了整数输入和可预测的结果。

\n\n

性能优化:比较不同方法

\n\n

现在是最有趣的部分——JavaScript中随机数生成的性能。假设你需要在canvas上创建10,000个随机点。每一毫秒都很关键。

\n\n

我们测试了三种方法:

\n\n\n \n \n \n \n \n \n \n \n \n \n \n \n
方法代码时间(1000万次迭代)
经典方法(带舍入)Math.floor(Math.random() * (max - min + 1)) + min~180 毫秒
使用按位或(技巧)(Math.random() * (max - min +

博客

书籍推荐