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?

Gareth
  • 133,157
  • 36
  • 148
  • 157
  • What do you mean 'repeat randomness'? If something is random, by definition it shouldn't be repeatable. Perhaps explain what you're actually trying to accomplish (the purpose for your calls to rand, for example). – Brett Bender Oct 29 '10 at 16:40
  • He wants to put all of the state of a PRNG inside a single object so that no other threads (or behind-the-scenes processes) can steal random numbers and upset the sequence. – Ken Bloom Oct 29 '10 at 16:56
  • 2
    @Brett: having a repeatable sequence of pseudorandom numbers can frequently be important for performing simulations (and for debugging those simulations). – Ken Bloom Oct 29 '10 at 16:57
  • I mean I want to present things in a randomised order to different people, but I want each person to see the items in the same order each time. Ideally I want to do this without saving the entire list randomised for every person – Gareth Oct 29 '10 at 16:58

6 Answers6

2

(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
  • 79,051
  • 16
  • 138
  • 171
1

(in ruby 1.9.3) there is a simplier solution ussing Random.

You need to use r = Random.new(seed) to get an object that you can use to generate randomness calling r.rand. this is repeateble, and will only affect calls to r.rand not Kernel.rand.

eloyesp
  • 3,135
  • 1
  • 32
  • 47
1

Use the simple-random gem.

Ken Bloom
  • 57,498
  • 14
  • 111
  • 168
0

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
  • 854,327
  • 234
  • 1,573
  • 1,953
0

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.

the Tin Man
  • 158,662
  • 42
  • 215
  • 303
  • 1
    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 Oct 30 '10 at 00:10
-1

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

Ken Bloom
  • 57,498
  • 14
  • 111
  • 168