微信红包
初一,一家人聚在一起发红包,便对微信红包算法产生了些兴趣。ps:这里说的是群红包 。
普通红包
首先是普通红包~
简单地说就是金额和个数都是固定的……
直接计数红包个数就行了……
拼手气红包
这个就比较有意思了
需要考虑的东西就比较多了
- 不能超领(15个包到第14个就领光了)
- 不能少领(15个包都领完了还剩了钱)
- 每个包钱数随机
- 先后拆红包期望相同
- 单包不超过200
思路
思路借鉴于coderroc
添加200元限制
假设有1000元钱,分给十个人。1000/10 = 100元。这是期望值。从0.01到200的区间中(其中200=期望值×2)Random函数抽取一个数,就是第一个人获得红包的大小。假设第一个人获得了150元,那么剩下的850元平均分给9个人,这九个人平均获得红包大小为94元,那么第二个人的红包大小均匀分布于0.01元到188元的区间中,依次类推。如果Random数超过200重新抽取,如果抽取之后下一次Loop中的期望大于200重新抽取。算法可以保证最后一个人至少抽到0.01元。发红包之前计算期望大于200提示单个红包不多于200元
实现
主体逻辑
public static double getRandomMoney(RedPackage _redPackage) {
// remainSize 剩余的红包数量
// remainMoney 剩余的钱
if (_redPackage.remainSize == 1) {
_redPackage.remainSize--;
return (double) Math.round(_redPackage.remainMoney * 100) / 100;
}
Random r = new Random();
double min = 0.01; //
double max = _redPackage.remainMoney / _redPackage.remainSize * 2;
double money = r.nextDouble() * max;
money = money <= min ? 0.01: money;
money = Math.floor(money * 100) / 100;
_redPackage.remainSize--;
_redPackage.remainMoney -= money;
return money;
}
类体
class RedPackage {
int remainSize;
double remainMoney;
}
需要在获取随机数并计算momey
值时加入循环,判断money
以及下轮期望
是否小于200。如果不成立重新获取随机数。成立跳出Loop。
手机打的手懒就不改代码了
顺便
祝大家春节快乐,万事如意。