# Rand(-10..10)

**URL:** <https://rubytalk.org/t/rand-10-10/29332>\
**Category:** ruby-talk\
**Created:** [27 July 2006 00:40 UTC](https://rubytalk.org/t/rand-10-10/29332 "2006-07-27T00:40:11Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![Daniel\_Schule](https://avatars.discourse-cdn.com/v4/letter/d/958977/32.png) [@Daniel\_Schule](https://rubytalk.org/u/Daniel_Schule)\
**Post date:** [27 July 2006 00:40 UTC](https://rubytalk.org/t/rand-10-10/29332/1 "2006-07-27T00:40:11Z")

</div>

Hi all,

wouldn't it make sense to allow

rand -10..10

be aquivalent to

-10 + rand(20)

the first is by far more obvious.  
Of course rand -10...10 should work too.  
What do you think?

> **···**
>
> --  
> Daniel

---

<div class="post-metadata">

**Author:** ![Daniel\_Schule](https://avatars.discourse-cdn.com/v4/letter/d/958977/32.png) [@Daniel\_Schule](https://rubytalk.org/u/Daniel_Schule)\
**Post date:** [27 July 2006 00:50 UTC](https://rubytalk.org/t/rand-10-10/29332/2 "2006-07-27T00:50:04Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![Morton\_Goldberg](https://avatars.discourse-cdn.com/v4/letter/m/7ea924/32.png) [@Morton\_Goldberg](https://rubytalk.org/u/Morton_Goldberg)\
**Post date:** [27 July 2006 05:02 UTC](https://rubytalk.org/t/rand-10-10/29332/3 "2006-07-27T05:02:48Z")

</div>

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  
&nbsp;&nbsp;&nbsp;&nbsp;URAND\_ARG\_ERR = "Arguments not valid for urand"  
&nbsp;&nbsp;&nbsp;&nbsp;# Return a pseudo-random number in the range 0.0...1.0, 0...m, or m..n.  
&nbsp;&nbsp;&nbsp;&nbsp;def urand(m=0, n=nil)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;case m  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;when Range  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;m, n = m.begin, m.end  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;when Integer  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return rand(m) if n.nil?  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;raise ArgumentError, URAND\_ARG\_ERR  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;raise ArgumentError, URAND\_ARG\_ERR if n \< m  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;m + rand(n - m + 1)  
&nbsp;&nbsp;&nbsp;&nbsp;end  
end

# Now for a little testing ...  
def test(times, m=0, n=nil)  
&nbsp;&nbsp;&nbsp;&nbsp;r = Array.new(times)  
&nbsp;&nbsp;&nbsp;&nbsp;if n.nil? then  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if m == 0 then r.collect! {urand}  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else r.collect! {urand(m)}  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
&nbsp;&nbsp;&nbsp;&nbsp;else r.collect! {urand(m, n)}  
&nbsp;&nbsp;&nbsp;&nbsp;end  
&nbsp;&nbsp;&nbsp;&nbsp;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  
&nbsp;&nbsp;&nbsp;&nbsp;test(1, 3, -1)  
rescue ArgumentError =\> error  
&nbsp;&nbsp;&nbsp;&nbsp;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.

---

<div class="post-metadata">

**Author:** ![Dr\_Nic](https://avatars.discourse-cdn.com/v4/letter/d/bc8723/32.png) [@Dr\_Nic](https://rubytalk.org/u/Dr_Nic)\
**Post date:** [27 July 2006 13:53 UTC](https://rubytalk.org/t/rand-10-10/29332/4 "2006-07-27T13:53:48Z")

</div>

> 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

\*Sniff\* God I love Ruby.

> **···**
>
> --  
> Posted via [http://www.ruby-forum.com/\](http://www.ruby-forum.com/%5C).

---

<div class="post-metadata">

**Author:** ![Marc\_Heiler](https://avatars.discourse-cdn.com/v4/letter/m/e8c25b/32.png) [@Marc\_Heiler](https://rubytalk.org/u/Marc_Heiler)\
**Post date:** [27 July 2006 14:07 UTC](https://rubytalk.org/t/rand-10-10/29332/5 "2006-07-27T14:07:53Z")

</div>

"the first is by far more obvious."

I think it looks ugly. 🙂

(-10..10).rand  
looks much nicer IMHO.

> **···**
>
> --  
> Posted via [http://www.ruby-forum.com/](http://www.ruby-forum.com/).

---

<div class="post-metadata">

**Author:** ![Daniel\_Schierbeck](https://avatars.discourse-cdn.com/v4/letter/d/dfb087/32.png) [@Daniel\_Schierbeck](https://rubytalk.org/u/Daniel_Schierbeck)\
**Post date:** [27 July 2006 15:25 UTC](https://rubytalk.org/t/rand-10-10/29332/6 "2006-07-27T15:25:11Z")

</div>

Marc Heiler wrote:

> "the first is by far more obvious."
> 
> I think it looks ugly. 🙂
> 
> (-10..10).rand  
> looks much nicer IMHO.

This should work with all enumerables:

&nbsp;&nbsp;&nbsp;module Enumerable  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;def rand  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;entries = entries  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;entries.at(Kernel.rand(entries.length))  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
&nbsp;&nbsp;&nbsp;end

I can't seem to get around the `entries = entries' part -- I don't want to convert the enumerable to an array more than once. Any ideas?

Cheers,  
Daniel

---

<div class="post-metadata">

**Author:** ![Chris6](https://avatars.discourse-cdn.com/v4/letter/c/b2d939/32.png) [@Chris6](https://rubytalk.org/u/Chris6)\
**Post date:** [27 July 2006 16:25 UTC](https://rubytalk.org/t/rand-10-10/29332/7 "2006-07-27T16:25:04Z")

</div>

Daniel Schierbeck wrote:  
...

> This should work with all enumerables:
> 
> &nbsp;&nbsp;&nbsp;module Enumerable  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;def rand  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;entries = entries  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;entries.at(Kernel.rand(entries.length))  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
> &nbsp;&nbsp;&nbsp;end
> 
> I can't seem to get around the `entries = entries' part -- I don't want  
> to convert the enumerable to an array more than once. Any ideas?

Enumerable supports sort\_by, so could just use:

module Enumerable  
&nbsp;&nbsp;def rand  
&nbsp;&nbsp;&nbsp;&nbsp;self.sort\_by{Kernel.rand}.last  
&nbsp;&nbsp;end  
end

Cheers  
Chris

---

<div class="post-metadata">

**Author:** ![Daniel\_Schierbeck](https://avatars.discourse-cdn.com/v4/letter/d/dfb087/32.png) [@Daniel\_Schierbeck](https://rubytalk.org/u/Daniel_Schierbeck)\
**Post date:** [27 July 2006 17:45 UTC](https://rubytalk.org/t/rand-10-10/29332/8 "2006-07-27T17:45:06Z")

</div>

ChrisH wrote:

> Daniel Schierbeck wrote:  
> ...
> 
> > This should work with all enumerables:
> > 
> > &nbsp;&nbsp;&nbsp;module Enumerable  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;def rand  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;entries = entries  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;entries.at(Kernel.rand(entries.length))  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
> > &nbsp;&nbsp;&nbsp;end
> > 
> > I can't seem to get around the `entries = entries' part -- I don't want  
> > to convert the enumerable to an array more than once. Any ideas?
> 
> Enumerable supports sort\_by, so could just use:
> 
> module Enumerable  
> &nbsp;&nbsp;def rand  
> &nbsp;&nbsp;&nbsp;&nbsp;self.sort\_by{Kernel.rand}.last  
> &nbsp;&nbsp;end  
> end

I think sorting the entire enumerable may be slight overkill, although it of course is prettier 🙂

Daniel

---

<div class="post-metadata">

**Author:** ![Daniel\_Martin](https://avatars.discourse-cdn.com/v4/letter/d/dc4da7/32.png) [@Daniel\_Martin](https://rubytalk.org/u/Daniel_Martin)\
**Post date:** [27 July 2006 18:45 UTC](https://rubytalk.org/t/rand-10-10/29332/9 "2006-07-27T18:45:46Z")

</div>

Daniel Schierbeck \<daniel.schierbeck@gmail.com\> writes:

> > > This should work with all enumerables:
> > > 
> > > &nbsp;&nbsp;&nbsp;module Enumerable  
> > > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;def rand  
> > > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;entries = entries  
> > > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;entries.at(Kernel.rand(entries.length))  
> > > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
> > > &nbsp;&nbsp;&nbsp;end
> > > 
> > > I can't seem to get around the `entries = entries' part -- I don't want  
> > > to convert the enumerable to an array more than once. Any ideas?

There's also this, which is possibly more memory-efficient (if the  
Enumerable in question chews large amounts of memory when being  
converted to an array, but not with each), but is almost certainly  
much slower, since it calls rand once per element:

module Enumerable  
&nbsp;&nbsp;def rand  
&nbsp;&nbsp;&nbsp;&nbsp;ret, i = nil, 0  
&nbsp;&nbsp;&nbsp;&nbsp;each {|v| ret = v if 0 == Kernel.rand(i += 1)}  
&nbsp;&nbsp;&nbsp;&nbsp;ret  
&nbsp;&nbsp;end  
end

Test code for irb:

h=Hash.new(0); 10000.times {h[%w{a b c d e}.rand] += 1}; h

---

<div class="post-metadata">

**Author:** ![Florian\_Frank2](https://avatars.discourse-cdn.com/v4/letter/f/a587f6/32.png) [@Florian\_Frank2](https://rubytalk.org/u/Florian_Frank2)\
**Post date:** [27 July 2006 19:26 UTC](https://rubytalk.org/t/rand-10-10/29332/10 "2006-07-27T19:26:03Z")

</div>

Daniel Martin wrote:

> module Enumerable  
> &nbsp;&nbsp;def rand  
> &nbsp;&nbsp;&nbsp;&nbsp;ret, i = nil, 0  
> &nbsp;&nbsp;&nbsp;&nbsp;each {|v| ret = v if 0 == Kernel.rand(i += 1)}  
> &nbsp;&nbsp;&nbsp;&nbsp;ret  
> &nbsp;&nbsp;end  
> end
> 
> Test code for irb:
> 
> h=Hash.new(0); 10000.times {h[%w{a b c d e}.rand] += 1}; h  
> &nbsp;&nbsp;

I think you shouldn't name this method rand. It shadows Kernel.rand in all classes, that already call rand and include Enumerable. The same is true for Range#rand, if people inherit from Range and already call rand. Ruby makes those things possible, but it's also very easy to shoot yourself or others into the foot, if you aren't careful.

The Kernel#rand(-5..15) version wouldn't suffer from this problem. It would be a good idea to add this to ruby core, because this functionality is something, that is needed very often.

> **···**
>
> --  
> Florian Frank

---

<div class="post-metadata">

**Author:** ![Daniel\_Schule](https://avatars.discourse-cdn.com/v4/letter/d/958977/32.png) [@Daniel\_Schule](https://rubytalk.org/u/Daniel_Schule)\
**Post date:** [28 July 2006 22:45 UTC](https://rubytalk.org/t/rand-10-10/29332/11 "2006-07-28T22:45:05Z")

</div>

[...]

> The Kernel#rand(-5..15) version wouldn't suffer from this problem. It would be a good idea to add this to ruby core, because this functionality is something, that is needed very often.

yes, this was exactly my point  
if we already had Kernel#rand with Range object, people wouldn't implement their own methods, making scripts shoter and slightly more portable (regarding copy&paste other code)

Regards, Daniel
