Как «randomize ()» случайные числа в C (Linux)? - PullRequest
6 голосов
/ 08 февраля 2011

Пытаясь генерировать случайные числа в C, rand () не генерирует разные числа каждый раз, когда я компилирую код, может кто-нибудь сказать мне, как использовать srand () или любой другой метод генерации.

Ответы [ 4 ]

11 голосов
/ 08 февраля 2011

Чтобы сгенерировать последовательность из псевдослучайных чисел, генератор должен быть засеянным . Семя полностью определяет последовательность чисел, которые будут произведены. В C, вы указываете srand, как вы указали. Согласно справочной странице srand(3), отсутствие явного заполнения означает, что генератор будет использовать 1 в качестве начального числа. Это объясняет, почему вы всегда видите одни и те же числа (но помните, что сама последовательность довольно случайна, причем качество зависит от используемого генератора, даже если последовательность всегда одинакова).

Пользователь mzabsky указывает, что один из способов получить семя, которое кажется случайным для человека, - это посеять время. Другой распространенный метод (который я только что увидел, что mzabsky также указывает - извините) - это заполнить генератор содержимым генератора случайных чисел системы, который извлекает из пула энтропии, питаемого такими вещами, как движение мыши, время диска и т. Д. не может извлечь много случайности из системного генератора, так как он не сможет собрать достаточно энтропии. Но если вы просто извлечете из него начальное число, вы выберете случайную последовательность случайных чисел в своей программе. Вот пример того, как сделать это в C на Linux:

unsigned int seed;
FILE* urandom = fopen("/dev/urandom", "r");
fread(&seed, sizeof(int), 1, urandom);
fclose(urandom);
srand(seed);

В свете ответа Конрада Мейера я подумал, что уточню немного подробнее. Я бы разделил использование случайных чисел на три категории:

  1. Вариация. Если вы используете случайные числа для создания, казалось бы, случайного или разнообразного поведения, например, в игре, вам не нужно слишком задумываться о теме или выборе правильного начального числа. Посмотрите со временем и посмотрите на какое-то другое решение, если оно окажется недостаточно хорошим. В этом сценарии даже относительно плохие ГСЧ выглядят достаточно случайными.
  2. Научное моделирование. Если вы используете случайные числа для научной работы, такой как вычисления Монте-Карло, вам нужно позаботиться о том, чтобы выбрать хороший генератор . Ваше семя должно быть исправлено (или изменено пользователем). Вы не хотите вариаций (в вышеприведенном смысле); вам нужно детерминированное поведение, но хорошая случайность.
  3. Криптография. Вы будете очень осторожны. Это, вероятно, выходит за рамки этой темы.
8 голосов
/ 08 февраля 2011

Это обычно используемое решение:

srand ( time(NULL) );

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

Или вы можете прочитать данные из /dev/random (откройте его, как любой другой файл).

4 голосов
/ 08 февраля 2011

Если вы используете ОС, которая не предоставляет / dev / random, используйте что-то вроде того, что показано ниже

timeval t1;<br> gettimeofday(&t1, NULL);<br> srand(t1.tv_usec * t1.tv_sec);

Этот фрагмент кода можно легко перенести на другойOS.

Для улучшения начального числа - вы можете объединить (возможно, используя MD5 или алгоритм контрольной суммы) показанный выше временной продукт с MAC-адресом хост-машины.

3 голосов
/ 08 февраля 2011

Будь осторожен; В справочной странице rand(3) в linux отмечается, что реализации rand() на некоторых платформах не дают хорошей случайности для младших битов. По этой причине вы можете использовать библиотеку для получения реальных случайных чисел. Glib предоставляет полезные функции, такие как g_random_int_range(), которые могут лучше соответствовать вашим целям.

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