我有N个选项,介于1到数千之间。例如,我将用3个选项解释它,但我需要这个算法适用于N个选项。
我需要随机获得这三个选项中的一个,但根据概率。
我通过生成0到100之间的随机数来实现它,并且我正在做一些沉重和丑陋的代码来知道数字介于0和A可能性数字之间,A可能性和B可能性之间等等
你知道更好的方法吗?
答案 0 :(得分:5)
在您需要的范围内选择一个随机数,开始从该数字中减去每个选项的概率,直到达到0.您减去的最后概率就是您想要的。
int[] possibilities = new int[] {20,50,30};
Random rand = new Random();
int r = rand.nextInt(100);
int i = 0;
for (i=0;i<possibilities.length; i++) {
r -= possibilities[i];
if (r <= 0)
break;
}
System.out.println(i); // the index of the possibility
答案 1 :(得分:5)
即使给出了大量不同的选项(假设您不止一次从同一组选项中选择),其中一个方法是执行此操作,即构建一个累积概率表,然后对它们进行二进制搜索。 / p>
也就是说,假设您有以下预期结果:[0.2,0.2,0.5,0.05,0.05]
我们通过使每个元素成为原始列表中所有前面元素的总和来构建一组累积概率:[0.0,0.2,0.4,0.9,0.95]
要随机选择结果,我们会生成0到1之间的随机数,并对列表进行二进制搜索,以找到小于它的最大索引。这将选择每个元素与它与前一个元素之间的差距成比例,这是原始概率的数量。
答案 2 :(得分:3)
如何生成可能性的“地图”:a - 30,b - 80(a + 50%),c - 100(b + 20%)
m = [30,80,100]
然后你生成一个从0到100的数字并从a到c开始检查并在第一个为真时停止。
int[] m = {30, 80, 100};
Random rand = new Random();
int r = rand.nextInt(100);
for (int i = 0; i < m.length; i++){
if (r < m[i]){
// the i-th possibilty occured!
break;
}
}
答案 3 :(得分:2)
创建一个包含所需粒度的元素的表,例如。为1%,它将是100元素表。 根据您所需的概率分布,在表格中填写您的选项 在元素表的相同范围内绘制一个随机int。 使用它作为索引从表中获取选项。
让我们说(为简单起见)您只允许10%的更改和您给定的A,B,C选项 然后 (伪代码)
chances[]={A,A,A,B,B,B,B,B,C,C}
index=random() //make sure you get an int number in the range 0..9 here
myChance=chances[index]
它使用更多的内存作为基于概率表的循环,但它是O(1),它会对大N产生影响,如果你需要重复绘制
答案 4 :(得分:1)
创建一个更大的数组,其中包含与所需频率成比例的值为1,2,3的实例。例如,创建一个包含100,000个条目的数组,如果#342是例如7%,则将7个342的副本放入大数组中。然后使用统一的随机数和模块划分从大数组中随机选择一个值。
(请注意,如果您的概率是整数%并且加到100,则大数组的大小将是可能性的100倍。对于更精细的粒度,数组必须更大。)
答案 5 :(得分:1)
假设机会存储在 机会 数组中,您可以使用以下内容:
srand(time(NULL));
const double chances[] = {
0.2, 0.3, 0.1, 0.4
};
const double sigma = 1e-6;
int i, max = sizeof(chances)/sizeof(double);
double cumulative = 0.0, random_value = (double)rand()/(double)RAND_MAX;
for ( i = 0; i < max; i++ ) {
cumulative += chances[ i ];
if ( random_value - cumulative < sigma ) break;
}
printf( "Index of chance: %d\n", i );