工作需要,这两天写一个简单的java抽奖算法,因为逻辑简单不复杂,所以代码也很简洁,可以做到不同权重有不用的中奖概率(就类似于nginx集群一样,权重越大,概率越高),在这里将java概率随机抽奖代码抽离出来分享给大家。
具体需求:
给第三方推送数据,每个第三方根据预算会有不同的额度,考虑到服务器压力,所以采取了主动推送的方式,在每次推送的时候,需要根据第三方的配额计算出相应的概率,然后挑选一个第三方来推送。
思路分析:
从形式上看,跟随机抽奖几乎一模一样,都是在N中挑选1,而且还不是公平挑选,是带有概率性的。
由于只分享概率随机抽奖的算法,所以就暂不考虑上限的情况,简单的说一下算法部分的实现思路(重点在于计算概率和区间,我这里是数量固定,所以概率很好算,具体真实的抽奖业务中会很复杂)。
1、需要计算出每个第三方的配额在总配额中的占比情况:自身数量 / 总数量 = 各自占比;
2、用100来做随机区间(1也可以),计算出每个区间的随机数值跨度:比例 * 100 = 区间跨度;
3、根据跨度计算出每个区间的起始数值:从0开始按照每个跨度相加,最终将100拆分成N个区间;
代码实现:
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
/**
* Created by Felix on 2019/07/10.
*/
public class Lottery {
/**
* 计算自身相对于总体的比例
*
* @param self 自身
* @param all 总体
* @return 比例
*/
private static float getPercent(Integer self, Integer all) {
// 比例计算出来会有很多小数,为了看得清晰,要四舍五入一下
return new BigDecimal(self / all.floatValue()).setScale(2, BigDecimal.ROUND_HALF_UP).floatValue();
}
/**
* 根据比例,在100之间计算出区间跨度,进一步来计算中奖区间
*
* @param percent 比例
* @return 跨度
*/
private static int getRandom(float percent) {
// 如果getPercent中没有四舍五入,那么就需要在这里四舍五入
return new BigDecimal(percent * 100).intValue();
}
private void lottery() {
Integer allAmount