[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Re: rand random. You've got to be kidding

Jacob Fugal

11/28/2006 6:08:00 PM

On 11/28/06, Smgspices@aol.com <Smgspices@aol.com> wrote:
> Surely it must be possible to initialize rand with current date and
> time. Documents seem to indicate this is done with rand(0) or srand
> with no value. I have tried both methods and I get the same tired old
> sequence of numbers. I would write my own random number generator
> except I don't know how to get a numeric value out of Time.

I'm not sure which documents you're reading. These are the ri docs I
see (examples elided for brevity):

------------------------------------------------------------ Kernel#rand
rand(max=0) => number
------------------------------------------------------------------------
Converts _max_ to an integer using max1 = max+.to_i.abs+. If the
result is zero, returns a pseudorandom floating point number
greater than or equal to 0.0 and less than 1.0. Otherwise, returns
a pseudorandom integer greater than or equal to zero and less than
max1. +Kernel::srand+ may be used to ensure repeatable sequences of
random numbers between different runs of the program. Ruby
currently uses a modified Mersenne Twister with a period of
219937-1.

----------------------------------------------------------- Kernel#srand
srand(number=0) => old_seed
------------------------------------------------------------------------
Seeds the pseudorandom number generator to the value of
_number_.+to_i.abs+. If _number_ is omitted or zero, seeds the
generator using a combination of the time, the process id, and a
sequence number. (This is also the behavior if +Kernel::rand+ is
called without previously calling +srand+, but without the
sequence.) By setting the seed to a known value, scripts can be
made deterministic during testing. The previous seed value is
returned. Also see +Kernel::rand+.

So no, providing an argument to Kernel#rand does not set the seed, it
provides the range. Kernel#srand is used for setting the seed value.
As you indicated, calling Kernel#srand with no argument should reset
the seed to a value based on the current time (+ process id and
sequence number).

However, you should not even need to call Kernel#srand to set the seed
to the current time unless you've already reseeded to something else
first. When the Ruby interpreter starts up Kernel#srand is
(effectively) called with no argument to initialize the RNG.

This can be seen with the following test program:

$ cat rand_test.rb
puts rand
puts rand
puts rand

$ ruby rand_test.rb
0.386885926082005
0.0444309071556157
0.147546420511617

$ ruby rand_test.rb
0.882099491922559
0.984145785659405
0.590537113434846

As you can see, each run of the program got a different set of random
numbers without ever needing to call srand.

To answer you last question, if you ever *do* need an integer
representing the current time, you can use +Time.now.to_f.to_i+.
Time.now gives you the current time as an object, Time#to_f converts
it to the number of milliseconds since the epoch and then Float#to_i
to truncate it down to an integer. You can also do +Time.now.to_i+ but
that's grained to the second instead of milliseconds.

Jacob Fugal