java抽獎算法

1. 算法分析

根據概率將獎品劃分區間,每個區間代表一個獎品,然後抽取隨機數,反查落在那個區間上,即爲所抽取的獎品。


2. 代碼

核心算法

public class Arithmetic {
    // 放大倍數
    private static final int mulriple = 1000000;

    public int pay(List<Prize> prizes) {
        int lastScope = 0;
        // 洗牌,打亂獎品次序
        Collections.shuffle(prizes);
        Map<Integer, int[]> prizeScopes = new HashMap<Integer, int[]>();
        Map<Integer, Integer> prizeQuantity = new HashMap<Integer, Integer>();
        for (Prize prize : prizes) {
            int prizeId = prize.getPrizeId();
            // 劃分區間
            int currentScope = lastScope + prize.getProbability().multiply(new BigDecimal(mulriple)).intValue();
            prizeScopes.put(prizeId, new int[] { lastScope + 1, currentScope });
            prizeQuantity.put(prizeId, prize.getQuantity());

            lastScope = currentScope;
        }

        // 獲取1-1000000之間的一個隨機數
        int luckyNumber = new Random().nextInt(mulriple);
        int luckyPrizeId = 0;
        // 查找隨機數所在的區間
        if ((null != prizeScopes) && !prizeScopes.isEmpty()) {
            Set<Entry<Integer, int[]>> entrySets = prizeScopes.entrySet();
            for (Map.Entry<Integer, int[]> m : entrySets) {
                int key = m.getKey();
                if (luckyNumber >= m.getValue()[0] && luckyNumber <= m.getValue()[1] && prizeQuantity.get(key) > 0) {
                    luckyPrizeId = key;
                    break;
                }
            }
        }

        if (luckyPrizeId > 0) {
            // 獎品庫存減一
        }

        return luckyPrizeId;
    }
}

Prize bean

public class Prize {

    /**
     * 獎品唯一標示
     */
    private Integer prizeId;

    /**
     * 中獎概率
     */
    private BigDecimal probability;

    /**
     * 獎品數量
     */
    private Integer quantity;

    public Integer getPrizeId() {
        return prizeId;
    }

    public void setPrizeId(Integer prizeId) {
        this.prizeId = prizeId;
    }

    public BigDecimal getProbability() {
        return probability;
    }

    public void setProbability(BigDecimal probability) {
        this.probability = probability;
    }

    public Integer getQuantity() {
        return quantity;
    }

    public void setQuantity(Integer quantity) {
        this.quantity = quantity;
    }

}


3. 測試

prize1概率: 5%

prize2概率: 10%

prize3概率: 15%

prize4概率: 20%

prize5概率: 50%

public class Test {
    public static void main(String[] args) {
        List<Prize> prizes = new ArrayList<Prize>();
        Prize prize1 = new Prize();
        prize1.setPrizeId(1);
        prize1.setProbability(new BigDecimal(0.05));
        prize1.setQuantity(1);
        prizes.add(prize1);

        Prize prize2 = new Prize();
        prize2.setPrizeId(2);
        prize2.setProbability(new BigDecimal(0.10));
        prize2.setQuantity(10);
        prizes.add(prize2);

        Prize prize3 = new Prize();
        prize3.setPrizeId(3);
        prize3.setProbability(new BigDecimal(0.15));
        prize3.setQuantity(20);
        prizes.add(prize3);

        Prize prize4 = new Prize();
        prize4.setPrizeId(4);
        prize4.setProbability(new BigDecimal(0.20));
        prize4.setQuantity(50);
        prizes.add(prize4);

        Prize prize5 = new Prize();
        prize5.setPrizeId(5);
        prize5.setProbability(new BigDecimal(0.50));
        prize5.setQuantity(200);
        prizes.add(prize5);

        int prize1GetTimes = 0;
        int prize2GetTimes = 0;
        int prize3GetTimes = 0;
        int prize4GetTimes = 0;
        int prize5GetTimes = 0;
        Arithmetic arithmetic = new Arithmetic();
        int times = 1000;
        for (int i = 0; i < times; i++) {
            int prizeId = arithmetic.pay(prizes);
            switch (prizeId) {
                case 1:
                    prize1GetTimes++;
                    break;
                case 2:
                    prize2GetTimes++;
                    break;
                case 3:
                    prize3GetTimes++;
                    break;
                case 4:
                    prize4GetTimes++;
                    break;
                case 5:
                    prize5GetTimes++;
                    break;
            }
        }
        System.out.println("抽獎次數" + times);
        System.out.println("prize1中獎次數" + prize1GetTimes);
        System.out.println("prize2中獎次數" + prize2GetTimes);
        System.out.println("prize3中獎次數" + prize3GetTimes);
        System.out.println("prize4中獎次數" + prize4GetTimes);
        System.out.println("prize5中獎次數" + prize5GetTimes);
    }
}


結果:

通過1000次抽取,我們看出算法精度還是很高的。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章