营销奖励金额算法

        业务场景是用户买充值卡,如果买100元充值卡,就给账户充100加上奖励的金额,要求平均给用户充值本金+本金*3%的金额,最少给用户充本金+本金*1%,最多给用户充本金+本金*50%,如何去保证必须有一部分用户充到最大值并且有平均值在3%上下浮动呢?

        提供两个方法,以本金100元举例;

        一.创建一个队列,随机一千个数放入队列里,这一千个数的平均值是3元,最小值是1元,最大值是50,一个用户买产品的时候就从这个队列里面拿一个,如果大于一千人买就在取一遍队列里的值。

        二.两次随机数,第一次随机落到大奖金区间里面还是落到小奖金区间里面,概率是可以配置的,为了保证均值在3元上下浮动,小奖金区间是(最小值,2*平均值-最小值),最大值的区间是(最小值-最大值)。具体代码如下。


public class RandomUtils {
    private static Random random = new Random();
    private static final Logger logger = LoggerFactory.getLogger(RandomUtils.class);

   /**
    * 给定范围
    * 生成随机金额
    */
   public static Integer randomInt( int left , int right , int avg ){
      
      if( left - right > 0 ){
         
         throw new IllegalArgumentException("最小金额不应大于最大金额");
      }
      
      if( left == right ){
         
         return left ;
      }
      
      if( avg < left ) {
         
         return avg;
      }
      
      if( avg > right ){
         return  randomIntByDifference(left, avg);
      }
      
      int winProbability =5;// Integer.parseInt( JXJConfigInit.getMerchantConfig( Constants.SWELL_PROBABILITY ) + "" );
      int winRate =1000;// Integer.parseInt( JXJConfigInit.getMerchantConfig( Constants.SWELL_RATE ) + "" );
      logger.info( "RandomUtils.randomInt winProbability:{} winRate:{}", winProbability, winRate );
      int bonus = 0;
      if( winProbability > randomInt(0, winRate) ){
         /**
          * 
          * 大奖金
          */
         
         bonus = randomIntByDifference(left, right );
         if( ( bonus + left ) > right ){
            
            bonus = left ;
         }
         logger.info( "RandomUtils.randomInt largeAmount bonus:{}", bonus );

      }else{
         
         /**
          * 小奖金
          */
         
         bonus = randomIntByDifference(left, (avg * 2 - left));
         if( ( bonus + left ) > right ){

            bonus = left ;
         }

         logger.info( "RandomUtils.randomInt smallAmount bonus:{}", bonus );

      }
      
      if( bonus > right ){
         
         /**
          * 
          * 不允许超过最大金额
          */
         
         bonus = right;
      }
      return bonus;
   }
   
   public static Integer randomIntByDifference( int left , int right ){
      
      logger.info( "RandomUtils.randomIntByDifference left:{} right:{}", left, right );
      if( left - right > 0 ){
         
         throw new IllegalArgumentException("最小金额不应大于最大金额");
      }
      
      if( left == right ){
         
         return left ;
      }
      
      int dif = right - left + 1 ;
      Random rand = new Random();
      int bonus = rand.nextInt( dif ) + left;
      return bonus;
      
//    
//    int digit = right - left;
//    String digitStr = digit + "";
//    int digitLength = digitStr.length();
//    StringBuffer sb = new StringBuffer();
//    char [] ca = digitStr.toCharArray();
//    for (int i = 0; i < digitLength; i++) {
//       
//       char c = ca[ i ];
//       if( '0' == c  ){
//          
//          /**
//           * 
//           * 所有0置换为9
//           */
//          sb.append( randomInt( 0, 9 ) );
//          
//       }else{
//          
//          sb.append( randomInt( 0, Integer.parseInt( String.valueOf( c ) ) ) );
//          
//       }
//    }
//    
//    logger.info( "RandomUtils.randomIntByDifference randomNo:{}", sb.toString() );
//    return Integer.parseInt( sb.toString() );
   }
   private static Random r = new Random();
   public static Integer randomInt( int left , int right ){
      
      logger.info( "RandomUtils.randomInt left:{} right:{}", left, right );

      if( left - right > 0 ){
         
         throw new IllegalArgumentException("最小金额不应大于最大金额");
      }
      
      if( left == right ){
         
         return left ;
      }
      
      int seqs = right - left;
      int [] indexs = new int[ seqs + 1 ];
      
      for (int i = 0; i < indexs.length; i++) {
         
         indexs [ i ] = left++;  
         
      }
      
      int index = r.nextInt( seqs + 1 );
      logger.info( "RandomUtils.randomInt indexs [ index ]:{}", indexs [ index ] );
      return indexs [ index ] ; 
   }
   
   
   
   public static void main(String[] args) {
      
      int countmax=0,countmin=0,count=0 ,summax=0,summin=0;
      for (int i = 0; i < 10000; i++) {
         int r = randomInt(10, 500,50);
         if( r > 90 ){
            
            countmax+=r;
            summax++;
         }else{
            
            countmin+=r;
            summin++;
         }
         count+=r;

         
      }
      System.out.println((count)/10000);
      System.out.println(countmax/summax);
      System.out.println(countmin/summin);
      System.out.println((summax * 1.0d)/10000d);
      System.out.println(countmax/(count*1.0d));
   }
   

    /**
     * 示例:String reqNo = buildReqNo("CUC");
     * String reqNo = buildReqNo("JDP");
     * 
     */
    public static String buildReqNo(String requestModule)
    {
        if(requestModule != null && requestModule.length() == 3){
            StringBuffer sb = new StringBuffer();
            sb.append(new SimpleDateFormat("yyyyMMddHHmmssSSS").format(new Date()));
            sb.append(requestModule.toUpperCase());
            sb.append(getRegularRandomStr());
            return sb.toString();
        }else{
            throw new RuntimeException("Invalid requestModule");
        }
    }
    
    private static String getRegularRandomStr()
    {
        return lpad(5, (random.nextInt(100000)));
    }
    
    /**
     * 左补函数
     * 
     * @param length 长度
     * @param number 数字
     * @return
     */
    private static String lpad(int length, int number)
    {
        String f = "%0" + length + "d";
        return String.format(f, number);
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值