-
-
Save antirez/52529aefb7000aa076f5fc6675252c3c to your computer and use it in GitHub Desktop.
/* MacOS libc PRNG is garbage! | |
* Test this on MacOS 10.12.3 (may be the same with other versions) | |
* You'll see three times the same output. | |
* Cheers by @antirez. */ | |
#include <stdio.h> | |
#include <stdlib.h> | |
int main(void) { | |
/* Note, 1000000, 1000001, 1000002 are not special. | |
* You can use any other "near" seeds and MOD 7 the sequence will be the same. */ | |
srand(1000000); | |
printf("%d\n", rand() % 7); | |
srand(1000001); | |
printf("%d\n", rand() % 7); | |
srand(1000002); | |
printf("%d\n", rand() % 7); | |
return 0; | |
} |
Is this post satire? with an unbiased PRNG there will be a subsequence of three 0's like this in every 7^3 (343) sequence of seeds. 6 more if you're willing to accept a subsequence of any particular digit. Also this isn't an unbiased test. rand() % 7 will bias slightly in favor of the value 0 because RAND_MAX isn't a whole multiple of 7.
sigh. I missed the comment, and only read the code. It does look like rand() on Mac has some kind of internal periodicity. Which is bad.
^ makes sense.
using the first seed gives
4
1
1
3
0
or
21585
18586
29373
4301
3304
without the modulus
every time.
Less a bug, more an intended, but sucky, feature.
There is some confusion here about crypto-PRNG, my example above, which is not limited to the seeds I selected, and so forth. So:
- The problem is not that the rand() sequence is deterministic. Here I'm not even checking that its distribution is random-looking.
- The special seeds I wrote above are just examples, the % 7 same results for different X, X+1, X+2 seeds will happen for almost all the seeds.
- It is trivial to have a fast PRNG that provides a decent distribution, and that by changing the seed produces a very different sequence.
- My claim is documented in the implementation itself... so the code acknowledges it.
- srand(time(NULL)) is a huge programming pattern to just say: give me a different sequence every different second I run it.
@colmmacc read my last post. You misunderstood the point completely. Happens for every possible N seeds that are just similar numbers.
TLDR: it happens even with this code.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main(void) {
int seed = time(NULL);
srand(seed+1);
printf("%d\n", rand() % 7);
srand(seed+2);
printf("%d\n", rand() % 7);
srand(seed+10);
printf("%d\n", rand() % 7);
return 0;
}
Copying here from my twitter:
BTW, OpenBSD replaced all those crappy libc PRNGs with one good cryptographically secure PRNG.