微信红包算法在知乎上面有个专题讨论,其实红包的发放的随机算法,有两种作法:java
一、预生产:
算法
无外乎是在发红包的时候,随机去把金额生成到某个容器当中,而后要用的时候,一个一个的POP;微信
二、实时随机dom
用户在抢红包的时候,根据随机算法,算出此次用户要抢到多少测试
本文讲的是第二种。优化
之因此没弄第一种,是由于咱们的研发同窗张智哥,在之前的红包发放算法里面就是用的第二种,而我在征求他的意见看是否改为预生产的时候,他想偷个懒,不想再加表、动流程啥的。我想一想也是,动流程动出问题来了,到时候仍是得哥背锅。虽然做为研发一直都有丰富的背锅经验和强大的背锅心里,可是,可以少背个仍是少背个。spa
今后,也就开始了我比较黑暗的调整算法、调整参数的过程。code
红包算法关键是要简单、迅速的找出随机值,而这个坑,什么正态分布修正、什么平方后再开方取随机数优化,我都尝试过。orm
结果很惨淡:要么是前面的拿大头的概率很大,要么是后面的拿大头的概率很大,而前面拿大头,或者后面拿大头,是咱们运营的大爷们吐槽咱们的随机算法作得不如微信好的一个重要缘由(尼玛谈需求的时候不讲,还弄了个随机数范围要在8%到74%之间作限制,以为不爽就让研发背锅)。
get
废话完了,说下个人算法:
其实很简单,两个随机数,一个随机0到2;一个随机-1到1;两个随机数之和乘以均值,就是此次跑出来的随机数。而后再作下上下限的保护就好了。
个人代码里面偷了个懒,只作了下限,没作上限的保护。由于毕竟是研究算法,不是实际生产环境代码。
public static void dispath(int total, int people, int min){
for(int i = 0; i < people - 1 ; i++ ){
int leftPeople = people - i;
double avg = Double.valueOf(total)/leftPeople;
double ratio1 = getRandom(0, 2);
double ratio2 = getRandom(-1, 1);
double ratio = ratio1+ratio2;
int cur = (int) Math.floor(ratio * avg) > min ? (int) Math.floor(ratio * avg) : min;
// 扣减总额阅点数目
total = total - cur;
System.out.format("第 %d 个红包: %d 阅点,剩下: %d 阅点\n", i + 1, cur,total);
}
// 剩余的就是最后一个用户的阅点额度
System.out.format("第 %d 个红包: %d 阅点,剩下: 0 阅点\n", people, total);
}
结果嘛,还马马虎虎,反正跑了几回测试,基本上还能够知足要求,反正最大和最小的,不会固定在某个地方出现了。