Как сгенерировать случайное число между a и b в Ruby?


190

Например, чтобы сгенерировать случайное число от 3 до 10, я использую: rand(8) + 3

Есть ли способ сделать это лучше (что-то вроде rand(3, 10))?


4
def my_rand(x, y); rand(y - x) + x; end
Тео

@ Тео y - x + 1, кстати.
Nakilon

1
Попробуйте ваш правильный ответ на 10 и 10 ** 24 в качестве пределов: 0 будет очень-очень долго ждать :)
Саян Малакшинов

5
Это работает:rand(3..10)
eikes

Ответы:


325

ОБНОВЛЕНИЕ: Ruby 1.9.3 Kernel#randтакже принимает диапазоны

rand(a..b)

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

Преобразование в массив может быть слишком дорогим и ненужным.


(a..b).to_a.sample

Или

[*a..b].sample

Массив # образец

Стандарт в Ruby 1.8.7+.
Примечание: в 1.8.7 был назван #choice, а в более поздних версиях был переименован.

Но в любом случае для создания массива требуются ресурсы, и решение, которое вы уже написали, является лучшим, что вы можете сделать.


Благодарность! Думаю, я останусь с старым и хорошим методом :)
Миша Морошко

32
Это действительно плохая идея, особенно если ваши a и b неизвестного размера. Попробуйте (100000000000000000..100000000000000) .to_a.sample и посмотрите, что я имею в виду
:)

4
@pixelearth, если у вас есть лучшее представление о том, что соответствует вопросу, вы можете оставить сообщение.
Nakilon

rand(a..b)не работает, она распадается: TypeError: can't convert Range into Integer. Это даже не поддерживается в Ruby 2.0
fguillen

2
@fguillen У меня работает в 1.9.3, я не знаю, почему у вас не работает.
Майкл Дорст

87
Random.new.rand(a..b) 

Где aваша самая низкая ценность и bваша самая высокая ценность.


4
Следует отметить важное различие: если вы просто звоните, rand()вы звоните Kernel#rand, что поддерживает только maxаргумент. Если вы хотите передать диапазон, вы должны использовать Random#rand, что означает, что вы должны реализовать этот способ. +1
grumpit

2
следует добавить, что вышесказанное относится к 1.9.2
grumpit

он включает a и b?
Abhradip


11

Обратите внимание на разницу между операторами диапазона:

3..10  # includes 10
3...10 # doesn't include 10

3

Смотрите этот ответ: есть в Ruby 1.9.2, но нет в более ранних версиях. Лично я думаю, что rand (8) + 3 в порядке, но если вам интересно, посмотрите класс Random, описанный в ссылке.




2

А вот быстрый тест для #sampleи #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)

Итак, делать rand(a..b)это правильно

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.