js 随机数(超详细)

更新时间:

💡一则或许对你有用的小广告

欢迎加入小哈的星球 ,你将获得:专属的项目实战(已更新的所有项目都能学习) / 1v1 提问 / Java 学习路线 / 学习打卡 / 每月赠书 / 社群讨论

  • 新开坑项目:《Spring AI 项目实战》 正在持续爆肝中,基于 Spring AI + Spring Boot 3.x + JDK 21..., 点击查看 ;
  • 《从零手撸:仿小红书(微服务架构)》 已完结,基于 Spring Cloud Alibaba + Spring Boot 3.x + JDK 17...点击查看项目介绍 ;演示链接: http://116.62.199.48:7070 ;
  • 《从零手撸:前后端分离博客项目(全栈开发)》 2 期已完结,演示链接: http://116.62.199.48/ ;

截止目前, 星球 内专栏累计输出 90w+ 字,讲解图 3441+ 张,还在持续爆肝中.. 后续还会上新更多项目,目标是将 Java 领域典型的项目都整一波,如秒杀系统, 在线商城, IM 即时通讯,权限管理,Spring Cloud Alibaba 微服务等等,已有 3100+ 小伙伴加入学习 ,欢迎点击围观

在 JavaScript 开发中,"js 随机数" 是一个高频需求,无论是游戏中的道具掉落、抽奖系统的实现,还是数据测试时的模拟生成,都离不开随机数的支撑。然而,许多开发者在初次接触这一主题时,常因对随机数生成机制的误解而陷入困境。本文将从基础到进阶,系统性地解析如何在 JavaScript 中高效、安全地生成随机数,并通过实际案例展示其应用场景。


一、基础:Math.random() 的核心原理

JavaScript 的随机数生成主要依赖于全局对象 Math 中的 Math.random() 方法。该方法返回一个 [0, 1) 区间的浮点数,即包含 0 但不包含 1。

1.1 方法特性与局限性

  • 伪随机性Math.random() 生成的数是伪随机的,其“随机性”基于算法和初始种子值(seed)。这意味着在相同种子下,同一代码段会生成相同的序列。
  • 均匀分布:理论上,该方法在区间内均匀分布,但实际实现可能因 JavaScript 引擎的差异而存在细微偏差。

示例代码

// 生成 0 到 1 之间的随机浮点数  
const randomValue = Math.random();  
console.log(randomValue); // 可能输出:0.123456789  

二、核心技巧:生成指定范围的随机数

多数场景需要的随机数并非 [0,1),而是整数或特定区间的数值。以下是常见转换方法:

2.1 生成随机整数

方法 1:乘法 + 取整

通过 Math.random() 乘以范围长度,再用 Math.floor()Math.ceil() 去除小数部分。

  • 区间 [min, max) 的随机整数
    function getRandomInt(min, max) {  
      return Math.floor(Math.random() * (max - min)) + min;  
    }  
    // 例如生成 1 到 10 的整数:  
    const result = getRandomInt(1, 10); // 可能输出 3  
    
  • 区间 [min, max] 的随机整数
    需要将 max 替换为 max + 1
    const result = Math.floor(Math.random() * (max - min + 1)) + min;  
    

方法 2:ES6 的 Math.trunc()

function getRandomIntES6(min, max) {  
  return Math.trunc(Math.random() * (max - min)) + min;  
}  

形象比喻

想象将 [0,1) 的区间比作一条长度为 1 的线段,乘以 (max - min) 相当于将线段“拉伸”到目标长度,而取整操作则是“切割”线段后取整数部分。


2.2 生成随机浮点数

若需保留小数位,可通过 toFixed() 方法控制精度:

function getRandomFloat(min, max, decimalPlaces = 2) {  
  const value = Math.random() * (max - min) + min;  
  return parseFloat(value.toFixed(decimalPlaces));  
}  
// 生成 1.5 到 3.5 之间的两位小数:  
const result = getRandomFloat(1.5, 3.5); // 可能输出 2.76  

三、进阶问题与解决方案

3.1 随机数重复与去重

在需要唯一值的场景(如抽奖、验证码),直接使用 Math.random() 可能导致重复。此时可通过以下方法解决:

方法 1:数组去重法

function generateUniqueNumbers(count, min, max) {  
  const numbers = [];  
  while (numbers.length < count) {  
    const num = getRandomInt(min, max);  
    if (!numbers.includes(num)) {  
      numbers.push(num);  
    }  
  }  
  return numbers;  
}  
// 生成 5 个不重复的 1-10 整数:  
const uniqueNumbers = generateUniqueNumbers(5, 1, 10);  

方法 2:Fisher-Yates 洗牌算法

function shuffle(array) {  
  for (let i = array.length - 1; i > 0; i--) {  
    const j = Math.floor(Math.random() * (i + 1));  
    [array[i], array[j]] = [array[j], array[i]];  
  }  
  return array;  
}  
// 生成 1-10 的随机排列:  
const shuffled = shuffle([...Array(10).keys()].map(i => i + 1));  

3.2 加密安全的随机数

Math.random() 不适合加密场景,因其伪随机性易被预测。此时可使用 Web Crypto API:

async function getSecureRandomInt(min, max) {  
  const array = new Uint32Array(1);  
  await crypto.subtle.randomFill(array);  
  return (array[0] % (max - min)) + min;  
}  
// 生成加密安全的 1-100 整数:  
getSecureRandomInt(1, 100).then(result => console.log(result));  

四、实际案例与应用

4.1 抽奖系统

const participants = ["Alice", "Bob", "Charlie", "David"];  
function drawWinner() {  
  const index = Math.floor(Math.random() * participants.length);  
  return participants[index];  
}  
console.log("Winner is:", drawWinner()); // 可能输出 "Charlie"  

4.2 简易验证码生成

function generateVerificationCode(length = 6) {  
  const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";  
  let code = "";  
  for (let i = 0; i < length; i++) {  
    const index = Math.floor(Math.random() * chars.length);  
    code += chars[index];  
  }  
  return code;  
}  
console.log("Verification Code:", generateVerificationCode(6)); // 可能输出 "aB7xK3"  

五、性能优化与最佳实践

5.1 避免频繁调用 Math.random()

若需生成大量随机数,可预先生成一个数组再复用:

function generateBatchRandoms(count) {  
  const arr = new Array(count);  
  for (let i = 0; i < count; i++) {  
    arr[i] = Math.random();  
  }  
  return arr;  
}  

5.2 种子随机数生成(需第三方库)

若需可复现的随机序列,可借助 seedrandom 库:

const { createSeededRNG } = require("seedrandom");  
const rng = createSeededRNG("my-seed");  
console.log(rng()); // 始终返回相同值  

六、结论

掌握 "js 随机数" 的核心方法与进阶技巧,能显著提升开发效率。从基础的 Math.random() 到加密安全的 Web Crypto API,开发者需根据场景选择合适方案。通过本文的案例与代码示例,读者可快速实现抽奖系统、验证码生成等需求,并理解随机数背后的数学逻辑。未来随着 JavaScript 的发展,随机数生成技术将持续演进,开发者需持续关注其最佳实践与性能优化策略。

最新发布