Srand () - зачем называть это только один раз? -- c поле с участием random поле с участием srand пол Связанный проблема

srand() — why call it only once?


78
vote

проблема

русский

Этот вопрос о комментарии в этом вопросе Рекомендуемый способ инициализации Srand? Первый комментарий говорит, что <код> srand() следует вызывать только один раз в приложении. Почему это так?

Английский оригинал

This question is about a comment in this question Recommended way to initialize srand? The first comment says that srand() should be called only ONCE in an application. Why is it so?

</div
        
   
   

Список ответов

111
 
vote
vote
Лучший ответ
 

Это зависит от того, что вы пытаетесь достичь.

Рандомизация выполняется в качестве функции, которая имеет начальное значение, а именно семену .

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

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

Семя обычно берется из текущего времени, которые являются секундами, как в new Attr()0 , поэтому, если вы всегда устанавливаете семена, прежде чем принимать случайный номер, вы получите то же количество, если Вы называете Srand / Rand Combo несколько раз в той же секунде .

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

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

Кроме того, вы можете попытаться увеличить точность в микросекунды (минимизация вероятности того же семени), требуется (<код> new Attr()1 ):

 <код> new Attr()2  
 

That depends on what you are trying to achieve.

Randomization is performed as a function that has a starting value, namely the seed.

So, for the same seed, you will always get the same sequence of values.

If you try to set the seed every time you need a random value, and the seed is the same number, you will always get the same "random" value.

Seed is usually taken from the current time, which are the seconds, as in time(NULL), so if you always set the seed before taking the random number, you will get the same number as long as you call the srand/rand combo multiple times in the same second.

To avoid this problem, srand is set only once per application, because it is doubtful that two of the application instances will be initialized in the same second, so each instance will then have a different sequence of random numbers.

