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.
seed(0)
AFAIK. – Honeysuckersrand()
, then a few calls tostd::cout << rand() << "\n";
. Does it still happen? E.g., ideone.com/U14x0g. – Mycarand()/(RAND_MAX+1.0)
may lead to differing results (especially if you're using an algorithm that compounds errors), I don't think there is any standard rquirement that this division is done in the same precision or rounds in the same direction each time – HawaiianYes, I did try that. But then there is no issue
part, in case it wasn't clear) – Desai