srand() — why call it only once?
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?
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);
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.