Почему srand(time(NULL)) работает без сбоев, хотя я неоднократно сбрасывал его?

У меня есть функция, которая создает вектор размера N и перемешивает его:

void rand_vector_generator(int N) {
   srand(time(NULL));
   vector <int> perm(N);
   for (unsigned k=0; k<N; k++) {
      perm[k] = k;
   }
   random_shuffle(perm.begin(),perm.end());
}

Я вызываю это из своей основной функции с помощью цикла:

for(int i=0; i<20; i++)
    rand_vector_generator(10);

Я ожидал, что это не даст мне достаточной случайности в моей перетасовке, потому что я вызываю srand(time(NULL)); при каждом вызове функции, и начальное значение не слишком отличается от последовательного вызова для вызова. Насколько я понимаю, я вызываю srand(time(NULL)); один раз, а не несколько раз, поэтому семя не «сбрасывается».

Этот thread несколько подтверждает то, что я ожидал получить в результате.

Вместо этого я получаю:

6 0 3 5 7 8 4 1 2 9 
0 8 6 4 2 3 7 9 1 5 
8 2 4 9 5 0 6 7 1 3 
0 6 1 8 7 4 5 2 3 9 
2 5 1 0 3 7 6 4 8 9 
4 5 3 0 1 7 2 9 6 8 
8 5 2 9 7 0 6 3 4 1 
8 4 9 3 1 5 7 0 6 2 
3 7 6 0 9 8 2 4 1 5 
8 5 2 3 7 4 6 9 1 0 
5 4 0 1 2 6 8 7 3 9 
2 5 7 9 6 0 4 3 1 8 
5 8 3 7 0 2 1 6 9 4 
7 4 9 5 1 8 2 3 0 6 
1 9 2 3 8 6 0 7 5 4 
0 6 4 3 1 2 9 7 8 5 
9 3 8 4 7 5 1 6 0 2 
1 9 6 5 3 0 2 4 8 7 
7 5 1 8 9 3 4 0 2 6 
2 9 6 5 4 0 3 7 8 1 

Эти векторы кажутся мне довольно случайно перетасованными. Что мне не хватает? Вызов srand каким-то образом существует в другой области, чем вызов функции, поэтому он не сбрасывается при каждом вызове? Или я неправильно понимаю что-то более фундаментальное здесь?


person Ritwik Biswas    schedule 09.04.2017    source источник
comment
random_shuffle не обязательно вызывает rand.   -  person aschepler    schedule 09.04.2017
comment
У стандарта определенно было несколько изменений на random_shuffle en.cppreference.com/w/cpp/ алгоритм/random_shuffle является (3) единственным допустимым в С++ 17 и более поздних версиях?   -  person Richard Critten    schedule 09.04.2017
comment
Как бы вы сказали, имеет ли что-то достаточную случайность? Вы проводили какие-либо статистические тесты?   -  person Kerrek SB    schedule 09.04.2017
comment
Вызов std::srand(std::time(0)) должен просто давать вам одно и то же начальное число каждую секунду, но генератор случайных чисел все равно будет генерировать подходящие случайные числа.   -  person Galik    schedule 09.04.2017
comment
Разве std::random_shuffle не перемешивается так, чтобы каждая возможная перестановка имела равную вероятность? Вы должны проверить, как часто происходит каждая перестановка. По сути, для вектора из двух элементов 1 и 2, 12 и 21 должны появляться в 50% случаев каждый.   -  person lapk    schedule 09.04.2017


Ответы (1)


В соответствии со стандартом использование std::rand как в std::random_shuffle, так и в std::shuffle определяется реализацией (хотя часто используется std::rand, это не гарантируется). Попробовать на другом компиляторе? Другая платформа?

Если вы хотите убедиться, что используется убедиться, что std::rand используется, вы должны разрешить своему коду использовать его явно (например, с помощью лямбда-выражения):

random_shuffle(perm.begin(), perm.end(), []{return std::rand();});

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

person YePhIcK    schedule 09.04.2017
comment
Std::rand не имеет правильной подписи для использования в качестве третьего аргумента std::random_shuffle. - person rici; 09.04.2017
comment
Ты прав. Я должен был сказать псевдокод, поскольку это была просто иллюстрация того, как это должно быть сделано, а не реальная реализация. - person YePhIcK; 09.04.2017