Как генерировать случайные числа в C с соответствующим интервалом? - PullRequest
0 голосов
/ 25 марта 2020

Мне пришлось сгенерировать заданное количество случайных значений с плавающей точкой в ​​диапазоне [1,10] для некоторого кода. Однако из-за некоторых ограничений интервал между случайными числами должен быть не менее dx (учитывая).

Я использую кодовые блоки. (float)rand()/(float)(RAND_MAX/(10)) генерирует случайные числа в диапазоне.

Теперь, чтобы достичь желаемого расстояния, как было сказано ранее, любые предложения по простой стратегии, легко реализуемые в C?

1 Ответ

0 голосов
/ 25 марта 2020

Самый простой способ сделать это без смещения - это продолжать генерировать случайные числа, пока они не удовлетворяют критериям:

#include <stdbool.h>
#include <stddef.h>
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
#include <time.h>


bool check_spacing(float* of, size_t count, float spacing) {
    // n^2 algorithm, but can be reduced to n lg n if you sort and then just compare to
    // previous item and either allocate a copy to sort or shuffle afterwards
    for (size_t i = 1; i < count; ++i) {
        for (size_t j = 0; j < i; ++j) {
            if (fabsf(of[i] - of[j]) <= spacing) return false;
        }
    }

    return true;
}

void generate_until_spacing(float* to, size_t count, float spacing, float rng(void*), void* context) {
    do {
        for (size_t i = 0; i < count; ++i) to[i] = rng(context);
    } while (!check_spacing(to, count, spacing));
}

float frng(void* context) {
    // Your original rng should have looked like `1 + rand() / (RAND_MAX / 9f)`
    // for range [1, 10], or `rand() / (RAND_MAX / 10f)` for range [0, 10]
    float* min_max = context;
    float min = min_max[0];
    float max = min_max[1];
    return min + (rand() / (RAND_MAX / (max - min)));
}

int main(void) {
    srand(time(NULL));

    float spacing = 0.2;
    float min = 1;
    float max = 10;

    float numbers[10];
    generate_until_spacing(numbers, 10, spacing, frng, (float[]) { min, max });

    for (size_t i = 0; i < 10; ++i) {
        printf(i == 0 ? "%f" : ", %f", numbers[i]);
    }
    putchar('\n');
}

Это гарантирует, что все сгенерированные числа действительно независимы (насколько позволяет ваш rng) .

Если после выбора номера вы должны были сгенерировать числа из уменьшенного диапазона, числа с экстремальными значениями более вероятны, так как они с меньшей вероятностью окажутся в уменьшенном диапазоне. Хотя это может быть хорошо для вашего приложения и, вероятно, будет намного быстрее.

Генерация в большем диапазоне и деление эквивалентны генерации в меньшем диапазоне, поэтому это не решает проблему (или Вы ограничиваете себя целочисленными коэффициентами dx, что, вероятно, не то, что вы хотите).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...