在参考此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());
}
}
答案 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);
}
}