1

Suppose I call srand(1234), then call rand() repeatedly. Am I guaranteed to get the same sequence of random numbers regardless of my environment?

For instance,

  • Ruby 1.8.7 vs 1.9.3 vs 2.0
  • MRI vs JRuby
  • Windows vs Mac vs Linux
Chowlett
  • 45,935
  • 20
  • 116
  • 150

2 Answers2

4

The answer in my experience is "yes"

I do this exact same thing when testing a new gem. The gem is not ready for real-world use, but relies heavily on random numbers, and most of the tests involve running Ruby's srand() beforehand so I get predictable numbers for assertions. All in all I probably test a few hundred small integers generated by rand() every time I run the test suite.

So far I have tested:

On Windows: MRI 1.9.3

On Mac: MRI 1.8.7, MRI 1.9.3 and MRI 2.0.0

On Travis (see build https://travis-ci.org/neilslater/games_dice), I test all these:

  • "1.8.7"
  • "1.9.3"
  • "2.0.0"
  • jruby-18mode # JRuby in 1.8 mode
  • jruby-19mode # JRuby in 1.9 mode
  • rbx-18mode
  • rbx-19mode

The last two of which I don't even know what they are :-)

The test suite has never failed due to an unexpected number from Ruby's rand method.

The underlying mechanism in Ruby is called the Mersenne Twister http://en.wikipedia.org/wiki/Mersenne_twister and this will generate same values from the same seeds, even across different languages, where it has been implemented. As far as I know, this algorithm is the one used by Ruby's rand() (and srand()) in all the standard implementations.

Neil Slater
  • 26,512
  • 6
  • 76
  • 94
  • Thanks for the additional datapoints. If you could add the bit about them all using the well-defined Mersenne Twister, then I'll Accept this answer too. – Chowlett Apr 12 '13 at 15:49
  • 1
    Interesting data point; while the above appears to be true of `rand`, it is _not_ true of `Array#sample`. Simply run `srand(42); a = (1.100).to_a; a.sample` in Ruby 1.9.3 and 2.0.0; 1.9.3 produces `38` while 2.0.0 gives `52`. This appears to due to C-source differences in `rb_ary_sample`. This matters to me, which suggests I need to use `my_array[rand(my_array.length)]`, which is a minor pain. – Chowlett Apr 23 '13 at 10:41
2

Well, this is what I get inside my irb - does it match what you get in yours? If so, then I think you can safely say "yes".

BTW, this is the whole point of seeding, so I expect the answer will definitely be "yes", and if not I'll be surprised.

ruby 1.9.3p327 (2012-11-10) [x86_64-darwin12.2.0]

irb(main):001:0> srand(1234)
=> 312936473923896776645464224839555650313
irb(main):002:0> rand
=> 0.1915194503788923
irb(main):003:0> rand
=> 0.6221087710398319
irb(main):004:0> rand
=> 0.4377277390071145
irb(main):006:0> rand
=> 0.7853585837137692
irb(main):007:0> rand
=> 0.7799758081188035
jefflunt
  • 33,527
  • 7
  • 88
  • 126
  • Is seeding really supposed to guarantee the same results across different platforms / versions? I wouldn't say so. IMHO, seeding is just something that is necessary, because the generated numbers are not truly random. – Daniel Hilgarth Apr 12 '13 at 14:55
  • That does match, which is encouraging as you say. Assuming you aren't also `ruby 1.9.3p392 (2013-02-22) [i386-mingw32]`. Is it guaranteed, though? It might be arguable that the seed is just to produce reproducible randomness on one environment. – Chowlett Apr 12 '13 at 14:57
  • @DanielHilgarth - that's certainly part of it, but seeding can also be used to "replay" the same sequence of random numbers over and over. This was used in minesweeper (the old Windows game) where you could entere a game number on any Windows machine and it would use that to generate a random board. The board layout is identical across all minesweeper instances, and it wasn't because minesweeper had a copy of every possible board distributed with it - they were generated on the fly, as I understand it. – jefflunt Apr 12 '13 at 15:00
  • If the concern is about "truly randomness" then it's better to use something like SecureRandom (http://www.ruby-doc.org/stdlib-1.9.3/libdoc/securerandom/rdoc/SecureRandom.html) which will stand up to the security needs of, for example, cryptography. – jefflunt Apr 12 '13 at 15:02
  • Also the documentation of srand states it as so: **"...srand may be used to ensure repeatable sequences of pseudo-random numbers between different runs of the program. By setting the seed to a known value, programs can be made deterministic during testing."** This is not to be confused with two sequences being the same between two **different** Ruby versions (1.8 vs. 1.9 vs. 2.0) or between two different languages (Ruby vs. Java vs. C), but the same version of Ruby on Windows vs. Linux vs. Mac OS with the same seed should replay the same set of random numbers on each platform. – jefflunt Apr 12 '13 at 15:04
  • @normalocity: MineSweeper is a nice anecdote, but the question was if it is guaranteed or should be guaranteed to be the same. Clearly, as long as the same algorithm is used, the result will be the same. However, is there any guarantee that the algorithm is the same between versions and platforms? In other words: Is it part of the contract that using the same seed will generate the same sequence *independent of the platform or version*? I don't think so. – Daniel Hilgarth Apr 12 '13 at 15:06
  • @DanielHilgarth I think my last comment covers that situation. It's not guaranteed necessarily between versions or languages, but the same version should generate the same output across platforms. This is a necessary trait not unique to the srand method - a language on multiple platforms must provide the identical output for identical input, otherwise it's a bug. – jefflunt Apr 12 '13 at 15:07
  • @normalocity: I think your previous comment proofs my point. The contract only talks about different runs of the program. – Daniel Hilgarth Apr 12 '13 at 15:07
  • Ok, but unless specifically stated, ALL methods in ALL languages MUST return identical output for indentical input across the platforms in which they run, otherwise it's a flaw in the documentation or a bug in one or more of the implementations. If this wasn't the case cross platform development would be nearly impossible because no one would be able to rely on the output. Platform-specific differences should always be noted as such. – jefflunt Apr 12 '13 at 15:10
  • @normalocity - what _is_ your platform, for completeness? – Chowlett Apr 12 '13 at 15:10
  • @Chowlett - added my ruby version to the sample output – jefflunt Apr 12 '13 at 15:13
  • @normalocity: I have written a dice emulator gem, which uses srand to fix test results. Tests pass on many versions of Ruby, including JRuby 1.8, MRI 2.0.0 etc. The underlying mechanism in Ruby is http://en.wikipedia.org/wiki/Mersenne_twister and this will generate same values from same seeds, even across different languages, where it has been implemented. – Neil Slater Apr 12 '13 at 15:34