抽奖算法 百万次抽奖 单线程环境下 约 3.5 秒

摇奖算法:

package com.hs.services.utils;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import com.hs.commons.exception.ParameterErrorException;

/**
 * 摇摇机
 * @author ZHANGYUKUN
 *
 */
public class ShakeMachine {
    
    /**
     * 摇奖
     * @param gradeSlice 中奖等级 和 概率的关系
     * @return 0 表示不中奖,别的返回中奖等级
     */
    public static int shake(List<GradeSlice> gradeSlice) {
        if( gradeSlice.isEmpty() ) {
            return 0;
        }
        Collections.sort(gradeSlice);
        
        Double total = 0D;
        for(GradeSlice item :  gradeSlice) {
            total = total + item.getGrade().doubleValue();
        }
        if( total > 1D ) {
            throw new ParameterErrorException("总概率高于1");
        }
        
        double min = gradeSlice.get( gradeSlice.size()-1 ).getGrade().doubleValue();
        if( 1-total < min ) {
            min = 1-total;
        }
        
        int t = getNumberDecimalDigits( min ) ;
        int len = 0;
        if( t>len ) {
            len = t;
        }
        
        Double multiple = Math.pow( 10  , len );
        
        Double random = Math.random()*multiple;
        long r = random.longValue();
        
        int bj = 0;
        for(  GradeSlice item :  gradeSlice ) {
            Double totalItem =  item.getGrade().doubleValue()*multiple;
            long dbj = totalItem.longValue();
            bj +=dbj;
            if( r<bj ) {
                return item.getKey();
            }
        }
        return 0;
    }
    
    
      public static int getNumberDecimalDigits(double number) {
            if (number == (long)number) {
                return 0;
            }
            int i = 0;
            while (true){
                i++;
                if (number * Math.pow(10, i) > 1) {
                    return i;
                }
            }
     }
    
    
    
    public static void main(String[] args) {
        List<GradeSlice> list = new ArrayList<>();
        
        list.add(new GradeSlice(1, new BigDecimal(0.09) ));
        list.add(new GradeSlice(2, new BigDecimal(0.09) ));
        list.add(new GradeSlice(3, new BigDecimal(0.09) ));
        list.add(new GradeSlice(4, new BigDecimal(0.09)));
        list.add(new GradeSlice(5, new BigDecimal(0.09) ));
        list.add(new GradeSlice(6, new BigDecimal(0.09) ));
        list.add(new GradeSlice(7, new BigDecimal(0.09) ));
        
        
        int a0 = 0;
        int a1 = 0;
        int a2 = 0;
        int a3 = 0;
        int a4 = 0;
        int a5 = 0;
        int a6 = 0;
        int a7 = 0;
        
        System.out.println(  );
        
        
        long cc = System.currentTimeMillis();
        for( int i = 0;i<100000;i++ ) {
            int a = shake(list);
            
            switch( a ) {
            case 0:{
                a0++;
                break;
            }
            case 1:{
                a1++;
                break;
            }
            case 2:{
                a2++;
                break;
            }
            case 3:{
                a3++;
                break;
            }
            case 4:{
                a4++;
                break;
            }
            case 5:{
                a5++;
                break;
            }
            case 6:{
                a6++;
                break;
            }
            case 7:{
                a7++;
                break;
            }
            }
        }
        
        System.out.println( a7 );
        System.out.println( a6 );
        System.out.println( a5 );
        System.out.println( a4 );
        System.out.println( a3 );
        System.out.println( a2 );
        System.out.println( a1 );
        System.out.println( a0 );
        
        System.out.println("用時:" + (System.currentTimeMillis()-cc  ) );
        
    }

}

 

 

 

概率封装类:

package com.hs.services.utils;

import java.math.BigDecimal;

/**
 * 概率封装类
 * @author ZHANGYUKUN
 *
 */
public class GradeSlice implements Comparable<GradeSlice> {
	
	
	public GradeSlice(int key, BigDecimal grade) {
		super();
		this.key = key;
		this.grade = grade;
	}
	
	/**
	 * 中几等奖
	 */
	private int key;
	
	/**
	 * 中奖概率
	 */
	private BigDecimal grade;
	
	public int getKey() {
		return key;
	}
	public void setKey(int key) {
		this.key = key;
	}
	public BigDecimal getGrade() {
		return grade;
	}
	public void setGrade(BigDecimal grade) {
		this.grade = grade;
	}
	@Override
	public int compareTo(GradeSlice o) {
		return o.getGrade().compareTo( grade );
	}
	
	
	
	
	

}

  

 

posted on 2019-04-26 09:38  zhangyukun  阅读(171)  评论(0编辑  收藏  举报

导航