srand initialization

My main question is at the very bottom. The information here is supporting info.

I am a fairly experienced programmer and have fairly good understanding of good and bad code but a friend freaked out at me when I had a dual initialization of srand in some code I sent him and I'm struggling to understand why. At the beginning of my main I had the following line which i use fairly regularly:

srand((unsigned int)time(NULL));rand();rand();srand((unsigned int)rand());

I understand that this is bad from the fact that it wastes 2 rand() statements but I commonly use it to get better spread in my programs rand for testing, specifically when I need to run the program shortly after a previous run. I make 1 seed with the time and then use two rands (the first one is linear with time and the second one is still a fairly small increase), finally reinitializing srand with a somewhat random seed. The only time I could ever see this causing issues is if my program was run many, many times by another program, although that causes issues with most programs.

Main question: He said that it's bad because you are never supposed to prep rand's seed (srand) more than once, can someone explain this to me?
Last edited on
> srand((unsigned int)time(NULL));rand();rand();srand((unsigned int)rand());

doesn't give you any extra randomness over just srand((unsigned int)time(NULL));. In either case, the next random number that is generated is deterministically arrived at based on the initial seed value.


Prefer using the C++ random number generation facilities provided in the header <random>. The drop in replacement for std::srand()/std::rand() is the mersenne twister std::mt19937 - it is reasonably fast and has measurably better quality.
1
2
3
4
5
6
7
8
#include <random>
#include <iostream>

int main()
{
    std::mt19937 twister( std::time(0) ) ;
    for( int i=0 ; i<10 ; ++i ) std::cout << twister() << '\n' ;
}
I would use the random header but the header I have for it requires requires the new C++ standard to be enforced and I don't really want to do that.

You're right in the fact that it's no more random than it is before, but the first rand() called no longer goes up by 1 by every second and will jump around "seemingly" randomly so it is more psuedorandom than it normally is. If I only had srand(time(NULL)) and then printed rand() I would get numbers that increased linearly every time I ran the program based on how much time had ellapsed since my last run. I do not want this. I want a more random distribution of numbers with respect to time which this gives. The other thing I sometimes use for this purpose is srand((unsigned int) pow(time(NULL)%100,3)) but this just makes the change cubic rather than linear. It's not that it gets me better distribution within the program, it's that it gets me better distribution over runs.

My actual question however remains unanswered. Why is it bad to initialize your seed more than once.
Last edited on
> Why is it bad to initialize your seed more than once.

It is ok to initialize your seed more than once, provided you do it (as in this case) before any random numbers are actually used. It is bad to reset the seed after some random numbers have been generated and used, because it would affect the overall randomness of the pseudo random number sequence.

> I can't figure out how to enforce it in code::blocks without running the compiler manually.

Menu: Settings -> Submenu: Compiler and debugger -> Tab: Compiler settings -> Subtab: Other options:
Type in: --std=c++0x
My actual question however remains unanswered. Why is it bad to initialize your seed more than once


There is nothing bad but it is useless just like adding const to the return type of function that returns by value.

Also initializing srand with time(0) on the same line(s) gives exactly same result since time(0) return seconds passed until now, and since intializing is done in a less then a second you achive completely nothing, just like if you would type:
1
2
3
int a = 3;
a = 3;
a = 3;

So your result is the same!

For example function (on windows) srand(GetTickCount()); however will do the job you want since it's in miliseconds, and not in seconds like std::time(0)

srand((unsigned int) pow(time(NULL)%100,3)) but this just makes the change cubic rather than linear. It's not that it gets me better distribution within the program, it's that it gets me better distribution over runs.


If you realy need a distribution then as already mentioned by others, use <random> which has good distributinos like bernouli, gaussian, log normal dist etc...


for example:

1
2
3
4
5
exponential_distribution<float> dist(exp(1));
shuffle_order_engine<ranlux24, 333> gen;
gen.seed(static_cast<unsigned>(time(false)));
for (int i = 0; i < 100; i++)
      cout << dist(gen) << endl;
Topic archived. No new replies allowed.