# Random range

**URL:** <https://rubytalk.org/t/random-range/10446>\
**Category:** ruby-talk\
**Created:** [6 March 2004 13:44 UTC](https://rubytalk.org/t/random-range/10446 "2004-03-06T13:44:47Z")\
**Posts on this page:** 3\
**Page:** 2

<div class="post-metadata">

**Author:** ![Mark\_Hubbart](https://avatars.discourse-cdn.com/v4/letter/m/b77776/32.png) [@Mark\_Hubbart](https://rubytalk.org/u/Mark_Hubbart)\
**Post date:** [7 March 2004 19:03 UTC](https://rubytalk.org/t/random-range/10446/21 "2004-03-07T19:03:22Z")

</div>

> > > No Enumerable#size. Try:
> > > 
> > > module Enumerable
> > > 
> > > ## Return a random element, or nil if empty.
> > > 
> > > def rand  
> > > i = 1  
> > > ret = nil  
> > > each do |el|  
> > > if Kernel.rand(i) == 0  
> > > ret = el  
> > > end  
> > > i += 1  
> > > end  
> > > return ret  
> > > end  
> > > end
> > 
> > Umm I don’t think that is a uniform distribution, not to mention the
> 
> It _is_ uniform…
> 
> > fact that you don’t break out of the each if it succeeds.
> 
> … precisely because he doesn’t break out of the each if it succeeds.
> 
> S(i): element i is taken in ret = el (i.e. Kernel.rand(i) == 0)  
> AND: intersection  
> PI: big PI (product)  
> N: number of elements in the Enumerable (if infinite, rand would never  
> return)
> 
> # P(ret == el(i) at the end) = P(S(i) AND (for all N \>= j \> i NOT S(j))) == { they’re independent if we ignore the fact that this is a PRNG } == = P(S(i)) \* P(for all j \> i NOT (S(j))) == { S(j) and S(j+1) indep. }
> 
> = 1/i \* PI(1-P(S(j)), j = i+1 … N) =  
> = 1/i \* (1-1/(i+1)) \* (1-1/(i+2)) \* … \* (1-1/(N)) =  
> = 1/i \* i/(i+1) \* (i+1)/(i+2) \* … \* (N-1)/N =  
> = 1/i \* i / N = 1 / N

or, for those who (like me) have no idea what the above means:

```
>> 10000.times{b[a.rand]+=1}

```

=\> 10000  
\>\> 10000.times{b[a.rand]+=1}  
=\> 10000  
\>\> b  
=\> [2055, 1959, 1934, 2002, 1983, 1931, 2005, 2050, 2057, 2024]

looks good to me!

–Mark

> **···**
>
> On Mar 7, 2004, at 3:51 AM, Mauricio Fernández wrote:
> 
> > On Sun, Mar 07, 2004 at 04:49:39PM +0900, Charles Comstock wrote:
> 
> > –  
> > Running Debian GNU/Linux Sid (unstable)  
> > batsman dot geo at yahoo dot com
> > 
> > Netscape is not a newsreader, and probably never shall be.  
> > – Tom Christiansen

---

<div class="post-metadata">

**Author:** ![Gltewalt](https://avatars.discourse-cdn.com/v4/letter/g/c89c15/32.png) [@Gltewalt](https://rubytalk.org/u/Gltewalt)\
**Post date:** [7 March 2004 13:54 UTC](https://rubytalk.org/t/random-range/10446/22 "2004-03-07T13:54:41Z")

</div>

Mark Hubbart [discord@mac.com](mailto:discord@mac.com) wrote in message news:[B80C2894-6FCA-11D8-B2B9-000502FDD5CC@mac.com](mailto:B80C2894-6FCA-11D8-B2B9-000502FDD5CC@mac.com)…

> > > It’s not redefining rand to take more varied arguments that’s a bad  
> > > thing, it’s defining it for Array#rand that’s a Bad Idea™, IMHO.  
> > > Kernel is included in Object so that you can access it’s methods  
> > > easily  
> > > within other objects. Redefining it in a subclass could potentially  
> > > break lots of code. For example, I often do this:
> > > 
> > > class Array  
> > > def randomize()  
> > > sort{rand(2)-0.5}  
> > > end  
> > > end
> > > 
> > > … and defining an Array#rand would break this.
> > 
> > You must not be very fond of IO#gets, Thread#exit, Dir::open, or  
> > Proc#binding 🙂 Which is to say – there are cases where Kernel  
> > methods we use without a receiver do get redefined for specialized  
> > purposes.
> 
> point taken 🙂 Still, with IO#gets and Thread#exit (I admit I haven’t  
> used the others), the kernel methods were redefined so that they would  
> make more sense in the context. My beef with Array#rand is that it  
> redefines it to do something very _different_ from what the Kernel  
> method does. Kernel.rand _generates_ a random number within parameters,  
> the proposed Array.rand would _select_ a random element from a list.  
> Maybe it’s only a distinction I make in my head 🙂
> 
> > However, while it’s moot anyway because of my fatal  
> > Enumerable#size flaw, my snippet was really just to show the behavior  
> > we were discussing on IRC.
> 
> Just because it can’t be added to Enumerable, doesn’t mean it should be  
> nixed. I would certainly still want it in Array, personally. I just  
> think it should have a different name. 🙂
> 
> > No endorsement of reckless endangerment of  
> > Kernel intended 🙂
> 
> 🙂
> 
> BTW, the reason I’m fairly strong against Array#rand is because I added  
> that exact method into my personal “utils” library a while back, and  
> suddenly a lot of my scripts started failing. It took me a while to  
> figure out where the problem was. 🙂
> 
> –Mark

First off let me apologise if I double post.  
My Browser crashed on the first attempt and I dont  
remember if I hit submit or not.

What about…  
Or, what would the dangers be with,

class Range  
def random  
r = self.to\_a  
r[rand(r.size)]  
end  
end

(5…10).random

class Array  
def random  
self[rand(size)]  
end  
end

[2,4,6,8].random

Or, I guess they could be named: a\_rand, r\_rand

> **···**
>
> > On Mar 6, 2004, at 1:17 PM, David A. Black wrote:
> > 
> > > On Sun, 7 Mar 2004, Mark Hubbart wrote:

---

<div class="post-metadata">

**Author:** ![Charles\_Comstock](https://avatars.discourse-cdn.com/v4/letter/c/91b2a8/32.png) [@Charles\_Comstock](https://rubytalk.org/u/Charles_Comstock)\
**Post date:** [7 March 2004 19:24 UTC](https://rubytalk.org/t/random-range/10446/23 "2004-03-07T19:24:45Z")

</div>

> What about this…  
> Or, what would the dangers be?
> 
> class Range  
> def random  
> r = self.to\_a  
> r[rand(r.size)]  
> end  
> end
> 
> (5..10).random

yes but what happens when someone says  
(1..1000000000).random  
or how about even worse  
(1.1 .. 2.56).random #\<-- this definitely breaks it (infinite set)

For integers the best thing for Range would be  
class Range  
def pick  
lower + rand(upper)  
end  
end

# i’m pretty sure the range is wrong on that but the idea is there

But obviously that doesn’t work for anything else. The main problem  
with pick/random over a range is without doing a to\_a we actually don’t  
know what the size of the range is, which is potentially pretty bad.  
Not to mention when it’s over a floating range where you get infinite  
numbers in between technically.

So I think what that means is we can add pick to array and hash, as well  
as pick!, but not to enumerable. For the rand, I still think we should  
modify it to take a numeric range. Other then that I don’t think we can  
generalize it.

Charles Comstock

[Previous page](https://rubytalk.org/t/random-range/10446.md?page=1)
