tags:

views:

83

answers:

5

I know I can "restart" my rand calls by calling srand with a seed, but surely this would affect future calls to rand by other library methods, including cryptographic methods?

How can I repeat my randomness in certain places and still ensure that the rest of my code isn't affected?

A: 

Well, you could implement your own PRNG that didn't use the system version. There's plenty of literature on the subject of how to do this, from the simplest linear congruential to the Mersenne twister.

In fact, since Ruby is open source, you could actually sneak a peek (see random.c) at how it does random numbers and re-implement that using information separate from the system version.

paxdiablo
I've already backported the `Random` class: just `require 'backports'`.
Marc-André Lafortune
A: 

If you're using JRuby, you can just instantiate a java.util.Random.

Ken Bloom
+1  A: 

Use the simple-random gem.

Ken Bloom
+1  A: 

(Ruby 1.9.2) You could serialize a random generator, store it in a file and provide the file with your program.

Create the file:

File.open('random_generator.marshal', 'w'){ |f| Marshal.dump(Random.new, f) }

use the random generator in your program:

f = File.open( 'random_generator.marshal', 'r' )
r = Marshal.load( f )
f.close

10.times{ puts r.rand } #repeatable
steenslag
Available for earlier Ruby versions with `require 'backports'`, although it will be much slower than the native class in 1.9.2.
Marc-André Lafortune
A: 

rand():

...Kernel::srand may be used to ensure repeatable sequences of random numbers between different runs of the program....

srand():

Seeds the pseudorandom number generator to the value of number.to_i.abs. ... By setting the seed to a known value, scripts can be made deterministic during testing....

You can store your seed value, and the number of iterations that the user has made, then at a later time reseed with that value, then loop the number of times they've used it before to step over the previous values, and land on your next value in the sequence. It's the only way I know of to try to recover the sequence. If you are concerned about other routines/threads then grab the original seed and store it before you set srand with yours, get your next number, then restore the original seed.

If you are concerned about affecting the randomness about other routines that rely on it, I think the authors of those routines should have done something to ensure they were dealing with a truly random seed. You really can only concern yourself about your code and not killing the system. Beyond that the responsibility becomes theirs.

Greg
Well this is exactly my point (I mentioned both of these in the question). After I've called `srand` with my seed, any future `rand` calls (whether I make them, or another library function) are also going to be predictable - I lose my randomness after I call srand with a predictable, repeatable seed.
Gareth