JS使用Math.random()生成从1开始的不重复随机数问题咨询
问题原因
- 随机数出现0:
Math.random()返回的是[0, 1)区间的浮点数,你之前的生成逻辑应该是直接乘以最大值后取整,得到的范围默认从0开始,不符合需求 - 随机数重复:每次生成随机数时没有做已使用值的校验,小范围随机场景下数值碰撞概率很高,自然会出现重复的随机数
解决方法
根据你的需求场景选择对应实现即可:
场景1:给N个成员分配1~N的不重复随机数
推荐用Fisher-Yates洗牌算法实现,性能最高,完全不会出现重复和0值问题:
// 成员列表 const members = ['William', 'James', 'Evelyn', 'Harper', 'Mason', 'Ella'] const count = members.length // 生成1~N的有序数组 const randomNumList = Array.from({length: count}, (_, index) => index + 1) // 洗牌算法打乱数组 for (let i = randomNumList.length - 1; i > 0; i--) { const randomIndex = Math.floor(Math.random() * (i + 1)) ;[randomNumList[i], randomNumList[randomIndex]] = [randomNumList[randomIndex], randomNumList[i]] } // 拼接生成最终结果 const result = 'Winer: ' + members.map((name, idx) => `${name}${randomNumList[idx]}`).join(',') // 输出到页面 document.querySelector('#result').textContent = result
对应HTML展示代码:
<!-- 结果展示容器 --> <div id="result"></div>
场景2:随机数最大值大于成员数量(比如6个成员分配1~10之间的不重复随机数)
用Set做已使用值校验即可:
const members = ['William', 'James', 'Evelyn', 'Harper', 'Mason', 'Ella'] const maxRandomNum = 10 // 可自定义随机数最大值 const usedNums = new Set() const resultList = [] for (const name of members) { let num // 循环生成直到拿到未被使用的随机数 do { // +1保证随机数从1开始 num = Math.floor(Math.random() * maxRandomNum) + 1 } while (usedNums.has(num)) usedNums.add(num) resultList.push(`${name}${num}`) } const result = 'Winer: ' + resultList.join(',') document.querySelector('#result').textContent = result
内容的提问来源于stack exchange,提问作者Hiep Anh
相关产品推荐
相关产品推荐

