Take the 2-minute tour ×

Whats the fastest way to write a ruby random number generator? Are there academic formulas for this?

I'm doing this, and for 10,000 random numbers it takes about ~4 seconds:

def generate_random_num(count = 1)
  count.times.map do |i|
    # make a setting!
    num = rand(99999)
    num = "0" * (5 - num.to_s.length) + num.to_s
    redo if codes.include?(num)
    codes << num

I'm just trying to generate up to 99999 random numbers, all 5 digits. Any tips?

share|improve this question
You're converting it to a string twice (once to calculate the length, once for the string). That can't help. You could convert it once and then use the length, or the length is easily calculated from the value, or you could add five zeroes anyway and then take the rightmost 5 characters). Also, it's probably quicker to check you've already got this one when it's stil a number, not a string? –  Paul Dec 6 '10 at 18:54
you don't mention anything about the quality of the randomness you want, which implies that you probably don't care. Is there any reason you can't just generate the list of numbers once and save it, so you can reuse it every time? –  Peter Recore Dec 6 '10 at 19:30
add comment

1 Answer

up vote 5 down vote accepted

This gives you 10000 unique numbers (strings) with leading zeroes:

(1..10000).to_a.shuffle!.map{|n| n.to_s.rjust(5,'0')}

Benchmark (using Benchmark.measure):

user       system     total       real
0.020000   0.000000   0.020000 (  0.017471)

I would, however, just use:


Which is faster:

user       system     total       real
0.000000   0.000000   0.000000 (  0.001692)

And add the leading zeroes when you output each value. According to this post Ruby's shuffle use the Fisher-Yates algorithm Saeed mentions.


So to answer your question, you could generate 10000 unique random numbers in the range [0,99999] with the following code:

(0..99999).to_a.shuffle!.slice(0..9999).map{|n| n.to_s.rjust(5, '0')}

With a benchmark of:

user       system     total       real
0.020000   0.000000   0.020000 (  0.026122)
share|improve this answer
Hi, this only works for count=10000, right?. For smaller count, you could get away with just choosing the first count items from this list, but presumably it would be less efficient than the original method. –  Sanjay Manohar Dec 6 '10 at 19:24
Just change 10000 to anything else, e.g. 100 and you will get random numbers between 1 and 100. If you are using the first example with rjust, you would also have to change 5 -> 3. –  Mads Mobæk Dec 6 '10 at 19:51
but what if you want 100 distinct values in the range [0,99999]? The questioner says "up to" 99999 values. In that case, ideally you want to only do the first 100 steps of a Fisher-Yates shuffle, then take the end of the array that's shuffled. –  Steve Jessop Dec 6 '10 at 21:27
@Steve: then you could just slice the first 100 entries of the shuffeled array with (0..99999).to_a.shuffle!.slice(0..99). This will create an array with 100000 elements, but it's still fast to execute (0.020000, 0.000000, 0.020000, 0.013788)) –  Mads Mobæk Dec 6 '10 at 22:53
true, your timings are so much faster than the questioner's that further optimization probably isn't needed in this case. I just thought you might have misunderstood Sanjay's question. –  Steve Jessop Dec 6 '10 at 23:50
add comment

Your Answer


