Я хотел бы генерировать взвешенные случайные числа точным способом.Я могу объяснить точное с помощью примера: мой входной массив [1, 2, 3] и их веса снова [1, 2, 3].В этом случае я ожидаю увидеть 1 для 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];
}
}
}