JavaScript生成随机数的核心是Math.random(),它返回[0,1)的浮点数;整数需用Math.floor缩放偏移,避免Math.round破坏均匀分布;密码学场景须用crypto API。

JavaScript 中生成随机数的核心函数是 Math.random()
Math.random() 是唯一原生支持的随机数生成器,它返回一个大于等于 0、小于 1 的浮点数(即区间 [0, 1))。所有其他范围的随机数都得基于它做缩放和偏移——不是封装成函数就万事大吉,关键在边界处理是否严谨。
生成指定范围整数的常见写法及陷阱
比如要生成 1 到 6 之间的随机整数(模拟掷骰子),错误写法是:Math.floor(Math.random() * 6) + 1 看似正确,但实际没问题;而真正危险的是:Math.round(Math.random() * 5) + 1 ——它会让 1 和 6 出现概率只有其他数的一半。
-
Math.floor(Math.random() * (max - min + 1)) + min:适用于闭区间[min, max]的整数,最常用也最安全 -
Math.ceil(Math.random() * (max - min + 1)) + min - 1:等价但可读性差,不推荐 - 用
Math.round()会破坏均匀分布,因为两端值只覆盖半个区间 - 如果
min或max是变量,注意确保它们是整数,否则结果可能越界或非预期
需要真随机?Math.random() 不够安全
Math.random() 是伪随机,由引擎实现决定(V8 使用 xorshift128+),不可预测但可复现。它**不适合密码学场景**,比如生成 token、加密盐值或抽奖种子。
- 密码学安全请用
crypto.getRandomValues()(浏览器)或crypto.randomBytes()(Node.js) - 例如生成 4 字节安全整数:
const arr = new Uint32Array(1); crypto.getRandomValues(arr); const safeRand = arr[0] % 100;
-
cryptoAPI 是异步设计的替代方案(如crypto.subtle.generateKey),但对简单随机数属于杀鸡用牛刀 - 服务端若用 Node.js 且版本
,需注意crypto.randomInt()是 19+ 新增,旧版只能手动封装randomBytes
多次调用 Math.random() 会不会“更随机”?
不会。连续调用不会提升随机性,反而可能因重复 seed(极罕见)或浮点精度叠加引入偏差。有人误以为 Math.random() * Math.random() “更乱”,其实它让结果更集中在 0 附近,分布严重偏斜。
立即学习“Java免费学习笔记(深入)”;
- 想提高质量?换算法(如使用
seedrandom库自定义 seed)比堆调用有用得多 - 调试时若发现“总不中奖”,先检查逻辑是否用了
==比较浮点中间值,或循环中意外复用了同一个Math.random()结果 - 单元测试里固定随机行为,可用 sinon stub 或直接重赋值
Math.random = () => 0.5(注意仅限测试环境)
边界计算和用途区分才是难点,不是记不住公式。











