Рекомендуемый способ инициализировать srand?

63
задан An̲̳̳drew 29 January 2010 в 18:25
поделиться

8 ответов

Лучший ответ должен использовать материал случайного числа Повышения. Или если у Вас есть доступ к C++ 11, используют <random> заголовок.

, Но если мы говорим [приблизительно 113] и srand()
, лучший способ состоит в том, чтобы только использовать time():

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

    ...
}

убедиться сделать это в начале Вашей программы, и не каждый раз Вы звоните rand()!

Каждый раз, когда Вы запускаете, время () возвратит уникальное значение (если Вы не запустите приложение многократно в секунду). В системах на 32 бита это будет только повторяться каждые 60 лет или около этого.

я знаю, что Вы не думаете, что время достаточно уникально, но я нахожу, что это трудно верит. Но я, как было известно, был неправ.

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

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

 int main()
 {
     struct timeval time; 
     gettimeofday(&time,NULL);

     // microsecond has 1 000 000
     // Assuming you did not need quite that accuracy
     // Also do not assume the system clock has that accuracy.
     srand((time.tv_sec * 1000) + (time.tv_usec / 1000));

     // The trouble here is that the seed will repeat every
     // 24 days or so.

     // If you use 100 (rather than 1000) the seed repeats every 248 days.

     // Do not make the MISTAKE of using just the tv_usec
     // This will mean your seed repeats every second.
 }
52
ответ дан oleksii 24 November 2019 в 16:09
поделиться
#include <stdio.h>
#include <sys/time.h>
main()
{
     struct timeval tv;
     gettimeofday(&tv,NULL);
     printf("%d\n",  tv.tv_usec);
     return 0;
}

ТВ tv_usec находится в микросекундах. Это должно быть приемлемым семенем.

2
ответ дан user39307 24 November 2019 в 16:09
поделиться

Реальный вопрос, который необходимо задать сами, - то, в каком качестве случайности Вы нуждаетесь.

libc случайный LCG

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

, Если просто необходимо удостовериться, что различные экземпляры будут иметь различные инициализации, можно смешать идентификатор процесса (getpid), идентификатор потока и таймер. Смешайте результаты с xor. Энтропия должна быть достаточной для большинства приложений.

Пример:

struct timeb tp;
ftime(&tp);   
srand(static_cast<unsigned int>(getpid()) ^ 
static_cast<unsigned int>(pthread_self()) ^ 
static_cast<unsigned int >(tp.millitm));

По лучшему случайному качеству, используйте/dev/urandom. Можно сделать вышеупомянутый код портативным в использовании повышения:: поток и повышение:: date_time.

6
ответ дан Edouard A. 24 November 2019 в 16:09
поделиться

Лучший способ состоит в том, чтобы использовать другой генератор псевдослучайного числа. Вихрь Мерсенна (и Wichmann-выступ) является моей рекомендацией.

http://en.wikipedia.org/wiki/Mersenne_twister

7
ответ дан user39307 24 November 2019 в 16:09
поделиться

На окнах:

srand(GetTickCount());

обеспечивает лучшее семя, чем time() начиная с в миллисекундах.

9
ответ дан shoosh 24 November 2019 в 16:09
поделиться

при необходимости в лучшем генераторе случайных чисел не используйте libc рэнд. Вместо этого просто используйте что-то как /dev/random или /dev/urandom непосредственно (чтение в int непосредственно от него или что-то как этот).

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

15
ответ дан Evan Teran 24 November 2019 в 16:09
поделиться

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

unsigned long seed = mix(clock(), time(NULL), getpid());

, Где соединение:

// http://www.concentric.net/~Ttwang/tech/inthash.htm
unsigned long mix(unsigned long a, unsigned long b, unsigned long c)
{
    a=a-b;  a=a-c;  a=a^(c >> 13);
    b=b-c;  b=b-a;  b=b^(a << 8);
    c=c-a;  c=c-b;  c=c^(b >> 13);
    a=a-b;  a=a-c;  a=a^(c >> 12);
    b=b-c;  b=b-a;  b=b^(a << 16);
    c=c-a;  c=c-b;  c=c^(b >> 5);
    a=a-b;  a=a-c;  a=a^(c >> 3);
    b=b-c;  b=b-a;  b=b^(a << 10);
    c=c-a;  c=c-b;  c=c^(b >> 15);
    return c;
}
63
ответ дан Jonathan Wright 24 November 2019 в 16:09
поделиться

я предлагаю, чтобы Вы видели unix_random.c файл в коде Mozilla. (угадайте, что это - mozilla/security/freebl/...), это должно быть в freebl библиотеке.

там это использует информацию о системном вызове (как pwd, netstat....) для генерации шума для случайного числа; это записано для поддержки большинства платформ (который может получить меня призовой балл: D).

7
ответ дан FL4SOF 24 November 2019 в 16:09
поделиться
Другие вопросы по тегам:

Похожие вопросы: