概率抽奖算法

  1. 背景
    有一个抽奖活动,奖品有多种,每种奖品的抽中概率是设定好的,如何写这个抽奖逻辑呢?
  2. 代码案例
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Product {

    private Integer id;
    private String productName;
    private BigDecimal winRate;

}
    public static Product draw(List<Product> products) {
        BigDecimal decimal = new BigDecimal("10000");
        List<Integer> integers = products.stream()
                .map(product -> (product.getWinRate().multiply(decimal)).intValue())
                .collect(Collectors.toList());
        //1.划分概率区间
        Integer[] arr = new Integer[integers.size()];
        arr[0] = integers.get(0);
        for (int i = 1, sum = integers.get(0); i < integers.size(); i++) {
            arr[i] = sum + integers.get(i);
            sum += integers.get(i);
        }
        //2.计算随机数落入的区间索引
        int probabilityCount = decimal.intValue();
        //生成0-9999的随机数,0 <= Math.random() < 1
        int randomNum = (int) (Math.random() * probabilityCount);
        int index = getIndex(arr, randomNum);
        //3.根据索引值去查询出中奖商品
        return index == -1 ? null : products.get(index);
    }

    public static int getIndex(Integer[] arr, int randomNum) {
        if (randomNum < arr[0]) {
            return 0;
        }
        for (int i = 1; i < arr.length; i++) {
            if (randomNum >= arr[i - 1] && randomNum < arr[i]) {
                return i;
            }
        }
        return -1;
    }
  1. 测试
public static void main(String[] args) {
        List<Product> products = new ArrayList<>();
        products.add(new Product(1, "奖品1", new BigDecimal("0.2")));
        products.add(new Product(2, "奖品2", new BigDecimal("0.2")));
        products.add(new Product(3, "奖品3", new BigDecimal("0.15")));
        products.add(new Product(4, "奖品4", new BigDecimal("0.1")));
        products.add(new Product(5, "奖品5", new BigDecimal("0.05")));
        products.add(new Product(6, "下次再来", new BigDecimal("0.3")));
        double i1 = 0;
        double i2 = 0;
        double i3 = 0;
        double i4 = 0;
        double i5 = 0;
        double i6 = 0;
        int num = 1000000;
        for (int i = 0; i < num; i++) {
            Product discreteDraw = draw(products);
            if (discreteDraw.getId() == 1) {
                i1++;
            }
            if (discreteDraw.getId() == 2) {
                i2++;
            }
            if (discreteDraw.getId() == 3) {
                i3++;
            }
            if (discreteDraw.getId() == 4) {
                i4++;
            }
            if (discreteDraw.getId() == 5) {
                i5++;
            }
            if (discreteDraw.getId() == 6) {
                i6++;
            }
        }
        log.info("i1:{},i2:{},i3:{},i4:{},i5:{},i6:{}", i1 / num, i2 / num, i3 / num, i4 / num, i5 / num, i6 / num);

    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值