Як генерувати випадкове число між a і b в Ruby?


189

Наприклад, щоб генерувати випадкове число між 3 і 10, я використовую: rand(8) + 3

Чи є кращий спосіб зробити це (щось на зразок rand(3, 10))?


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

@Theo, y - x + 1до речі.
Накілон

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

5
Це працює:rand(3..10)
eikes

Відповіді:


324

ОНОВЛЕННЯ: 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+.
Примітка: був названий #choice в 1.8.7 та перейменований у більш пізні версії.

Але все одно, для створення масиву потрібні ресурси, і рішення, про яке ви вже писали, - найкраще, що ви можете зробити.


Дякую! Думаю, я залишатимусь із старим і хорошим методом :)
Міша Морошко

32
Це дійсно погана ідея, особливо якщо ваші a і b мають невідомі розміри. Спробуйте (100000000000000000..100000000000000) .to_a.sample і подивіться, що я маю на увазі
:)

4
@pixelearth, якщо у вас є краща ідея, яка відповідає питанню, ви можете залишити повідомлення.
Накілон

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?
Абградіп


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.