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