Генератор случайных чисел в C

Я пытаюсь создать случайное число 0 – 59, и я не удовлетворен функцией rand () в C. Вот код, который я играю с:

#include  #include  main() { int num; srand(time(NULL)); num = rand(); num = num % 59; printf("%d\n", num); } 

Я повторил прогон этого кода и заметил, что генерируемые случайные числа на самом деле не кажутся случайными. Сгенерированные числа, безусловно, следуют шаблону, так как каждый раз, когда я запускаю программу, число становится все больше, пока оно не вернется к началу (т.е. 2, 17, 21, 29, 38, 47, 54, 59, 4, 11 …. и т.д.).

Есть ли способ, которым я могу засеять функцию, чтобы каждый раз, когда я снова запускал функцию, я получал истинное случайное число с вероятностью 1/60 генерации? Или есть какие-то альтернативные методы, которые я могу реализовать самостоятельно, а не использовать функцию rand () в C?

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

Нет, в стандартной библиотеке C используется PRNG (генератор псевдослучайных чисел). Вы никогда не получите истинные случайные числа.

Однако вы можете засеять его чем-то, что изменяется чаще, чем time() , например, на POSIX:

 struct timeval tm; gettimeofday(&tm, NULL); srandom(tm.tv_sec + tm.tv_usec * 1000000ul); 

Кроме того, использование оператора modulo для генерации случайного числа не является хорошим решением (оно сильно уменьшает энтропию). Если у вас есть реализация libc в стиле BSD, используйте

 uint32_t n = arc4random_uniform(60); 

Или, если у вас нет этой функции:

 // random() is guaranteed to return a number in the range [0 ... 2 ** 31) #define MAX_RANDOM ((1 << 31) - 1) long n; do { n = random(); } while (n > (MAX_RANDOM - ((MAX_RANDOM % 60) + 1) % 60)); n %= 60; 

Обратите внимание на использование random() – он превосходит rand() (который имел и имеет несколько реализаций низкого качества). Эта функция может быть srandom() с помощью srandom() .

Или есть какие-то альтернативные методы, которые я могу реализовать самостоятельно, а не использовать функцию rand () в C?

Вы можете (конечно, еще, как это сделали бы авторы библиотеки C?), Но вам лучше не делать – это отдельная наука, чтобы написать хороший PRNG, так сказать.

Как ваша программа написана, вы должны повторно запускать ее каждый раз, чтобы получить новое случайное число, что также означает, что он каждый раз перебирается. Повторное поseleniumие PRNG плохое .

Вы хотите посеять один раз , а затем создать кучу случайных чисел.

Сделайте это так:

 int main(void) { int num, i; srand(time(NULL)); // Seed ONCE for(i=0; i<100; ++i) // Loop 100 times for random numbers { num = rand(); num = num % 59; printf("%d\n", num); } } 

Теперь вы должны получить гораздо лучшие результаты.

Каждый раз, когда вы повторно запускаете программу, вы повторно забираете с помощью time() , и эта функция продвигается только один раз в секунду (если вы повторно запустите программу достаточно быстро, вы получите тот же результат).

Тот факт, что он, кажется, увеличивается до тех пор, пока он не перевернется, предполагает, что первый вызов rand() возвращает немодифицированное семя – это число, которое увеличивается один раз в секунду. В этом случае вы получаете одинаковые результаты (или очень похожие результаты), как если бы вы запускали:

 printf("%d\n", time(NULL) % 59); 

Я уверен, вы можете понять, что с этим не так.

В этом случае, если вы использовали «более правильный» rand() * 59 / RAND_MAX , который должен предпочесть значение из «более случайных» битов, у вас будет еще худшая ситуация – результаты не изменятся на всех, возможно, на 500 секунд или больше.

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

Чтение из /dev/urandom должно обеспечить хорошее семя, и в этом случае вам не нужно будет беспокоиться о смешивании, но в противном случае вызов rand() пару раз должен помочь покончить с особенно яркими артефактами низкого качества семя, с которого вы начали (за исключением, конечно, проблемы, что он меняется только один раз в секунду).