java & orac版根據權重抽獎算法 (兩個方案都有)

java版本:java

/**
 * Created by liuyaowen on 2016/8/3.
 */

import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.List;

/**
 * JAVA 返回隨機數,並根據機率、比率
 *
 */
public class MathRandom {
    /**
     * 根據Math.random()產生一個double型的隨機數,判斷每一個獎品出現的機率
     * @param prizes
     * @return random:獎品列表prizes中的序列(prizes中的第random個就是抽中的獎品)
     */
    public int getPrizeIndex(List<Prize> prizes) {

        int random = -1;
        try{
            //計算總權重
            double sumWeight = 0;
            for(Prize p : prizes){
                sumWeight += p.getPrize_weight();
            }
            //產生隨機數
            double randomNumber;
            randomNumber = Math.random();
            System.out.println("隨機誰:"+randomNumber);
            //根據隨機數在全部獎品分佈的區域並肯定所抽獎品
            double d1 = 0;
            double d2 = 0;
            for(int i=0;i<prizes.size();i++){

                if(i==0){
                    d1 = 0;
                }else{
                    d1=d2;
                }
                d2 += Double.parseDouble(String.valueOf(prizes.get(i).getPrize_weight()))/sumWeight;

                if(randomNumber >= d1 && randomNumber <= d2){
                    random = i;
                    break;
                }
            }
        }catch(Exception e){
            System.out.println("生成抽獎隨機數出錯,出錯緣由:" +e.getMessage());
        }
        return random;
    }
    /**
     * 測試主程序
     *
     * @param agrs
     */
    public static void main(String[] agrs) {

        System.out.println("8%(2<<3)==="+8%(2<<3));


        int i = 0;
        MathRandom a = new MathRandom();
        int[] result=new int[4];
        List<Prize> prizes = new ArrayList<Prize>();

        Prize p1 = new Prize();
        p1.setPrize_name("范冰冰海報");
        p1.setPrize_weight(4);//獎品的權重設置成1
        prizes.add(p1);

        Prize p2 = new Prize();
        p2.setPrize_name("上海紫園1號別墅");
        p2.setPrize_weight(1);//獎品的權重設置成2
        prizes.add(p2);

        Prize p3 = new Prize();
        p3.setPrize_name("奧迪a9");
        p3.setPrize_weight(3);//獎品的權重設置成3
        prizes.add(p3);

        Prize p4 = new Prize();
        p4.setPrize_name("雙色球彩票");
        p4.setPrize_weight(2);//獎品的權重設置成4
        prizes.add(p4);

        System.out.println("抽獎開始");
        for (i = 0; i < 10000; i++)// 打印100個測試機率的準確性
        {
            int selected=a.getPrizeIndex(prizes);
            System.out.println("第"+i+"次抽中的獎品爲:"+prizes.get(selected).getPrize_name());
            result[selected]++;
            System.out.println("--------------------------------");
        }
        System.out.println("抽獎結束");
        System.out.println("每種獎品抽到的數量爲:");
        System.out.println("一等獎:"+result[0]);
        System.out.println("二等獎:"+result[1]);
        System.out.println("三等獎:"+result[2]);
        System.out.println("四等獎:"+result[3]);
    }

}


class Prize{

    private int id;//獎品id
    private String prize_name;//獎品名稱
    private int prize_amount;//獎品(剩餘)數量
    private int prize_weight;//獎品權重

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getPrize_name() {
        return prize_name;
    }

    public void setPrize_name(String prize_name) {
        this.prize_name = prize_name;
    }

    public int getPrize_amount() {
        return prize_amount;
    }

    public void setPrize_amount(int prize_amount) {
        this.prize_amount = prize_amount;
    }

    public int getPrize_weight() {
        return prize_weight;
    }

    public void setPrize_weight(int prize_weight) {
        this.prize_weight = prize_weight;
    }
}

 

 

 

oracle版:sql

function FN_LOAD_PRIZE(P_ACTIVITYID varchar2, --活動名字
                              P_GROUP varchar2 --新老用戶區分
                              ) return Number is                           
    v_sumWeight number(4,2);--總的權重
    --根據隨機數在全部獎品分佈的區域並肯定所抽獎品
    v_d1 number(18,10);
    v_d2 number(18,10);
    v_random number(18,10);--隨機數
    v_index number;--循環中的下標
    v_prize number; --獎品列表prizes中的序列(prizes中的第random個就是抽中的獎品)
 
    --獎品池 
    cursor cur_prizeinfo is
          select * from fsapi.tprizeinfo t 
          where t.pgroup='old' and t.activityno='8A0D108DCEE640D98351791D672C500E';

    prizeinfo cur_prizeinfo%rowtype;
  begin
      v_d2 :=0;  v_index :=0;
  
    --1.計算總的權重
    select sum(t.pweight) into v_sumWeight from fsapi.tprizeinfo t where t.pgroup='old' and t.activityno='8A0D108DCEE640D98351791D672C500E';  
   --2.生產隨機數
   select dbms_random.value  into v_random from dual ;
   
   dbms_output.put_line('活動NO:'||P_ACTIVITYID||',分組:'||P_GROUP||'總的權重:'||v_sumWeight||'隨機數:'||v_random);
 
    --3.循環獎品池
    open cur_prizeinfo;--打開遊標
    loop
      fetch cur_prizeinfo into prizeinfo;
      exit when cur_prizeinfo%notfound;
            --dbms_output.put_line('獎品名字'||prizeinfo.pname||',分組:'||prizeinfo.pgroup||'總的權重:'||prizeinfo.pweight);
            if (v_index = 0) then
                   v_d1 := 0;
               else
                   v_d1 := v_d2;
            end if;
            
            v_d2 := v_d2+(prizeinfo.pweight / v_sumWeight);
            
          dbms_output.put_line('v_d1:'||v_d1||',v_d2:'||v_d2||'v_random:'||v_random||'pweight:'||prizeinfo.pweight);
           --計算區段是否在獎品中。     if(randomNumber >= d1 && randomNumber <= d2){ 
           if (v_random >= v_d1 and v_random <= v_d2 and prizeinfo.povercount>0) then
                v_prize := prizeinfo.pid;--返回獎品ID
            
                --更新獎品數量
                update fsapi.tprizeinfo t set t.povercount=t.povercount-1 where t.pid=prizeinfo.pid;
                commit;
                
                exit;

           end if;
            
            
            v_index := v_index+1;

		end loop;
		close cur_prizeinfo;
     
   return v_prize;
  end;
相關文章
相關標籤/搜索