However, there is a slight possibility that you will run your app (especially if it's a short one, or a command line tool or something like that) many times in a second, then you will have to resort to some other way of choosing a seed (unless the same sequence in different application instances is ok by you). But like I said, that depends on your application context of usage.

Also, you may want to try to increase the precision to microseconds (minimizing the chance of the same seed), requires (sys/time.h):

struct timeval t1; gettimeofday(&t1, NULL); srand(t1.tv_usec * t1.tv_sec); 
</div
 
 
     
     
24
 
vote

Случайные числа на самом деле псевдо случайные. Семя установлена ​​в первую очередь, из которого каждый вызов <код> rand получает случайное число, и изменяет внутреннее состояние, и это новое состояние используется в следующем <код> rand Call, чтобы получить другой количество. Поскольку определенная формула используется для генерации этих «случайных чисел», поэтому установка определенного значения семян после каждого вызова rand вернет тот же номер от вызова. Например <код> srand (1234); rand (); вернет одинаковое значение. Инициализация после начала состояния со значением семян будет генерировать достаточно случайных чисел, поскольку вы не устанавливаете внутреннее состояние с помощью srand , что делает эти цифры более вероятны случайными.

Как правило, мы используем <код> time (NULL) Возвращенные секунды при инициализации значения семян. Скажите <код> srand (time (NULL)); в цикле. Затем петля может повторять более одного раза в одну секунду, поэтому количество раз петлей итерат внутри цикла во втором <код> rand вызова в цикле вернет один и тот же «случайное число», что не желательно Отказ Инициализация его после начала программы установит семена один раз, и каждый раз <код> rand вызывается, создается новый номер, и внутреннее состояние модифицировано, поэтому следующий вызов <код> rand Возвращает номер, который достаточно случайно.

Например Этот код из http://linux.die.net/man/3/rand :

 <код> rand0  

Внутреннее состояние <Код> rand1 объявляется как глобальный. Каждый <код> rand2 вызов будет изменять внутреннее состояние и обновить его и вернуть случайное число. Каждый звонок rand3 будет иметь другой <код> rand4 значение, поэтому этот метод вернет разные номера каждый вызов.

Посмотрите на <код> rand5 внедрение; Это просто устанавливает значение семян, которое вы проходите к <код> rand6 . Поэтому, если вы установите значение rand7 , то же самое каждый раз перед вызовом <код> rand8 это вернется то же случайное значение, из-за идентичной формулы, применяемой на нем, что не желательно, как Функция сделана случайным.

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

 

Random numbers are actually pseudo random. A seed is set first, from which each call of rand gets a random number, and modifies the internal state and this new state is used in the next rand call to get another number. Because a certain formula is used to generate these "random numbers" therefore setting a certain value of seed after every call to rand will return the same number from the call. For example srand (1234); rand (); will return the same value. Initializing once the initial state with the seed value will generate enough random numbers as you do not set the internal state with srand, thus making the numbers more probable to be random.

Generally we use the time (NULL) returned seconds value when initializing the seed value. Say the srand (time (NULL)); is in a loop. Then loop can iterate more than once in one second, therefore the number of times the loop iterates inside the loop in a second rand call in the loop will return the same "random number", which is not desired. Initializing it once at program start will set the seed once, and each time rand is called, a new number is generated and the internal state is modified, so the next call rand returns a number which is random enough.

For example this code from http://linux.die.net/man/3/rand:

static unsigned long next = 1; /* RAND_MAX assumed to be 32767 */ int myrand(void) {     next = next * 1103515245 + 12345;     return((unsigned)(next/65536) % 32768); } void mysrand(unsigned seed) {     next = seed; } 

The internal state next is declared as global. Each myrand call will modify the internal state and update it, and return a random number. Every call of myrand will have a different next value therefore the the method will return the different numbers every call.

Look at the mysrand implementation; it simply sets the seed value you pass to next. Therefore if you set the next value the same everytime before calling rand it will return the same random value, because of the identical formula applied on it, which is not desirable, as the function is made to be random.

But depending on your needs you can set the seed to some certain value to generate the same "random sequence" each run, say for some benchmark or others.

</div
 
 
     
     
12
 
vote

Краткий ответ: Вызов <Код> srand() не like "Rolling of the Dice" для генератора случайных номеров. Также не похоже на перетаскивание палубы карт. Во всяком случае, это все больше похоже на резку колоды карт.

Подумайте об этом об этом. <Код> rand() сделки с большой палубы карт, и каждый раз, когда вы это называете, все, что он делает, выбирают следующую карту с верхней части колоды, дайте вам значение и верните эту карту на дно колоды. (Да, это означает, что «случайная» последовательность повторится через некоторое время. Это большая колода , хотя: обычно 4294 967 296 карт.)

Кроме того, каждый раз, когда ваша программа работает, совершенно новая упаковка карт, куплена в магазине игры, и каждый совершенно новый пакет карт всегда имеет ту же последовательность. Поэтому, если вы не сделаете что-то особенное, каждый раз, когда ваши программы выполняются, она получит точно такие же «случайные» номера от <код> rand() .

Теперь, вы можете сказать: «Хорошо, так как я могу перемешать колоду?» И ответ - по крайней мере, насколько rand и <код> srand - это то, что нет способа перетаскивать колоду.

Так, что делает <код> srand делать? Основываясь на аналогии, которую я зрят здесь, вызывая <код> srand(n) в основном нравится, как говоря, «вырезать палубу <код> n карты сверху». Но подожди, еще одна вещь: это на самом деле начать с другой совершенно новой колоды и порезать его <код> n карты сверху .

Так что если вы звоните <код> srand(n) , <код> rand()0 , <код> rand()1 , <код> rand()2 , ..., с тем же <Код> rand()3 Каждый раз, вы не просто получите не очень случайную последовательность, вы фактически получаете тот же номер от <код> rand()4 каждый раз. (Вероятно, не тот же номер, который вы передали <код> rand()5 , но тот же номер обратно из <код> rand()6 снова и снова.)

Так что самое лучшее, что вы можете сделать, это сократить колоду один раз , то есть звонить <код> rand()7 один раз, в начале вашей программы, с <код> rand()8 Это разумно случайно, так что вы начнете в другом случайном месте в большой палубе каждый раз, когда ваши программы выполняются. С <Код> rand()9 , это действительно лучшее, что вы можете сделать.

[P.s. Да, я знаю, в реальной жизни, когда вы покупаете совершенно новую колоду карточек, это обычно в порядке, а не в случайном порядке. Для аналогии здесь, чтобы работать, я представляю, что каждая палуба, которую вы покупаете из игрового магазина, казалось бы, случайным порядком, но точно так же, казалось бы, случайным порядком, что и все остальные палубы карточек, которые вы покупаете из тех же магазин. Вроде как одинаково переломные колоды карт, которые они используют в мостовых турнирах.]

 

Short answer: calling srand() is not like "rolling the dice" for the random number generator. Nor is it like shuffling a deck of cards. If anything, it's more like just cutting a deck of cards.

Think of it like this. rand() deals from a big deck of cards, and every time you call it, all it does is pick the next card off the top of the deck, give you the value, and return that card to the bottom of the deck. (Yes, that means the "random" sequence will repeat after a while. It's a very big deck, though: typically 4,294,967,296 cards.)

Furthermore, every time your program runs, a brand-new pack of cards is bought from the game shop, and every brand-new pack of cards always has the same sequence. So unless you do something special, every time your program runs, it will get exactly the same "random" numbers back from rand().

Now, you might say, "Okay, so how do I shuffle the deck?" And the answer -- at least as far as rand and srand are concerned -- is that there is no way of shuffling the deck.

So what does srand do? Based on the analogy I've been building here, calling srand(n) is basically like saying, "cut the deck n cards from the top". But wait, one more thing: it's actually start with another brand-new deck and cut it n cards from the top.

So if you call srand(n), rand(), srand(n), rand(), ..., with the same n every time, you won't just get a not-very-random sequence, you'll actually get the same number back from rand() every time. (Probably not the same number you handed to srand, but the same number back from rand over and over.)

So the best you can do is to cut the deck once, that is, call srand() once, at the beginning of your program, with an n that's reasonably random, so that you'll start at a different random place in the big deck each time your program runs. With rand(), that really is the best you can do.

[P.S. Yes, I know, in real life, when you buy a brand-new deck of cards it's typically in order, not in random order. For the analogy here to work, I'm imagining that each deck you buy from the game shop is in a seemingly random order, but the exact same seemingly-random order as every other deck of cards you buy from that same shop. Sort of like the identically shuffled decks of cards they use in bridge tournaments.]

</div
 
 
 
 
8
 
vote

Причина в том, что <код> rand()0 устанавливает начальное состояние случайного генератора, и все значения, которые генератор производит только «случайные», если вы не прикасаетесь к государству. < / P >.

Например, вы можете сделать:

 <код> rand()1  

А потом, если вы вызываете эту функцию несколько раз, так что <код> rand()2 возвращает одинаковые значения в соседних вызовах, вы только что получаете то же значение - это по дизайну.

 

The reason is that srand() sets the initial state of the random generator, and all the values that generator produces are only "random enough" if you don't touch the state yourself in between.

For example you could do:

int getRandomValue() {     srand(time(0));     return rand(); } 

and then if you call that function repeatedly so that time() returns the same values in adjacent calls you just get the same value generated - that's by design.

</div
 
 
3
 
vote

Упрощенное решение для использования rand()3 для генерации разных семян для экземпляров приложений, выполняемых с той же секундой, как видно.

 <код> rand()4  

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

 

A simpler solution for using srand() for generating different seeds for application instances run at the same second is as seen.

srand(time(NULL)-getpid()); 

This method makes your seed very close to random as there is no way to guess at what time your thread started and the pid will be different also.

</div
 
 
2
 
vote

Семена Srand Seeds Pseudorandom Number Generator. Если вы называете его более одного раза, вы будете нанести RNG. И если вы назовете это с тем же аргументом, он будет перезапущен ту же последовательность.

Чтобы доказать это, если вы делаете что-то простое, как:

 <код> #include <cstdlib> #include <cstdio> int main() { for(int i = 0; i != 100; ++i) {         srand(0);         printf("%d ", rand());     } }   

Вы увидите тот же номер, напечатанный 100 раз.

 

srand seeds the pseudorandom number generator. If you call it more than once, you will reseed the RNG. And if you call it with the same argument, it will restart the same sequence.

To prove it, if you do something simple like:

#include <cstdlib> #include <cstdio> int main() { for(int i = 0; i != 100; ++i) {         srand(0);         printf("%d ", rand());     } } 

you will see the same number printed 100 times.

</div
 
 
 
 
0
 
vote

1 Кажется, каждый раз Rand () работает, он установит новое семя для следующего Rand ().

2 Если srand () работает несколько раз, проблема в том, что в том случае, если два хода выполняются за одну секунду (время (нуль) не меняется), следующий Rand () будет таким же, как Rand () вправо после предыдущего SRAND ().

 

1Seems every time rand() runs, it will set a new seed for the next rand().

2If srand() runs multiple times, the problem is if the two running happen in one second(the time(NULL) does not change), the next rand() will be the same as the rand() right after the previous srand().

</div
 
 
 
 

Связанный проблема

0  Где хранятся переменные указателя и как компилятор доступа к нормальной переменной? [закрыто]  ( Where the pointer variables are stored and how compiler access normal variable ) 
<в сторону CLASS = "S-NEWACTS S-WELTIVE__info JS-Post-New Imide MB16« Роль = «Статус»> закрыт. Этот вопрос не соответствует Рекомендациям переполнения ...

1  Lnk2001: неразрешенный внешний символ _maincrtstartup  ( Lnk2001 unresolved external symbol maincrtstartup ) 
Я пытаюсь скомпилировать пример Win32 Parrot Ardrone SDK V1.8, используя Visual Studio 2012 Express для Windows Desktop. Я использую Windows 7 64-бит. SDK нап...

-1  Могу ли я использовать бесплатно () формально в VS2013?  ( Can i use free formally in vs2013 ) 
<код> #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <stdlib.h> #include <string.h> #define TSIZE 45 struct film{ char title[TSIZE]; int ...

0  Если безымянный семафор инициализируется в общей памяти, Shm_unlink () уничтожает семафор?  ( If an unnamed semaphore is initialized in shared memory does shm unlink destr ) 
Я использую POSIX SEMAPHORES и совместную память для координации одного производителя и одного потребительского буфера. Я хочу полностью инициализировать эту ...

2  Состояние не удалось для ldrloaddll  ( Status failed for ldrloaddll ) 
Я пытаюсь разрабатывать функцию ldrloaddll и мне не повезло с этим .. Я также проушинул для некоторых примеров, нет никакой много документации или правильного...

1  Проблемы с проверкой программы. Пожалуйста помоги!  ( Issues with program validation please help ) 
// Ребята у меня есть проблемы с моим кодом и разрывая мои волосы, пытаясь решить это. Вопрос в том, что я пытаюсь подтвердить свой код, поэтому он не рассчит...

0  Реализация ARP Smooth  ( Implementing arp sweep ) 
Я играю с libpcap / jpcap. Реализация Sweeper ARP. Я отправляю запрос на все IP в блоке до вещательного адреса и чтения ответов. Теперь я не могу думать о том...

4  Преобразовать фильм в Openni * .oni видео  ( Convert movie to openni oni video ) 
the библиотека Kinect Openni использует пользовательский формат видеофайла для хранения видеороликов, которые содержат информацию RGB + D. Эти видео имеют р...

0  Структура в C- Чтобы добавить атрибут во время выполнения?  ( Structure in c to add a attribute at runtime ) 
Как добавить переменную / атрибут участника на структуру из основного в C? ...

0  Подсчет и сортировка в C  ( Counting and sorting in c ) 
Я заряжаюсь с обычной программой C, которая подсчитывает ряд входов и соответственно классифицирует их. У меня на самом деле нет ни одного кода, написанного д...

0  Ошибка сборки Android NDK  ( Android ndk build error ) 
Я написал маленькую Hello World Program в C, а вот это <код> circ.onclick = { e: dom.MouseEvent => ... } 0 Вот файл make <код> circ.onclick = { e: dom....

7  Как портировать родной C-код на Android  ( How to port native c code on android ) 
Кто-нибудь может сказать мне, как портировать нативную программу C на платформе Android ..умел ли я включить некоторые библиотеки C или как именно ...? Спас...

0  Как я могу хранить разные виды операторов в 2D-массиве в C?  ( How can i store different kinds of operators in a 2d array in c ) 
Я хочу сделать функцию y = f (x) в виде строки и выяснить операторы в нем, чтобы хранить их в 2D-массиве, где каждый операторы будут рассматриваться как разде...

0  Как остановить программу хранения более одного символа в переменную CHAR? [Дубликат]  ( How to stop a program from storing more than a single character into a char vari ) 
<в сторону CLASS = "S-NEWACTS S-WELTIVE__info JS-Post-New Imide MB16« Роль = «Статус»> Этот вопрос уже есть ответы здесь : ...

0  Fead вызывает ошибку сегментации  ( Fread causing segmentation fault ) 
Попытка создать файл 1024 байтов случайных данных. Когда я запускаю это, я получаю ошибку неисправности сегментации на линии FREAD. Кто-нибудь видит, что я де...