java & orac版根据权重抽奖算法 (两个方案都有)

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版:

  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;

 

转载于:https://my.oschina.net/u/557580/blog/731205

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值