业务场景是用户买充值卡,如果买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); } }