Question

I'm using srandom() and random() to generate random numbers in c on a Unix system. I would like to have multiple RNGs. Each one, given the same seed, should output the same sequence. I would also like to save and restore the state of each one. Here's a pseudocode example:

R1 = new_rng(5); //5 is the seed
R2 = new rng(5); //5 is the seed here, too.
a = R1.random();
b = R1.random();
d = R2.random(); //a == d
s1 = R2.get_state(); //save the state of R2
e = R2.random(); //b == e
R2.set_state(s1); //restore the state of R2
f = R2.random(); //b == f

How do I do this? Sometimes the RNGs will fork into different threads and I need to replicate the state of the RNG when creating a new thread, too.

Was it helpful?

Solution

Use erand48()/nrand48()/jrand48() to generate double precision floating point, non-negative long integer, or signed long integer random numbers, respectively. These functions allow you to have as many independent sequences as desired; the state is passed in as an argument and can easily be saved and restored. Furthermore, the sequence is defined by the standard and will not vary across runs, even on different platforms.

Some other answers suggest rand_r(). This function is obsolescent in POSIX.1-2008, which contains this note:

The drand48() function provides a much more elaborate random number generator.

The limitations on the amount of state that can be carried between one function call and another mean the rand_r() function can never be implemented in a way which satisfies all of the requirements on a pseudo-random number generator. Therefore this function should be avoided whenever non-trivial requirements (including safety) have to be fulfilled.

The rand_r() function may be removed in a future version.

OTHER TIPS

Read this article on Mersenne twister. There are links to several implementations at the very bottom. (In other words, implement a PRNG yourself.)

there are some C library extension on various UNIX flavours:

  • BSD like random, check initstate/setstate
  • _r variants (random_r, srandom_r, initstate_r, etc)
  • rand_r (stdlib.h)

which flavour is supported by your target UNIX?

Use rand_r(unsigned *seed) instead of srand() and rand(). That way you can maintain multiple random seeds.

I'm not sure you can rely on your PRNG to produce the exact same sequence given an identical seed actually. I know that some methods work that way, but I believe that some of the better ones include a certain amount of non-determinism, so that an identical seed may lead to a different sequence. You'll have to go through your libc documentation with a fine-toothed comb and see if this is mentioned somewhere. If not, check the code (if you're so lucky to have access to the code).

At any rate, this will couple your application very tightly indeed to the PRNG implementation in your libc. You'll definitely be bound to the flavour of libc you're developing on, and maybe even libc version. If this feature is very important, you may have to reimplement random number generation in your app to ensure portability and reproducability.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top