二倍均值法:
假设总金额是M元,N个人,每次抢的金额=(0, (M/N) *2),比如,还是之前说的条件,金额100,人数10,
第一个人抢的金额是 (0,20),抢到的数值,根据正态分布,应该是10左右,远低于10的概率很小,同样远大于10的概率和很小,这里假设第一个人抢到的数值是10;
第二个人抢的金额是(0,90/9 *2)=(0,20),同第一个人,第二个人红包金额也应该是10附近;
剩下的人,以此类推。
查阅了“微信红包的架构设计”,里面就是使用的这个方法。但是,这个算法,也不是完美的,假如第一个人抢到15,第二个人的范围是(0,18.89),假如第二个人又抢到很高,那对后面的人是不利的
另外,还看到了一种叫“线性切割法”的算法,这个算法的思想是:把总金额数值,想象成一条绳子,对绳子切割N-1刀(N就是人的数量),每个人抢到的红包金额就是切割的绳子的占比,但是,这方法也不能避免“无限循环小数”问题;并且,对每个人抢到的金额尽量平均,该如何保证呢?需要考虑的点很多,时间复杂度、空间复杂度都比较高
// 生成随机数范围值,保留两位小数
function random(m, n) {
let r = Math.random()*(m-n)+n
let res = (r*100).toString().split('.')[0]
res = Number(res)/100
return res
}
function randAlloc(totals, n) {
let resValue = 0
let result = []
let total = totals
let length = n
for(let i=0; i<length-1; i++) {
let n = random((total-resValue)/(length-i)*2, 0.01)
resValue= (resValue*100+n*100)/100
result.push(n)
}
let last = (total*100-resValue*100)/100
result.push(last)
return result
}
console.log(randAlloc(100,10))