1. 程式人生 > >java版根據權重抽獎演算法

java版根據權重抽獎演算法

根據權重進行抽取的演算法應用比較廣泛,其中抽獎便是主要用途之一。正好這幾天也正在進行抽獎模組的開發,整個抽獎模組涉及到的地方大概有三處,分別是後臺進行獎品的新增(同時設定權重和數量),前臺根據後臺配置生成抽獎佇列並根據指令開始抽獎活動,最後一部分是後臺統計中獎情況並設定物流狀態。本文主要針對前臺抽獎演算法進行介紹如何根據權重設定每個獎品被抽到的概率。

抽獎演算法的核心是根據權重設定隨機數出現的概率,在此我將它封裝成一個生成隨機數的隨機類,程式碼如下:



/**
 * JAVA 返回隨機數,並根據概率、比率
 * 
 */
public class MathRandom {
	
	private static Log logger = LogFactory.getLog(MathRandom.class);

	/**
	 * Math.random()產生一個double型的隨機數,判斷一下 每個獎品出現的概率
	 * 
	 * @return int
	 * 
	 */
	public int PercentageRandom(List<RewardPrize> prizes) {
		DecimalFormat df = new DecimalFormat("######0.00");  
		int random = -2;
		try{
			double sumWeight = 0;
			//計算總權重
			for(RewardPrize rp_1 : prizes){
				sumWeight += rp_1.getPrize_weight();
			}
			double randomNumber;
			randomNumber = Math.random();
			System.out.println("randomNumber是:" + randomNumber);
			double d1 = 0;
			double d2 = 0;
			
			for(int i=0;i<prizes.size();i++){
				d2 += Double.parseDouble(String.valueOf(prizes.get(i).getPrize_weight()))/sumWeight;
				if(i==0){
					d1 = 0;
				}else{
					d1 +=Double.parseDouble(String.valueOf(prizes.get(i-1).getPrize_weight()))/sumWeight;
				}
				if(randomNumber >= d1 && randomNumber <= d2){
					random = i;
					System.out.println("d1是:" + d1);
					System.out.println("d2是:" + d2);
					break;
				}
			}
		}catch(Exception e){
			System.out.println(e.getMessage());
			logger.error("生成抽獎隨機數出錯,出錯原因:" + e.getMessage());
			random = -1;
		}
		return random;
	}

	/**
	 * 測試主程式
	 * 
	 * @param agrs
	 */
	public static void main(String[] agrs) {
		int i = 0;
		MathRandom a = new MathRandom();
		List<RewardPrize> prizes = new ArrayList();
		for(int m=0;m<100;m++){
			RewardPrize rp = new RewardPrize();
			rp.setPrize_amount(10);//每個獎品數量設定10個
			rp.setPrize_weight(1);//每個獎品的權重都設定成1,也就是每個獎品被抽到的概率相同(可根據情況自行設定權重)
			prizes.add(rp);
		}
		for (i = 0; i <= 100; i++)// 列印100個測試概率的準確性
		{
			System.out.println(a.PercentageRandom(prizes));
		}
	}
}


簡單介紹一下上面的程式碼含義,首先計算出待選獎品的總權重,這樣做的目的是可以隨意設定獎品權重,不必再考慮權重之和是否等於100。隨機規則是首先生成一個隨機數randomNumber(生成的隨機數位於0到1的左開右閉區間),然後分別計算出當前獎品前前面所有有獎品(不包括當前獎品)的概率和d1和當前獎品後面(包括當前獎品)所有獎品的概率和d2,然後判斷生成的隨機數randomNumber是否已處於d1和d2之間,如果處於該區間之內則當前獎品將被抽中。