利用JS实现抢红包的三种算法
(福利推荐:你还在原价购买阿里云服务器?现在阿里云0.8折限时抢购活动来啦!4核8G企业云服务器仅2998元/3年,立即抢购>>>:9i0i.cn/aliyun)
对于抢红包来说最重要的就是随机性算法,如何确保每个人获得金额是趋向于平均的,也就是有平均的概率去随机,而尽量避免两极分化。
就比如一般的随机算法,假设有 100 元的红包,有 10 个人去抢,第一个人去抢红包的随机范围是(0, 100),一旦此人抢到足够大的金额比如 90,剩下的 9 个人只能在不断缩小的 10 以下的范围随机,这样的奖金范围会很受限。也就是越前面抢的人优势越大。
接着需要说明抢红包的核心规则:
- 每个人抢到的金额总和等于红包金额
- 确保每个人得到最小的非零金额数
- 要保证随机概率尽量分布均匀,避免存在可以通过技巧性钻空子。
接着我们将使用 js 实现3种抢红包的算法:
方法一:Math.random() 直接随机
function getRandomMoney(totalMoney, totalPeople) { let remainMoney = totalMoney; let remainPeople = totalPeople; let result = []; for (let i = 1; i < totalPeople; i++) { let max = remainMoney - remainPeople + 1; let money = Math.random() * max; money = Math.floor(money * 100) / 100; result.push(money); remainMoney -= money; remainPeople--; } result.push(remainMoney); // 最后一个人抢剩下的钱 return result; } let totalMoney = 100; let totalPeople = 5; let result = getRandomMoney(totalMoney, totalPeople); console.log(result);
就像开篇提到的,先抢的优势很大。
对于随机
random()
方法大家很熟悉,但方法返回一个大于等于 0 且小于 1 的伪随机浮点数,其实并不足够随机,在足够大的样本下还是会呈现某种趋势。
方法二:两倍均值法
也就是 money = (0, M/N*2)
剩余红包金额M,剩余人数N。
function getDoubleAverage(totalMoney, totalPeople) { let remainMoney = totalMoney; let remainPeople = totalPeople; let result = []; for (let i = 0; i < totalPeople - 1; i++) { let avg = remainMoney / remainPeople * 2; let money = Math.random() * avg; money = Math.floor(money * 100) / 100; result.push(money); remainMoney -= money; remainPeople--; } result.push(remainMoney); // 最后一个人抢剩下的钱 return result; } let totalMoney = 100; let totalPeople = 5; let result = getDoubleAverage(totalMoney, totalPeople); console.log(result);
这种方法等于每次抢红包的最大范围为人均的两倍。但是有个问题,最后一次还是任意的随机。这就意味着最后抢的人收益的风险最高。
方法三:线段切割法
function getRandomMoney(total, num) { if (num === 1) { return total; } let max = total - 0.01 * num; let randomArr = [0, total]; for (let i = 1; i < num; i++) { let random = Math.random() * max; randomArr.push(random); } randomArr.sort((a, b) => a - b); let result = []; for (let j = 0; j < num; j++) { let money = (randomArr[j + 1] - randomArr[j]).toFixed(2); result.push(parseFloat(money)); } return result; } let totalMoney = 100; let totalPeople = 5; let moneyList = getRandomMoney(totalMoney, totalPeople); console.log(moneyList);
线段切割法在抢红包等随机分配场景中被认为比较公平的原因主要是因为:线段切割法会将总金额分割成多个小段,然后随机分配给每个人,确保了每个人获得的金额相对均匀,避免了出现极端不公平的情况。
当然这还存在一种可能分割点可能重复,我们需要重新生成。
到此这篇关于利用JS实现抢红包的三种算法的文章就介绍到这了,更多相关JS抢红包算法内容请搜索程序员之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持程序员之家!
相关文章
el-table动态渲染列、可编辑单元格、虚拟无缝滚动的实现
vue对数据处理很常见,本文主要介绍了对el-table组件二次封装,包括对el-table的动态渲染、单元格编辑;对于无缝滚动的实现,优化大数据量下的页面卡顿问题,感兴趣的可以了解一下2023-12-12
最新评论