【功能实现】实现设置概率的随机数
程序员文章站
2022-05-04 10:52:54
1.故事背景 生成一个随机红包,红包的数值0.1元-100元不等,其具体概率为:0.1元为最小单位,0.1元到0.5元的概率为40%,0.5元到1元的概率为50%,1元-2元的概率为5%,2元-3元的概率为3%,3元-4元的概率为1%,4元-5元概率为0.99%,5元-100元的概率为0.01%。 ......
1.故事背景
生成一个随机红包,红包的数值0.1元-100元不等,其具体概率为:0.1元为最小单位,0.1元到0.5元的概率为40%,0.5元到1元的概率为50%,1元-2元的概率为5%,2元-3元的概率为3%,3元-4元的概率为1%,4元-5元概率为0.99%,5元-100元的概率为0.01%。
2.思考过程
其实问题很简单,把概率放到一条线段上,我们先把问题简单化,假设随机生成0的概率是40%, 生成1的概率是50%,生成2的概率为5%,生成3的概率是3%...,线段上的0.4/0.9/0.95都是计算上两个概率后的和,那么如果我们此时生成一个随机数n,他的随机 的区间是0到1,如果生成0.2,那么就会落到0-0.4的概率区间中,如果是0.7就是 0.4-0.9的概率区间中,符合问题逻辑。
3.实现方式
回到刚开始的故事,就是把第一层的概率逻辑拿过来,然后具体区间中生成的红包数额再进行一次随机数的生成,所以我设计了一个CommonRandom类来存放红包区间的最小值和最大值,还有个该区间的概率,
CommonRandom类
8 /** 9 * @author wangjun 10 * @Date 2018/3/6 11 */ 12 public class CommonRandom { 13 private Double min; 14 private Double max; 15 private Double chance; 16 private Double calculateRate; 17 18 private transient Integer reality = 0; 19 private transient Double realityRate; 20 21 public static CommonRandom getInstance(Double min, Double max, Double rate) { 22 CommonRandom commonRandom = new CommonRandom(); 23 commonRandom.setMin(min); 24 commonRandom.setMax(max); 25 commonRandom.setChance(rate); 26 return commonRandom; 27 } 28 29 public static String getDefault() { 30 return JsonUtils.toJson(getCommonRandom()); 31 } 32 33 public Double getMin() { 34 return min; 35 } 36 37 private void setMin(Double min) { 38 this.min = min; 39 } 40 41 public Double getMax() { 42 return max; 43 } 44 45 private void setMax(Double max) { 46 this.max = max; 47 } 48 49 public Double getChance() { 50 return chance; 51 } 52 53 private void setChance(Double chance) { 54 this.chance = chance; 55 } 56 57 public Double getCalculateRate() { 58 return calculateRate; 59 } 60 61 public void setCalculateRate(Double calculateRate) { 62 this.calculateRate = calculateRate; 63 } 64 65 public Integer getReality() { 66 return reality; 67 } 68 69 public void setReality(Integer reality) { 70 this.reality = reality; 71 } 72 73 public Double getRealityRate() { 74 return realityRate; 75 } 76 77 public void setRealityRate(Double realityRate) { 78 this.realityRate = realityRate; 79 } 80 81 private static List<CommonRandom> getCommonRandom() { 82 List<CommonRandom> commonRandomList = Lists.newArrayList(); 83 commonRandomList.add(CommonRandom.getInstance(0.1, 0.5, 0.4)); 84 commonRandomList.add(CommonRandom.getInstance(0.5, 1.0, 0.5)); 85 commonRandomList.add(CommonRandom.getInstance(1.0, 2.0, 0.05)); 86 commonRandomList.add(CommonRandom.getInstance(2.0, 3.0, 0.03)); 87 commonRandomList.add(CommonRandom.getInstance(3.0, 4.0, 0.01)); 88 commonRandomList.add(CommonRandom.getInstance(4.0, 5.0, 0.0099)); 89 commonRandomList.add(CommonRandom.getInstance(5.0, 100.0, 0.0001)); 90 return commonRandomList; 91 } 92 } 93 94 CommonRandom
生成randomUtil
8 /** 9 * @author wangjun 10 * @Date 2018/3/6 11 */ 12 public class RandomUtil { 13 /** 14 * 保留小数位数 15 */ 16 private static final int POW = (int) Math.pow(10, 3); 17 private static final double ERROR_RANDOM_RESULT = -1D; 18 19 public static Double randomRedPackMoney() { 20 List<CommonRandom> commonRandoms = CommonRandom.getCommonRandom(); 21 Double result = random(commonRandoms); 22 if (result == ERROR_RANDOM_RESULT) { 23 return 1; 24 } 25 return result 26 } 27 28 /** 29 * 返回指定概率生成的随机数 30 * 传入集合中的chance概率和应为1 31 * @param commonRandomList 配置生成随机数概率及区间 32 * @return 随机数 33 */ 34 public static Double random(List<CommonRandom> commonRandomList) { 35 if (CollectionUtils.isEmpty(commonRandomList)) { 36 return ERROR_RANDOM_RESULT; 37 } 38 double randomNumber = Math.random() * getLastRate(commonRandomList); 39 for (CommonRandom item : commonRandomList) { 40 if (randomNumber < item.getCalculateRate()) { 41 return getRandomNumber(item.getMax(), item.getMin()); 42 } 43 } 44 return ERROR_RANDOM_RESULT; 45 } 46 47 private static double getLastRate(List<CommonRandom> commonRandomList) { 48 return commonRandomList.get(commonRandomList.size() - 1).getCalculateRate(); 49 } 50 51 private static Double getRandomNumber(Double max, Double min) { 52 return Math.floor((Math.random() * (max - min) + min) * POW) / POW; 53 } 54 }
上一篇: 无锁之CAS
下一篇: 全方位科普平面设计中的时尚流行复古风格