825

How do I generate a random number between 0 and n?

techdreams
  • 5,371
  • 7
  • 42
  • 63
Mark A. Nicolosi
  • 82,413
  • 11
  • 44
  • 46
  • 1
    Using `srand ` before writing `rand` code will give you a deterministic (i.e. repeatable) pseudo-random sequence, if you need that. https://ruby-doc.org/core-2.5.6/Random.html#method-c-srand – Purplejacket Feb 20 '20 at 23:29

18 Answers18

990

Use rand(range)

From Ruby Random Numbers:

If you needed a random integer to simulate a roll of a six-sided die, you'd use: 1 + rand(6). A roll in craps could be simulated with 2 + rand(6) + rand(6).

Finally, if you just need a random float, just call rand with no arguments.


As Marc-André Lafortune mentions in his answer below (go upvote it), Ruby 1.9.2 has its own Random class (that Marc-André himself helped to debug, hence the 1.9.2 target for that feature).

For instance, in this game where you need to guess 10 numbers, you can initialize them with:

10.times.map{ 20 + Random.rand(11) } 
#=> [26, 26, 22, 20, 30, 26, 23, 23, 25, 22]

Note:

This is why the equivalent of Random.new.rand(20..30) would be 20 + Random.rand(11), since Random.rand(int) returns “a random integer greater than or equal to zero and less than the argument.” 20..30 includes 30, I need to come up with a random number between 0 and 11, excluding 11.

thumbtackthief
  • 6,093
  • 10
  • 41
  • 87
VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250
  • 2
    Isn't this terribly non-ruby-like? I thought everything is an object, least-surprise and that... – Dan Rosenstark Jan 26 '10 at 18:50
  • 1
    @yar: It is a bit "perlish". Now Ruby has it's Random class (see my answer) – Marc-André Lafortune May 05 '10 at 14:02
  • `Random.rand` does not accept a range, and so this code does not work: `Random.rand(20..30)`, I am running on 1.9.2p180. – horseyguy Jun 27 '11 at 07:47
  • also the top-level `rand` method does not accept a range! how the heck did you get 74 points when your code is totally broken?! – horseyguy Jun 27 '11 at 07:59
  • @banister: that is strange, according to the current implementation, it (i.e: `Random.rand`) should support Range: http://redmine.ruby-lang.org/projects/ruby-19/repository/entry/random.c#L1124 – VonC Jun 27 '11 at 08:04
  • @VonC, im pretty sure that's the docs for the Random#rand _instance\_method_ you're looking at there ;). For some reason the Random.rand class method behaves differently to the Random#rand instance method in this case – horseyguy Jun 27 '11 at 09:38
  • @banister: very good point (that '`static`' there through me off). I have edited the answer to reflect your remark. To answer your other question "how the heck did you get 74 points when your code is totally broken?!", it is because up until less than a month ago, this answer contained "`Random.new.rand(20..30)`, ie *instance* method `rand` ;) The recent edit in [Marc-André's answer](http://stackoverflow.com/questions/198460/how-to-get-a-random-number-in-ruby/2773866#2773866) prompted me to update (a bit too quickly) that code in order to use the class method. – VonC Jun 27 '11 at 10:54
  • 2
    @VonC ah :) sorry if i was a bit harsh, it just surprised me – horseyguy Jun 27 '11 at 11:10
  • 1
    `Random.rand` *does* accept a range, actually. (Since 1.9.3, I believe.) – Ajedi32 Jan 02 '15 at 19:56
  • Link to game guessing 10 numbers is gone. – digitalextremist Jul 31 '15 at 12:44
  • 1
    @DanRosenstark: 8 years later... `method(:rand)` outputs `#`. So `rand` is a `Kernel` method, available to every `Object`. You can call `self.send(:rand, 0..10)` if it makes you feel better. – Eric Duminil Mar 12 '18 at 10:15
606

While you can use rand(42-10) + 10 to get a random number between 10 and 42 (where 10 is inclusive and 42 exclusive), there's a better way since Ruby 1.9.3, where you are able to call:

rand(10...42) # => 13

Available for all versions of Ruby by requiring my backports gem.

Ruby 1.9.2 also introduced the Random class so you can create your own random number generator objects and has a nice API:

r = Random.new
r.rand(10...42) # => 22
r.bytes(3) # => "rnd"

The Random class itself acts as a random generator, so you call directly:

Random.rand(10...42) # => same as rand(10...42)

Notes on Random.new

In most cases, the simplest is to use rand or Random.rand. Creating a new random generator each time you want a random number is a really bad idea. If you do this, you will get the random properties of the initial seeding algorithm which are atrocious compared to the properties of the random generator itself.

If you use Random.new, you should thus call it as rarely as possible, for example once as MyApp::Random = Random.new and use it everywhere else.

