【发布时间】:2010-11-17 18:00:10
【问题描述】:
我想以精确的方式生成加权随机数。我可以用一个例子来解释一下:我的输入数组是 [1, 2, 3],它们的权重也是 [1, 2, 3]。在那种情况下,我希望看到 1 次,2 次 2 次,3 次 3 次。就像 3 -> 2 -> 3 -> 1 -> 3 -> 2...
我正在使用 rand() 实现随机数生成,以获得 [0, sum_of_weights) 之间的范围。 sum_of_weights = 1 + 2 + 3 = 6 对于上面的例子。我在互联网上搜索了现有的解决方案,但结果不是我想要的。有时我得到 2 多于 2 次,而序列中没有 1。它仍然加权但不完全给出我等待的次数。
我不确定下面的代码有什么问题。我应该做错事还是尝试完全不同?感谢您的回答。
int random_t (int items[], int items_weight[], int number_of_items)
{
double random_weight;
double sum_of_weight = 0;
int i;
/* Calculate the sum of weights */
for (i = 0; i < number_of_items; i++) {
sum_of_weight += items_weight[i];
}
/* Choose a random number in the range [0,1) */
srand(time(NULL));
double g = rand() / ( (double) RAND_MAX + 1.0 );
random_weight = g * sum_of_weight;
/* Find a random number wrt its weight */
int temp_total = 0;
for (i = 0; i < number_of_items; i++)
{
temp_total += items_weight[i];
if (random_weight < temp_total)
{
return items[i];
}
}
return -1; /* Oops, we could not find a random number */
}
我也尝试了一些不同的方法(代码如下)。它适用于我的情况,但整数溢出和静态变量的广泛使用使其成为问题。
如果您在给出 NULL 之前输入了一个输入数组并继续使用它。有点类似于 strtok() 的用法。
int random_w(int *arr, int weights[], int size)
{
int selected, i;
int totalWeight;
double ratio;
static long int total;
static long int *eachTotal = NULL;
static int *local_arr = NULL;
static double *weight = NULL;
if (arr != NULL)
{
free(eachTotal);
free(weight);
eachTotal = (long int*) calloc(size, sizeof(long));
weight = (double*) calloc(size, sizeof(double));
total = 0;
totalWeight = 0;
local_arr = arr;
for (i = 0; i < size; i++)
{
totalWeight += weights[i];
}
for (i = 0; i < size; i++)
{
weight[i] = (double)weights[i] / totalWeight;
}
srand(time(NULL));
}
while (1)
{
selected = rand() % size;
ratio = (double)(eachTotal[selected])/(double)(total+1);
if (ratio < weight[selected])
{
total++;
eachTotal[selected]++;
return local_arr[selected];
}
}
}
【问题讨论】:
-
“在这种情况下,我希望看到 1 次 1,2 次 2 次,3 次 3 次。” 抱歉,这不是随机的工作原理。
-
好像和上一个问题stackoverflow.com/questions/4108528/…类似