Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

c++ srand does not give same sequences of random numbers

Tags:

c++

srand

I have a optimisation algorithm which uses rand() and srand(). In order to be able to test the behaviour I have set the seed to a specific number in order to get the same sequence of random numbers on different runs of the program.

#define RN rand()/(RAND_MAX+1.0)
int main(int argc, char **argv)
{
    unsigned int seed=47456536;
    srand(seed);
    // a lot of stuff including RN
}

Issue is that in different runs I get different sequence of numbers. Is that possible?

like image 463
Cristina Avatar asked Feb 06 '15 21:02

Cristina


2 Answers

First off: Do not use rand. There are enough better alternatives.

Even the 2011 version of the C standard1 says in footnote 295:

There are no guarantees as to the quality of the random sequence produced and some implementations are known to produce sequences with distressingly non-random low-order bits. Applications with particular requirements should use a generator that is known to be sufficient for their needs.

In case that did not convince you, please let me add some emphasis:

There are no guarantees as to the quality of the random sequence produced and some implementations are known to produce sequences with distressingly non-random low-order bits. Applications with particular requirements should use a generator that is known to be sufficient [read: not this one] for their needs.

However, if you decide to use it against all reason, C99 7.20.2.2 and C11 7.22.2.2 both define the srand functon as follows:

(2) The srand function uses the argument as a seed for a new sequence of pseudo-random numbers to be returned by subsequent calls to rand. If srand is then called with the same seed value, the sequence of pseudo-random numbers shall be repeated. If rand is called before any calls to srand have been made, the same sequence shall be generated as when srand is first called with a seed value of 1.

(3) [...] The implementation shall behave as if no library function calls the srand function.

This means2 that either your standard library is broken, you are invoking undefined behaviour (e.g. writing to memory you should not write to) or are indeed having some other source of non-determinism. As you are surely aware, the most common sources of non-determinism are threading and reading input (keyboard, time, etc). Note that calling rand/srand from multiple threads is inherently unsafe3 beyond just the order of execution.

Since the rand random number generation facilities have only one central state, you should also be aware that libraries used by your code can modify it as well, therefore your problem may be hiding in some innocent call to a library function (excepting the standard library).

Let me also reiterate that the algorithm used by rand is not specified. Therefore, different compilers (more specifically different standard libraries) can and will produce different random numbers.

Finally, let me say again that you should not use rand if at all possible.

If there is any doubt left as to what you should be doing now, please just have a look at the following completely standards-compliant implementation of srand and rand:

#define RAND_MAX 32767
static int _rand_state = 1;
void srand(unsigned int seed) { _rand_state = (int)(seed % 32768); }
int rand() { return (++_rand_state) % 32768; }

Footnotes:

1. In case you are using linux, the man page rand(3) agrees: "on older rand() implementations, and on current implementations on different systems, the lower-order bits are much less random than the higher-order bits. Do not use this function in applications intended to be portable when good randomness is needed."

2. In combination with C99 7.20.2.1/3 or C11 7.22.2.1/3 which guarantees that the implementation behaves as if srand and rand are never called by any standard library function.

3. C11 explicitly allows data races when using these functions (C11 7.22.2.1/3 and C11 7.22.2.2/3) and C99 would do so as well if it knew the concept of threads and thread-safety.

like image 145
gha.st Avatar answered Nov 09 '22 10:11

gha.st


No, as the random number generator is defined to be deterministic given a fixed seed.

Is it possible that your "a lot of stuff including RN" might reorder things, maybe based on timing?

EDIT: "reordering": Are there external factors (time, data from files, multiple threads being scheduled etc) that might influence the order in which random numbers are requested?

EDIT: you can try to use something like Boost's RNGs; I've had excellent experience with boost::mt19937, and the fact that you can have generator "objects" eradicates the possibility that some library you're using is also getting random numbers via rand, messing up your sequence.

like image 37
Marcus Müller Avatar answered Nov 09 '22 10:11

Marcus Müller