The cases where Random.new is helpful are the following:

  • you are writing a gem and don't want to interfere with the sequence of rand/Random.rand that the main programs might be relying on
  • you want separate reproducible sequences of random numbers (say one per thread)
  • you want to be able to save and resume a reproducible sequence of random numbers (easy as Random objects can marshalled)
Marc-André Lafortune
  • 78,216
  • 16
  • 166
  • 166
  • 1
    Excellent! +1. I have completed my own answer to reflect that new feature (and mentioning your contribution with Bug #3104 ;) ). – VonC May 05 '10 at 14:20
  • 1
    @yar: My `backports` gem is simply a collection of methods that are new to RUby 1.8.7, 1.9.1, 1.9.2, but implemented in Ruby. I use RubySpec to insure that the results are compatible with Ruby. – Marc-André Lafortune May 05 '10 at 15:16
  • @Marc-André Lafortune, thanks for that. It's always been strange to me how much of Ruby is implemented in non-Ruby (C or whatever) due to speed requirements. But them's the breaks – Dan Rosenstark May 05 '10 at 16:01
  • @yar: Until there is a really good implementation of Ruby, the builtin Random class will perform much better than my compatible Ruby version... It's the goal of Rubinius to minimize the C++ code without a big loss of performance. – Marc-André Lafortune May 05 '10 at 16:35
  • @Marc-André Lafortune, while we're here: is JRuby not a good implementation? I could be totally off-base and you'll say, "no it's the worst of all." – Dan Rosenstark May 05 '10 at 18:00
  • @yar: It is! But the mersenne twister in Ruby will spend most of the time in function calls and very little time doing the basic calculations. By a good implementation, I meant one that could inline those dynamic calls very well (which I don't think the JVM can do). Rubinius aims to do that. I haven't done any performance testing, though, so I'm speculating :-) – Marc-André Lafortune May 05 '10 at 18:30
  • Rubinius, eh? I'll keep my eye on that one, I see it's right in line with what we're talking about. Fascinating in any case... thanks for the chat. – Dan Rosenstark May 05 '10 at 18:36
  • Shorter version would be Random.new.rand(0..100) – Juanda Nov 05 '10 at 23:13
  • @Juanda: Actually my example is in two lines because it's a terrible idea to call `Random.new` all the time. I've edited my answer – Marc-André Lafortune Jun 17 '11 at 17:10
  • 5
    `Random.rand(10..42)` does not work. The `Random.rand` class method does not accept a range. (Ruby 1.9.2p180) – horseyguy Jun 27 '11 at 07:46
  • 1
    @banister: wow, I was convinced that the new api (rand with range, bytes, etc...) was available directly through the Random object. rand with range will be in 1.9.3, and I'll make a feature request for bytes. I've edited my answer – Marc-André Lafortune Jun 27 '11 at 14:20
48

If you're not only seeking for a number but also hex or uuid it's worth mentioning that the SecureRandom module found its way from ActiveSupport to the ruby core in 1.9.2+. So without the need for a full blown framework:

require 'securerandom'

p SecureRandom.random_number(100) #=> 15
p SecureRandom.random_number(100) #=> 88

p SecureRandom.random_number #=> 0.596506046187744
p SecureRandom.random_number #=> 0.350621695741409

p SecureRandom.hex #=> "eb693ec8252cd630102fd0d0fb7c3485"

It's documented here: Ruby 1.9.3 - Module: SecureRandom (lib/securerandom.rb)

bv.
  • 85
  • 6
Thomas Fankhauser
  • 5,039
  • 1
  • 33
  • 32
39

You can generate a random number with the rand method. The argument passed to the rand method should be an integer or a range, and returns a corresponding random number within the range:

rand(9)       # this generates a number between 0 to 8
rand(0 .. 9)  # this generates a number between 0 to 9
rand(1 .. 50) # this generates a number between 1 to 50
#rand(m .. n) # m is the start of the number range, n is the end of number range
MattD
  • 4,220
  • 2
  • 34
  • 44
22

Well, I figured it out. Apparently there is a builtin (?) function called rand:

rand(n + 1)

If someone answers with a more detailed answer, I'll mark that as the correct answer.

Mark A. Nicolosi
  • 82,413
  • 11
  • 44
  • 46
17

What about this?

n = 3
(0..n).to_a.sample
Rimian
  • 36,864
  • 16
  • 117
  • 117
  • 3
    It should be noted that generating an array of numbers like this solution provides has terrible performance on large ranges as it's O(n) while `rand` is O(1). – Travis Feb 23 '17 at 14:01
15

Simplest answer to the question:

rand(0..n)
dgilperez
  • 10,716
  • 8
  • 68
  • 96
sqrcompass
  • 643
  • 1
  • 8
  • 17
11

You can simply use random_number.

If a positive integer is given as n, random_number returns an integer: 0 <= random_number < n.

Use it like this:

any_number = SecureRandom.random_number(100) 

The output will be any number between 0 and 100.

techdreams
  • 5,371
  • 7
  • 42
  • 63
6
rand(6)    #=> gives a random number between 0 and 6 inclusively 
rand(1..6) #=> gives a random number between 1 and 6 inclusively

Note that the range option is only available in newer(1.9+ I believe) versions of ruby.

Josh
  • 5,631
  • 1
  • 28
  • 54
  • I believe the range option is only available in `ruby 1.9.3+`. It didn't work in `1.9.2` when I tried at least. – Batkins Dec 13 '12 at 21:24
6

range = 10..50

rand(range)

or

range.to_a.sample

or

range.to_a.shuffle(this will shuffle whole array and you can pick a random number by first or last or any from this array to pick random one)

sumit
  • 255
  • 3
  • 5
5

you can do rand(range)

x = rand(1..5)
Scott
  • 132
  • 1
  • 10
4

This link is going to be helpful regarding this;

http://ruby-doc.org/core-1.9.3/Random.html

And some more clarity below over the random numbers in ruby;

Generate an integer from 0 to 10

puts (rand() * 10).to_i

Generate a number from 0 to 10 In a more readable way

puts rand(10)

Generate a number from 10 to 15 Including 15

puts rand(10..15)

Non-Random Random Numbers

Generate the same sequence of numbers every time the program is run

srand(5)

Generate 10 random numbers

puts (0..10).map{rand(0..10)}
Sam
  • 1,623
  • 1
  • 19
  • 31
  • Also you can follow this blog for step by step very clear picture over random nos in ruby; http://www.sitepoint.com/tour-random-ruby/ – Sam Dec 24 '13 at 17:40
4

Easy way to get random number in ruby is,

def random    
  (1..10).to_a.sample.to_s
end
Vaisakh VM
  • 1,071
  • 11
  • 9
2

Maybe it help you. I use this in my app

https://github.com/rubyworks/facets
class String

  # Create a random String of given length, using given character set
  #
  # Character set is an Array which can contain Ranges, Arrays, Characters
  #
  # Examples
  #
  #     String.random
  #     => "D9DxFIaqR3dr8Ct1AfmFxHxqGsmA4Oz3"
  #
  #     String.random(10)
  #     => "t8BIna341S"
  #
  #     String.random(10, ['a'..'z'])
  #     => "nstpvixfri"
  #
  #     String.random(10, ['0'..'9'] )
  #     => "0982541042"
  #
  #     String.random(10, ['0'..'9','A'..'F'] )
  #     => "3EBF48AD3D"
  #
  #     BASE64_CHAR_SET =  ["A".."Z", "a".."z", "0".."9", '_', '-']
  #     String.random(10, BASE64_CHAR_SET)
  #     => "xM_1t3qcNn"
  #
  #     SPECIAL_CHARS = ["!", "@", "#", "$", "%", "^", "&", "*", "(", ")", "-", "_", "=", "+", "|", "/", "?", ".", ",", ";", ":", "~", "`", "[", "]", "{", "}", "<", ">"]
  #     BASE91_CHAR_SET =  ["A".."Z", "a".."z", "0".."9", SPECIAL_CHARS]
  #     String.random(10, BASE91_CHAR_SET)
  #      => "S(Z]z,J{v;"
  #
  # CREDIT: Tilo Sloboda
  #
  # SEE: https://gist.github.com/tilo/3ee8d94871d30416feba
  #
  # TODO: Move to random.rb in standard library?

  def self.random(len=32, character_set = ["A".."Z", "a".."z", "0".."9"])
    chars = character_set.map{|x| x.is_a?(Range) ? x.to_a : x }.flatten
    Array.new(len){ chars.sample }.join
  end

end

https://github.com/rubyworks/facets/blob/5569b03b4c6fd25897444a266ffe25872284be2b/lib/core/facets/string/random.rb

It works fine for me

amarradi
  • 109
  • 3
  • 16
2

How about this one?

num = Random.new
num.rand(1..n)
Juan Dela Cruz
  • 221
  • 2
  • 16
1

Don't forget to seed the RNG with srand() first.

Liebach
  • 83
  • 1
1

Try array#shuffle method for randomization

array = (1..10).to_a
array.shuffle.first
lennon310
  • 12,503
  • 11
  • 43
  • 61
LuckyElf
  • 29
  • 2
0

You can use ruby rand method for this like below:

rand(n+1)

You need to use n+1 as the rand method returns any random number greater than or equal to 0 but less than the passed parameter value.

Sachin Singh
  • 993
  • 8
  • 16