Reputation: 7210
Here's some code:
#include <iostream>
int main() {
srand(1);
std::cout << rand() << "\n";
srand(UINT_MAX);
std::cout << rand() << "\n";
}
This produces the following output:
16807
16807
Why do these two seeds produce the same result? The entire sequence of values they produce on successive rand()
calls is also identical. The range of possible values is too large for this to be a pure coincidence. Is it:
rand()
(and if so, I'm curious what that might be)(Possibly related: the seeds 10, 100, 1000, 10000, and 100000 produce 168070, 1680700, 16807000, 168070000, and 1680700000 respectively.)
Upvotes: 5
Views: 549
Reputation: 28269
A very simple usable random number generator is a Lehmer number generator. This RNG is maybe the simplest to implement in software, which is still usable, so probably it has the most issues with randomness, and most easy to analyze.
The number 16807 (aka the fifth power of 7) is associated with Lehmer RNG, because it was used in one of the earliest implementations in 1988 - apparently still in use today!
The formula for Nth random number is (using ^
for exponentiation):
R(n) = (seed * (16807 ^ n)) mod (2 ^ 31 - 1)
If you set seed = 1, n = 1:
R(1) = 16807 mod (2 ^ 31 - 1) = 16807
If you set seed = 2 ^ 32 - 1
:
R(1) =
(2 ^ 32 - 1) * 16807 ≡ (expressing 2^32 = 2^31 * 2)
((2 ^ 31 - 1) * 2 + 1) * 16807 ≡ (distributive law)
(2 ^ 31 - 1) * 2 * 16807 + 1 * 16807 ≡ (modulo 2^31-1)
16807
Here the equality of the first number in the random sequence is because the modulo-number in the Lehmer RNG is almost a power of 2 (2^31-1
), and your seed is also almost a power of 2 (2^32-1
).
The same would happen for seed = 2^31
.
Upvotes: 4
Reputation: 41106
tl;dr: rand()
is known to be that bad.
The actual values are implementation defined. I get the following values on my platform:
seed: 1 : 41
seed: 4294967295 : 35
seed: 10 : 71
seed: 100 : 365
seed: 1000 : 3304
seed: 10000 : 32694
rand()
can be relied on to look somewhat random to a casual user in a hurry. It is not portably suitable for anything else.
The implementation usually use a low quality generator (most often Linear Congruential with bad constants).
The required numeric range is 0...32767, and while implementation may they usually don't exceed that - so you can expect many seeds to result in the same value.
For C++ modern, see <random>
for reliable options.
Upvotes: 3
Reputation: 238381
I don't see a good reason why the unfortunate correlation that you observed would be designed into the implementation of rand
that you're using. It's most likely an accident of the implementation as you suggest. That said, I would also consider it a coincidence, that you can produce correlation with exactly those inputs. Another implementation could have other sets of unfortunate inputs.
if so, I'm curious what that might be
If your implementation is open source, then you can find out by reading the source. If it's proprietary you could still find a mention of the algorithm in some documentation, or if you're a customer, you could ask the implementer.
Upvotes: 0
Reputation: 3405
This depends on the implementation of you random number generator. See What common algorithms are used for C's rand()? for common implementations.
Usually the space of possible seed values is much shorter than your UINT_MAX
.
It could be that 1 and UINT_MAX
are mapped to the same internal seed.
Often Linear congruential generator are used for rand()
, then the first generated random number depends like
first_random_number = (seed * const + another_const) % third_constant
on the seed. This explains the dependence you found.
Upvotes: 2
Reputation: 1035
As stated here, If seed is set to 1, the generator is reinitialized to its initial value and produces the same values as before any call to rand or srand.
Also note that Two different initializations with the same seed will generate the same succession of results in subsequent calls to rand.
Upvotes: -3