Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

For an assignment, I am supposed to ensure that, even when I execute a program within the same second, I should return different numbers. However, I've read other posts and can't quite figure out how to do so specifically within the same second. If I run the code:

int main()
{    
    srand(time(NULL));

    for(count = 0; count < 10; count++)
    {
        printf("%d\n", rand()%20 + 1);
    }

    return 0;
}

I end up with the same result when executed within the same second. Does anyone know how to mix the results within the same second? I'm operating in a Unix environment if that makes a difference. Thanks.

like image 330
homersimpson Avatar asked Dec 20 '22 18:12

homersimpson


2 Answers

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 code
n = 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
}
like image 129
chux - Reinstate Monica Avatar answered Dec 22 '22 06:12

chux - Reinstate Monica


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))))
like image 38
loreb Avatar answered Dec 22 '22 07:12

loreb