Morton Goldberg
7/27/2006 5:03:00 AM
I had similar thoughts a while back. I decided that extending Kernel
and mimicing the behavior of rand was the way to go. My code follows:
Regards, Morton
------ code starts
#!/usr/bin/ruby
# Extend Kernel with an enhanced uniform random number generator.
# Has the same behavior as rand for a single argument.
module Kernel
URAND_ARG_ERR = "Arguments not valid for urand"
# Return a pseudo-random number in the range 0.0...1.0, 0...m, or
m..n.
def urand(m=0, n=nil)
case m
when Range
m, n = m.begin, m.end
when Integer
return rand(m) if n.nil?
else
raise ArgumentError, URAND_ARG_ERR
end
raise ArgumentError, URAND_ARG_ERR if n < m
m + rand(n - m + 1)
end
end
# Now for a little testing ...
def test(times, m=0, n=nil)
r = Array.new(times)
if n.nil? then
if m == 0 then r.collect! {urand}
else r.collect! {urand(m)}
end
else r.collect! {urand(m, n)}
end
p r
end
test(3) # => [0.0403243284672499, 0.875487065408379,
0.142408860381693]
test(3, 11, 11) # => [11, 11, 11]
test(10, 3) # => [0, 1, 2, 0, 1, 0, 1, 2, 0, 0]
test(10, -1..1) # => [0, 0, 1, -1, -1, 1, -1, 1, -1, 0]
test(10, 100, 200) # => [126, 148, 183, 140, 188, 175, 115, 157, 136,
179]
begin
test(1, 3, -1)
rescue ArgumentError => error
puts error.message
end # => Arguments not valid for urand
------ code ends
On Jul 26, 2006, at 8:50 PM, Schüle Daniel wrote:
> one solution could be
>
> irb(main):210:0* class Range
> irb(main):211:1> def rand
> irb(main):212:2> return self.begin + Kernel.rand(self.end-self.begin)
> irb(main):213:2> end
> irb(main):214:1> end
> => nil
> irb(main):215:0> (-10..10).rand
> => 2
> irb(main):216:0> (-10..10).rand
> => 6
> irb(main):217:0> (-10..10).rand
> => 4
> irb(main):218:0> (-10..10).rand
> => -1
>
> it's a matter of style to write
>
> rand(-10..10) or (-10..10).rand
>
> but since 10.sin doesn't work, as opposite tosin(10)
> non object oriented rand(-10..10) is also a nice thing to have.