不论是在节假日期间,还是在朋友间的日常调侃里,微信红包无疑已成为连接情感、增添乐趣的关键。每当指尖轻触,红包一开,那份未知的惊喜总是让人欲罢不能,也许是运气王,又或者是0.01,让你哭笑不得。但你是否也曾好奇,为何“运气王”似乎总与自己无缘,而“0.01”却好像是粘在鞋子上的口香糖,甩都甩不掉?
首先,搞清机制才能知道红包是怎么发的
咱们来想,假如我要发十块钱的红包到一个五人群,要求每个人拿到的金额大小是随机的,这样才能有打开红包时那种充满未知的“刺激感”。那么要怎么实现随机性呢?
这时就不得不提Math.random()方法了,这个方法可以生成 0 ~ 1 之间的随机数,那么有人会说直接使用5次Math.random()乘以总金额不就可以了吗?
这可不行,这样容易使生成的总金额大于你输入的金额,你总不能发个红包还倒贴吧?那么咱们想着写一个循环,循环里面计算出前四个人的红包金额大小,最后一个人的红包大小就是所剩下的金额了。那么咱们来看看代码是怎么实现的吧。
// 微信红包随机性实现
function hongbao(total, num) {
// 发红包的那一刻就已经决定了
// 宕机
const arr = [];
// 余额
let restAmount = total;
// 未领取人数
let restNum = num;
// num-1
for(let i =0; i < num -1; i++) {
let amount = parseFloat(Math.random() * (restAmount/restNum)).toFixed(2)
restAmount -= amount;
restNum--;
arr.push(amount)
}
// 最后一人的
arr.push(parseFloat(restAmount).toFixed(2));
return arr;
}
console.log(hongbao(10,5))
其中**(restAmount/restNum)** 表示的是当前人均应得的基础金额,即剩余总金额(restAmount)除以剩余需分配的人数(restNum)。随着每次循环,已分配出去的红包金额会使restAmount减小,剩余人数restNum也会相应减少,从而动态调整每次分配的基础数额,保持一定的公平性。Math.random() * (restAmount/restNum) 将随机数与当前人均基础金额相乘,来决定实际分配给某个人的红包金额。这样既保持了随机性,也使得每个人分到的金额在人均基础上有所浮动。那么
这样看或许不是很明显,那咱们来玩点大的,我要发一百块在一个十人群,那咱们多生成机组再来看看结果如何
咱们可以看到,最后一个包总是最大的,那这样我可就要最后一个领咯,显然这样是不行的,咱们肯定不能通过这种“非法”行为来拿下手气王。
那怎么样可以既让红包随机一点又可以相差不那么大呢?
一个有效的方法是在随机分配时,给定一个调整系数,比如让随机数乘以2,即amount = parseFloat(Math.random() * (restAmount/restNum)*2).toFixed(2);。这样,即使前面的人随机到较小的数额,也不会显著影响后面红包的大小,从而避免了极端不均的情况。那么咱们再来看看咱们手气如何吧
现在看起来就比较像咱们领到红包的样子了,不知道你们是不是都是里面的二十多块呢,反正经常是里面的零点几(┬┬﹏┬┬)。这个调整系数实际上是对原始随机过程的一种修正,它让分配更加均匀,同时保留了足够的随机性,使得每个人打开红包时都充满了期待。