C - How to ENSURE different random number generation in C when program is executed within the same second? C - How to ENSURE different random number generation in C when program is executed within the same second? unix unix

C - How to ENSURE different random number generation in C when program is executed within the same second?


To prevent 2 programs from generating the same pseudo-random numbers from rand(), they must, at a minimum effectively use different seeds for srand().

The source for the seeds for the 2 runs of the program could be derived from either

1) the same source - with a mechanism for unique generation.
2) a truly random source and the chance of same seed generation tolerable low.

1A With #1, time() is often used, but by definition, the programs start in the same second, so simplistic use of this fails.

1B Attempting to create a file that both program access to write something like "I started with this seed - 12345, so if you generate that seed try again".

1C Another approach is to use a finer time as hinted by (@Will) - That's better but the finer resolution may not be enough.

2A Some platforms provide a truly random number via a system function call, but since it depends on various esoteric system events , it is slow as compared to rand(), but useful for seeding srand(). Not all systems provide this.
[Edit] Did not see the Unix tag till later.
/dev/random & /dev/urandom (@Dietrich Epp) provide this feature.

2B One can use variant human reaction time like

printf("Press enter\n");unsigned u = 0;while (!keyboard_hit()) u++;srand(u);

Both: Combining (via exclusive-or ^) various sources like pid(), time(), reaction_time(), etc. helps. (See @nodakai)


Even with employing various mechanism to prevent a different seeding of a random number generator, 2 different runs still could generate the same sequence: about 1 in 20^10 (10,240,000,000,000) times per OP's code. After all these are random numbers, coming up with the same sequence could happen.

To absolutely prevent duplication, the 2 program must communicate - at least in one direction. Maybe which ever program was first to write to a common file, the sequence generated, the next could inspect and insure the sequence it makes is different.

// pseudo coden = 1;repeat {  srand(time()^n^pid());  n++;  generate_random_number_sequence();  attempt exclusive r/w access to shared file.  if (file opened) {    read file;    if (different sequence) {      write new sequence and fclose()      if (no I/O errors) {        we are done - exit      }    }    fclose()  }  maybe sleep for a fraction of a second  maybe quit if repeated too often}


Use /dev/random or /dev/urandom to get your seeds. The kernel will ensure that these are generated appropriately, usually by mixing physical entropy with a PRNG.

#include <fcntl.h>#include <unistd.h>#include <stdlib.h>// Seed the random number generator.void seed_rng(void){    int fp = open("/dev/random", O_RDONLY);    if (fp == -1) abort();    unsigned seed;    unsigned pos = 0;    while (pos < sizeof(seed)) {        int amt = read(fp, (char *) &seed + pos, sizeof(seed) - pos);        if (amt <= 0) abort();        pos += amt;    }    srand(seed);    close(fp);}

This code is a bit clumsy, because /dev/random can block. But it is a great way to seed your RNGs.

These requirements are a bit weird, because it's difficult to imagine a situation where using rand() is okay but seeding with the timestamp is not okay. The standard RNG is usually mediocre but simple and fast, and if you wanted something more sophisticated, you'd probably want to ditch rand() first.


First of all, read chux's answer carefully.

Done that? good.If it's ok to assume that the programs will run on the same computer you can just use the PID, and that will guarantee that no two programs running at the same time started with the same seed.

The downside of this "guarantee" is that you'll typically end up using only a subset of available seeds (srand() takes an uint, which is usually 32 bits wide, while a pid is almost always smaller: eg on my system it's limited to 32k); you can work around it by setting the low bits to the pid and the high bits to something else, eg

srand(getpid() + (time(0) << (CHAR_BIT * sizeof(pid_t))))