• 抽奖基本算法讨论


    前言

     抽奖在我们程序过程中其实是到处可见的,大部分都是直接采用Random进行处理,而这里是针对于多个奖品抽中某一个奖品的概率的一种简单算法-offset

    代码如下

    1. import lombok.AllArgsConstructor;
    2. import lombok.Data;
    3. import java.util.ArrayList;
    4. import java.util.LinkedHashMap;
    5. import java.util.List;
    6. import java.util.Map;
    7. import java.util.concurrent.ThreadLocalRandom;
    8. @Data
    9. public class LotteryTest {
    10. public static void main(String[] args) {
    11. List prizeList = new ArrayList<>();
    12. prizeList.add(new Prize("一等奖", 50));
    13. prizeList.add(new Prize("二等奖", 30));
    14. prizeList.add(new Prize("三等奖", 20));
    15. int lotteryCount = 10000;
    16. Map countMap = new LinkedHashMap<>();
    17. countMap.put("一等奖", 0);
    18. countMap.put("二等奖", 0);
    19. countMap.put("三等奖", 0);
    20. for (int k = 0; k < 30; k++) {
    21. for (int i = 0; i < lotteryCount; i++) {
    22. int a = 100;
    23. for (Prize prize : prizeList) {
    24. int r = ThreadLocalRandom.current().nextInt(a);
    25. if(r < prize.getL()) {
    26. countMap.put(prize.getName(), countMap.get(prize.getName()) + 1);
    27. break;
    28. }
    29. a = a - prize.getL();
    30. }
    31. }
    32. System.out.println(countMap);
    33. countMap.forEach((t, v) -> {
    34. countMap.put(t, 0);
    35. });
    36. }
    37. }
    38. @Data
    39. @AllArgsConstructor
    40. static class Prize {
    41. private String name;
    42. private int l;
    43. }
    44. }

    运行结果如下

    {一等奖=4988, 二等奖=2941, 三等奖=2071}
    {一等奖=5087, 二等奖=2924, 三等奖=1989}
    {一等奖=5084, 二等奖=2955, 三等奖=1961}
    {一等奖=4915, 二等奖=3062, 三等奖=2023}
    {一等奖=4975, 二等奖=3105, 三等奖=1920}
    {一等奖=4923, 二等奖=3112, 三等奖=1965}
    {一等奖=4974, 二等奖=3016, 三等奖=2010}
    {一等奖=5016, 二等奖=2989, 三等奖=1995}
    {一等奖=4998, 二等奖=3002, 三等奖=2000}
    {一等奖=5022, 二等奖=3025, 三等奖=1953}
    {一等奖=4979, 二等奖=2975, 三等奖=2046}
    {一等奖=5033, 二等奖=2986, 三等奖=1981}
    {一等奖=4970, 二等奖=3064, 三等奖=1966}
    {一等奖=5005, 二等奖=3067, 三等奖=1928}
    {一等奖=4964, 二等奖=3080, 三等奖=1956}
    {一等奖=4993, 二等奖=3015, 三等奖=1992}
    {一等奖=5106, 二等奖=2915, 三等奖=1979}
    {一等奖=5051, 二等奖=2973, 三等奖=1976}
    {一等奖=4999, 二等奖=2965, 三等奖=2036}
    {一等奖=5076, 二等奖=2966, 三等奖=1958}
    {一等奖=5032, 二等奖=2984, 三等奖=1984}
    {一等奖=5010, 二等奖=3005, 三等奖=1985}
    {一等奖=5019, 二等奖=2947, 三等奖=2034}
    {一等奖=5016, 二等奖=2985, 三等奖=1999}
    {一等奖=5025, 二等奖=3022, 三等奖=1953}
    {一等奖=4912, 二等奖=2998, 三等奖=2090}
    {一等奖=5004, 二等奖=2971, 三等奖=2025}
    {一等奖=4983, 二等奖=2993, 三等奖=2024}
    {一等奖=5087, 二等奖=2870, 三等奖=2043}
    {一等奖=5011, 二等奖=2996, 三等奖=1993}

    代码核心点介绍

    1.  ThreadLocalRandom.current() 为线程安全的随机类

    2.  核心算法在于offset的判断,默认所有奖品的总概率是100,然后循环奖品,如果随机出来的值小于当前奖品则表示中了当前奖品,否则用100减去当前奖品的概率然后再进行抽奖,以此类推,你可以多尝试几次,中奖概率基本是公平的,如上面的例子

    一等奖中奖概率为:50%

    二等奖中奖概率为:30%

    三等奖中奖概率为:20%

    扩展点

            上面的例子奖品是不存在库存的,假设有库存的存在,那么得根据业务来说是直接不中,还是依次类推,像我之前的就是依次类推,怎么弄呢?思路如下

            假设一等奖没有库存了,那么就把一等奖的50%平均分给其他的奖品,也就是说二等奖变为了55%,三等奖变为了45%,然后再进行抽奖

            如果你的业务是不允许的话,那么只需要判断中奖时奖品没库存也代表不中就行了

  • 相关阅读:
    数据结构——八叉树
    10、Java 方法的递归调用详解(递归调用的分析和案例:阶乘、斐波那契、猴子吃桃)
    【排序算法】图解简单选择排序(图解堪比Debug显示每次循环结果)
    Java 泛型类型简单了解
    莫名其妙el-table不显示问题
    【JavaScript面试】网页轮播图的制作
    Linux用户管理— 用户相关文件-passwd文件- shadow文件-其他相关文件
    matlab实现MCMC的马尔可夫转换MS- ARMA - GARCH模型估计
    我司何晓磊受邀在“科创中国”做”创新”课程分享
    nacos适配达梦、瀚高、人大金仓数据库及部分源码探究
  • 原文地址:https://blog.csdn.net/zxc_user/article/details/133824462