java Random 帶權重的隨機選擇


實際場景中,經常要從多個選項中隨機選擇一個,不過,不同選項經常有不同的權重。

/**
 * Created by xc on 2019/11/23
 * 帶權重的隨機選擇
 */
public class Test {

    public static void main(String[] args) {
        Pair[] options = new Pair[]{new Pair("first", 3.3), new Pair("second", 3.3), new Pair("third", 3.3)};
        WeightRandom rnd = new WeightRandom(options);
        for (int i = 0; i < 10; i++) {
            System.out.print(rnd.nextItem() + " ");
        }
    }


}

 

/**
 * Created by xc on 2019/11/25
 * 表示選項和權重的類Pair
 */
public class Pair {
    Object item;
    double weight;

    public Pair(Object item, double weight) {
        this.item = item;
        this.weight = weight;
    }

    public Object getItem() {
        return item;
    }

    public double getWeight() {
        return weight;
    }
}
/**
 * Created by xc on 2019/11/25
 * 代碼清單7-9 帶權重的選擇WeightRandom
 */
public class WeightRandom {
    private Pair[] options;
    private double[] cumulativeProbabilities;
    private Random rnd;

    public WeightRandom(Pair[] options) {
        this.options = options;
        this.rnd = new Random();
        prepare();
    }

    /**
     * prepare()方法計算每個選項的累計概率,保存在數組cumulativeProbabilities中
     */
    private void prepare() {
        int weights = 0;
        for (Pair pair : options) {
            weights += pair.getWeight();
        }
        cumulativeProbabilities = new double[options.length];
        int sum = 0;
        for (int i = 0; i < options.length; i++) {
            sum += options[i].getWeight();
            cumulativeProbabilities[i] = sum / (double) weights;
        }
    }

    /**
     * nextItem()方法根據權重隨機選擇一個,具體就是,首先生成一個0~1的數,
     * 然后使用二分查找,如果沒找到,返回結果是-(插入點)-1,所以-index-1就是插入點,插入點的位置就對應選項的索引。
     * @return
     */
    public Object nextItem() {
        double randomValue = rnd.nextDouble();
        int index = Arrays.binarySearch(cumulativeProbabilities, randomValue);
        if (index < 0) {
            index = -index - 1;
        }
        return options[index].getItem();
    }
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM