不要再用 Math.random()!用这个 API 做到真随机
moboyou 2025-09-18 04:17 1 浏览
当我们需要一个随机数时,Math.random() 几乎是所有人的第一反应。它简单、直接,一行代码就能得到一个 0 到 1 之间的浮点数。
然而,这个信手拈来的函数,却有着致命的缺陷。
Math.random()的“原罪”:它是可预测的
Math.random() 生成的数字并非真正的随机,而是伪随机。
什么是伪随机?它是由一个确定的算法,根据一个初始值(称为“种子”)计算出来的一系列数字。这个算法本身是公开的,这意味着,如果你知道了初始的“种子”,你就能完全预测出接下来生成的每一个“随机数”。
在早期的浏览器中,这个“种子”甚至可能只是简单的时间戳,使得预测变得非常容易。虽然现代浏览器已经改进了种子的生成方式,使其更难被猜测,但 Math.random() 的核心机制并没有改变。ECMAScript 规范本身不要求 Math.random() 必须是密码学安全的。
更安全的替代方案:crypto.getRandomValues()
window.crypto 是浏览器提供的一套用于密码学操作的 API,而 crypto.getRandomValues() 就是其中的一员。它是一个密码学安全伪随机数生成器 (CSPRNG)。
与 Math.random() 不同,crypto.getRandomValues() 的设计目标就是提供密码学级别的安全性。
它是如何做到“真正随机”的?
它直接从操作系统底层获取高质量的“熵 (Entropy)”。这些熵的来源是不可预测的物理事件,例如:
- 鼠标移动的精确时机和轨迹
- 键盘输入的时机
- 硬件设备产生的微小噪声
- 网络数据包的到达时间
操作系统将这些不可预测的事件混合成一个“熵池”,crypto.getRandomValues() 正是从这个池中获取随机性,使其生成的数值在统计学上是真正不可预测的。
如何使用 crypto.getRandomValues()?
它的用法与 Math.random() 有所不同。它不是直接返回一个数字,而是用于填充一个类型化数组 (Typed Array),如 Uint8Array 或 Uint32Array。
基础用法:
// 创建一个包含 10 个字节的数组
const randomBytes = new Uint8Array(10);
// 用密码学安全的随机值填充它
crypto.getRandomValues(randomBytes);
console.log(randomBytes); // 输出: Uint8Array(10) [185, 20, 248, 119, ...]
这看起来似乎没那么直观,但别担心,我们可以轻松地将它封装成我们习惯使用的函数。
替代 Math.random() 的函数:
我们可以生成一个 32 位无符号整数,然后将其转换为 0 到 1 之间的浮点数。
function secureRandom() {
// 创建一个能容纳一个 32 位无符号整数的数组
const array = new Uint32Array(1);
// 填充随机值
crypto.getRandomValues(array);
// 将其除以 32 位整数的最大值 (2^32 - 1),得到 [0, 1) 范围的浮点数
return array[0] / (Math.pow(2, 32) - 1);
}
console.log(secureRandom()); // 输出: 0.81... (一个密码学安全的随机浮点数)
生成范围内安全随机整数的函数(常用):
function secureRandomInt(min, max) {
const range = max - min + 1;
// 创建一个足够大的随机数,以减少模偏差
const randomValue = new Uint32Array(1);
crypto.getRandomValues(randomValue);
return min + (randomValue[0] % range);
}
console.log(secureRandomInt(1, 6)); // 模拟安全的骰子
console.log(secureRandomInt(1000, 9999)); // 生成一个安全的 4 位验证码
Math.random() 适用于那些不涉及安全或公平性的应用场景,例如:
- 生成随机的粒子效果、模拟下雨或下雪
- 创作随机的图案和视觉效果
- 需要玩家通过分享种子来玩到完全相同的游戏关卡
当需要真随机时,请选择 crypto.getRandomValues(),目前早已兼容各现代浏览器(IE 除外)。
相关推荐
- 一个时间选择器,为何大家都不相同
-
在自媒体平台的定时发布功能中,看似基础的时间选择器,在不同平台却呈现出显著差异——从时间范围限制、日期展示方式,到时间精度与交互布局,各平台设计均有侧重,这些差异背后,实则是对用户场景、操作便捷性...
- 全新生成模型「离散分布网络DDN」如何做到原理简单,性质独特?
-
本文作者杨磊,目前在大模型初创公司阶跃星辰担任后训练算法工程师,其研究领域包括生成模型和语言模型后训练。在这之前,他曾在旷视科技担任了六年的计算机视觉算法工程师,从事三维视觉、数据合成等方向。他于2...
- 大模型“记性差一点”反而更聪明!随机剔除token,让AI不再死记硬背
-
训练大模型时,有时让它“记性差一点”,反而更聪明!大语言模型如果不加约束,很容易把训练数据原封不动地复刻出来。为解决这个问题,来自马里兰大学、图宾根大学和马普所的研究团队提出了一个新方法——金鱼损失(...
- 彩票并非纯靠运气!老彩民绝不会告诉你的,五个选号笨办法!
-
在许多人眼里,购买彩票纯粹是一场与命运的对赌,完全依赖于那缥缈的运气。然而,真正深入其中的老彩民们却深知,虽然最终的开奖号码随机,但在选号的过程中,确实存在一些值得琢磨的“门道”。这些方法看似“笨拙”...
- 老程序员爱用AI写代码:调查显示三成资深工程师一半代码靠AI生成
-
IT之家9月8日消息,一项新调查深入剖析了生成式人工智能(GenAI)对软件开发者日常工作的变革作用。结果显示,不同资历的工程师呈现出明显分化:资深工程师更倾向于大量使用AI生成代码,主动...
- 告别手动!4种批量建Excel,省时还不出错
-
你是不是也遇到过这种情况:月底要做报表,要给每个部门单独建一个Excel;项目汇总,每个客户都得生成一份数据文件。光是新建、命名、保存这一套流程,就得重复几十遍。鼠标点到手酸,眼睛还得紧盯着生怕出错,...
- 财务多个发票凑一个金额,花了1天,同事用Excel2分钟搞定
-
我们现在有很多发票金额,如下是模拟的数据,这里有10张发票然后总金额是固定的,是由以下的发票金额凑起来正好的数值也不确定具体是几张发票凑起来的现在需要快速的将它们找出来,正好凑好总金额遇到这种凑金额的...
- 调和随机数的混沌_随机调配
-
编者按本文来自作家、游戏智慧(Game-Wisdom.com)创始人乔希·拜瑟(JoshBycer)的个人博客,由indienova取得授权并译制发表,原文链接见文末。正文随机数生成(Rando...
- 大模型“记性差一点”反而更聪明,金鱼损失随机剔除token,让AI不再死记硬背
-
训练大模型时,有时让它“记性差一点”,反而更聪明!大语言模型如果不加约束,很容易把训练数据原封不动地复刻出来。为解决这个问题,来自马里兰大学、图宾根大学和马普所的研究团队提出了一个新方法——金鱼损失(...
- 彩票店老板绝不会告诉你的十个选号潜规则!早知道早中奖!
-
每天都有无数彩民走进彩票店,怀揣着梦想购买一两注彩票。你可曾想过,那些看似随机的数字背后,可能隐藏着一些不为人知的"潜规则"?经过多方打探和走访,我们终于整理出彩票店老板绝不会主动告诉...
- Excel数据重塑利器:WRAPROWS和WRAPCOLS函数详解
-
WRAPROWS和WRAPCOLS是ExcelforMicrosoft365中引入的两个新函数,它们能够将单行或单列的数据按照指定的方式重新排列成多行多列的二维数组。WRAPROWS:...
- 生成式AI不是“通用智能”,而是“工具革命”:企业落地的3个关键思考
-
从ChatGPT到Midjourney,生成式AI的“魔法”正在席卷各行各业。但在热潮之下,我们更需要冷静思考:它真的具备“智能”吗?其实,生成式AI不是通用智能的雏形,而是一场信息处理方式的“工具革...
- 建议收藏!BigemapPro 快捷命令+函数公式大全,效率直接拉满
-
在使用BigemapPro处理地理数据时,熟练掌握快捷命令和函数公式能极大提升工作效率,告别重复操作,让你的地图编辑、数据处理更高效。今天,就为大家整理了一份超全的BigemapPro实用技巧,涵盖常...
- Excel制作小型抽奖系统,可以内定结果,拿去用
-
“年会抽奖还能内定?别笑,我亲眼见过。”这句话一出,会议室瞬间安静,老板都忍不住探头。其实内定不是黑幕,而是技术——Excel就能搞定。三分钟搭好,零代码基础也能玩得飞起,关键是还能让全场嗨到尖叫。先...
- 告别加班!27个Excel新函数全面升级你的工作效率,新手必看!
-
今天我要为大家带来27个Excel新函数全面解析,这些都是微软近年来推出的重磅功能,能够让你的工作效率提升十倍不止!一、动态数组革命:彻底改变Excel计算方式FILTER函数-按条件筛选数据=F...
- 一周热门
- 最近发表
- 标签列表
-
- 外键约束 oracle (36)
- oracle的row number (32)
- 唯一索引 oracle (34)
- oracle in 表变量 (28)
- oracle导出dmp导出 (28)
- 多线程的创建方式 (29)
- 多线程 python (30)
- java多线程并发处理 (32)
- 宏程序代码一览表 (35)
- c++需要学多久 (25)
- css class选择器用法 (25)
- css样式引入 (30)
- css教程文字移动 (33)
- php简单源码 (36)
- php个人中心源码 (25)
- php小说爬取源码 (23)
- 云电脑app源码 (22)
- html画折线图 (24)
- docker好玩的应用 (28)
- linux有没有pe工具 (34)
- mysql数据库源码 (21)
- php开源万能表单系统源码 (21)
- 可以上传视频的网站源码 (25)
- match函数的功能是 (21)
- 随机函数如何生成小数点数字 (31)