加权随机数:边界情况

时间:2011-09-14 12:44:36

标签: java random numbers

在参考此post中给出的最佳答案时,我注意到rnd=sum_of_weight时出现了边界情况。修复是在[0,sum_of_weight)中生成随机数,但是我想知道为什么代码在这个边界情况下失败了?这是算法中的一个缺陷吗?

编辑:此外,权重数组是否需要从高到低排序?看起来是这样,基于减法循环。

以下是在上面的帖子中实现伪代码的Java代码。

int sum_of_weight = 0;



int []choice_weight = {50, 15, 15, 10, 10};         // percentages
int num_choices = choice_weight.length;

public void init() {

    for (int i = 0; i < num_choices; i++) {
        sum_of_weight += choice_weight[i];
    }
}

int next() {
    int rnd = (int)Util.between(0, sum_of_weight);// random(sum_of_weight);
    rnd=sum_of_weight;                      // force the exception by hitting boundary case
    //System.out.print("rnd=" + rnd);
    for (int i = 0; i < num_choices; i++) {
        if (rnd < choice_weight[i])
            return i;
        rnd -= choice_weight[i];
    }

    throw new RuntimeException("should never get here for rnd=" + rnd);
}

public static void main(String[] args) {
    SimpleWeight sw = new SimpleWeight();
    sw.init();
    for (int i=0; i < 10;i++) {
        System.out.println(sw.next());
    }
}

2 个答案:

答案 0 :(得分:3)

算法you link to的第2步说明:

  

2)选择0到小于总和权重的随机数。

对我来说,这清楚而明确地说明了正确的方法是从[0,sum_of_weight)中选择一个数字。从不同范围(例如包含sum_of_weight的任何范围)中挑选数字不是算法中的缺陷,它是该算法的实现中的缺陷。

编辑不,不需要对权重进行排序以使算法有效。

答案 1 :(得分:0)

对于那些发现它有用的人,这是上面的另一个实现。如果你想让它变得更好,也可以反馈。我还是个初学者。

import java.util.Random;

public class WeightedRandom {

    private int choiceWeight[];
    private int numChoices = 0;
    private int i = 0;
    private Random r = new Random();

    public WeightedRandom() {
        this.choiceWeight = new int[] { 60, 35, 5 };
        this.numChoices = choiceWeight.length;
    }

    public WeightedRandom(int[] choiceWeight) {
        this.choiceWeight = choiceWeight;
        this.numChoices = this.choiceWeight.length;
    }

    public int weightedRandomGenerator() {

        int sumOfWeight = 0;
        for (int i = 0; i < numChoices; i++) {
            sumOfWeight += choiceWeight[i];
        }

        int randomNumber = r.nextInt(sumOfWeight);
        for (int i = 0; i < numChoices; i++) {
            if (randomNumber < choiceWeight[i])
                return i;
            randomNumber -= choiceWeight[i];
        }

        throw new RuntimeException("should never get here for RandomNumber = " + randomNumber);
    }

    public void printWeightedAverage(int numberOfIterations) {
        int numberCount[] = new int[numChoices];

        for (int n = 0; n < numberOfIterations; n++) {
            i = weightedRandomGenerator();
            numberCount[i]++;
        }

        for (int n = 0; n < numChoices; n++)
            System.out.println("Occurance of " + n + " = " + (((double) numberCount[n]) / numberOfIterations) * 100 + "%");
        System.out.println("--------");
    }

    public static void main(String[] args) {

        WeightedRandom wr = new WeightedRandom();
        WeightedRandom wr2 = new WeightedRandom(new int[] { 49, 25, 15, 5, 3, 2, 1 });
        wr.printWeightedAverage(100_000_000);
        wr2.printWeightedAverage(100_000_000);
    }

}