201

To generate a random number between 3 and 10, for example, I use: rand(8) + 3

Is there a nicer way to do this (something like rand(3, 10)) ?

Nakilon
  • 33,683
  • 14
  • 104
  • 137
Misha Moroshko
  • 157,453
  • 220
  • 487
  • 722

8 Answers8

346

UPDATE: Ruby 1.9.3 Kernel#rand also accepts ranges

rand(a..b)

http://www.rubyinside.com/ruby-1-9-3-introduction-and-changes-5428.html

Converting to array may be too expensive, and it's unnecessary.


(a..b).to_a.sample

Or

[*a..b].sample

Array#sample

Standard in Ruby 1.8.7+.
Note: was named #choice in 1.8.7 and renamed in later versions.

But anyway, generating array need resources, and solution you already wrote is the best, you can do.

mgarciaisaia
  • 13,156
  • 8
  • 53
  • 77
Nakilon
  • 33,683
  • 14
  • 104
  • 137
  • Thanks! I think I'll stay with the old and the good method :) – Misha Moroshko Dec 09 '10 at 07:12
  • 33
    This is a really bad idea, especially if your a and b are of unknown sizes. Try (100000000000000000..100000000000000).to_a.sample and see what I mean : ) – pixelearth Sep 16 '11 at 22:06
  • 4
    @pixelearth, if you have better idea, which accords the question, you are welcome to post. – Nakilon Sep 17 '11 at 01:54
  • `rand(a..b)` doesn't work, it splits: `TypeError: can't convert Range into Integer`. It's not even supported in [Ruby 2.0](http://ruby-doc.org/core-2.0/Kernel.html#method-i-rand) – fguillen Mar 09 '13 at 16:00
  • 2
    @fguillen It works for me in 1.9.3, I don't know why it's not working for you. – Michael Dorst Dec 18 '13 at 18:35
  • @anthropomorphic it is working for me in `ruby 2.0.0-p247` so I retract. – fguillen Dec 18 '13 at 20:07
  • @so_mv this doesn't happen on MRI. (2.0.0p594). `1000000.times{|i| a = rand(1000..9999); puts a if a < 1000}` does not puts a single number – Pelle Nov 22 '14 at 00:12
  • 1000.times{|i| puts rand(1000-9999)} is wrong. Notice the minus(-) between 1000-9999. It should be 1000..9999. I will remove my comment – so_mv Nov 25 '14 at 08:10
88
Random.new.rand(a..b) 

Where a is your lowest value and b is your highest value.

Simon Perepelitsa
  • 20,010
  • 8
  • 54
  • 73
user1782571
  • 889
  • 6
  • 2
  • 4
    The important difference to note is that if you just call `rand()` you are calling `Kernel#rand`, which only supports a `max` argument. If you want to pass a range, you have to use `Random#rand`, meaning you have to implement this way. +1 – grumpit Jan 17 '13 at 03:06
  • 2
    should add that the above applies to 1.9.2 – grumpit Jan 17 '13 at 03:20
  • does it include a and b ? – Abhradip Oct 24 '16 at 07:39
12
rand(3..10)

Kernel#rand

When max is a Range, rand returns a random number where range.member?(number) == true.

Dorian
  • 20,859
  • 8
  • 116
  • 113
12

Just note the difference between the range operators:

3..10  # includes 10
3...10 # doesn't include 10
Yaniv Preiss
  • 229
  • 2
  • 7
5
def random_int(min, max)
    rand(max - min) + min
end
Chaseph
  • 1,873
  • 3
  • 16
  • 20
3

See this answer: there is in Ruby 1.9.2, but not in earlier versions. Personally I think rand(8) + 3 is fine, but if you're interested check out the Random class described in the link.

Community
  • 1
  • 1
bnaul
  • 16,626
  • 4
  • 29
  • 28
3

For 10 and 10**24

rand(10**24-10)+10
Sayan Malakshinov
  • 7,833
  • 1
  • 16
  • 26
2

And here is a quick benchmark for both #sample and #rand:

irb(main):014:0* Benchmark.bm do |x|
irb(main):015:1*   x.report('sample') { 1_000_000.times { (1..100).to_a.sample } }
irb(main):016:1>   x.report('rand') { 1_000_000.times { rand(1..100) } }
irb(main):017:1> end
       user     system      total        real
sample  3.870000   0.020000   3.890000 (  3.888147)
rand  0.150000   0.000000   0.150000 (  0.153557)

So, doing rand(a..b) is the right thing

Vadym Tyemirov
  • 7,548
  • 3
  • 41
  • 37