程序中經常遇到隨機送紅包之類的情景,這個隨機還得指定概率,比如10%的機率可以得到紅包。那么java怎么實現一個簡單的概率計算了,見如下例子:
int randomInt = RandomUtils.nextInt(1,101); if(randomInt <= 10){ //100里面1個數,小於等於10的概率就是10% //do something }
RandomUtils工具類是commons-lang3包里面的
<dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> <version>3.7</version> </dependency>
如果要在某個數字區間產生一個隨機數,區間內部在不同的片段幾率不同如何實現呢?經常有這樣的場景,比如,隨機贈送紅包,范圍0.1元-100元,0.1-1元的概率是90%,1元-10元的概率是9%,10元-100元的概率是1%,也就是說數額越大得到的幾率越小!實現的原理如下圖:
原理就是,將范圍分割成一個個子范圍(片段),具體采用哪個范圍,再用機率判斷。片段機率可以依次排好序,映射成[1,100]之間的數字。然后隨機一個[1,100]之間的數,該數落在哪個區間,就采用哪個片段產生隨機數。具體源代碼如下:
package com.hdwang; import org.apache.commons.lang3.RandomUtils; import java.util.ArrayList; import java.util.List; /** * 按幾率產生隨機數 * 例如,產生0.1-100的隨機數,0.1-1的幾率是90%,1-10的幾率是9%,10-100的幾率是1% */ public class RateRandomNumber { /** * 產生隨機數 * @param min 最小值 * @param max 最大值 * @return 隨機結果 */ public static double produceRandomNumber(double min,double max){ return RandomUtils.nextDouble(min,max); //[min,max] } /** * 按比率產生隨機數 * @param min 最小值 * @param max 最大值 * @param separates 分割值(中間插入數) * @param percents 每段數值的占比(幾率) * @return 按比率隨機結果 */ public static double produceRateRandomNumber(double min,double max,List<Double> separates,List<Integer> percents){ if(min > max){ throw new IllegalArgumentException("min值必須小於max值"); } if(separates == null || percents==null || separates.size()==0){ return produceRandomNumber(min,max); } if(separates.size() +1 != percents.size()){ throw new IllegalArgumentException("分割數字的個數加1必須等於百分比個數"); } int totalPercent = 0; for(Integer p:percents){ if(p<0 || p>100){ throw new IllegalArgumentException("百分比必須在[0,100]之間"); } totalPercent += p; } if(totalPercent != 100){ throw new IllegalArgumentException("百分比之和必須為100"); } for(double s:separates){ if(s <= min || s >= max){ throw new IllegalArgumentException("分割數值必須在(min,max)之間"); } } int rangeCount = separates.size()+1; //例如:3個插值,可以將一個數值范圍分割成4段 //構造分割的n段范圍 List<Range> ranges = new ArrayList<Range>(); int scopeMax = 0; for(int i=0;i<rangeCount;i++){ Range range = new Range(); range.min = (i==0 ? min:separates.get(i-1)); range.max = (i== rangeCount-1 ?max:separates.get(i)); range.percent = percents.get(i); //片段占比,轉換為[1,100]區間的數字 range.percentScopeMin = scopeMax +1; range.percentScopeMax = range.percentScopeMin + (range.percent-1); scopeMax = range.percentScopeMax; ranges.add(range); } //結果賦初值 double r = min; int randomInt = RandomUtils.nextInt(1,101); //[1,100] for(int i=0;i<ranges.size();i++){ Range range = ranges.get(i); //判斷使用哪個range產生最終的隨機數 if(range.percentScopeMin <= randomInt && randomInt <= range.percentScopeMax){ r = produceRandomNumber(range.min,range.max); break; } } return r; } public static class Range{ public double min; public double max; public int percent; //百分比 public int percentScopeMin; //百分比轉換為[1,100]的數字的最小值 public int percentScopeMax; //百分比轉換為[1,100]的數字的最大值 } public static void main(String[] args) { List<Double> separates = new ArrayList<Double>(); separates.add(1.0); separates.add(10.0); List<Integer> percents = new ArrayList<Integer>(); percents.add(90); percents.add(9); percents.add(1); for(int i=0;i<100;i++) { double number = produceRateRandomNumber(0.1, 100, separates, percents); System.out.println(String.format("%.2f",number)); } } }