Як отримати випадкове число в Ruby


786

Як створити випадкове число між 0і n?


Використання srand <some_number>перед написанням randкоду дасть вам детерміновану (тобто повторювану) псевдовипадкову послідовність, якщо вам це потрібно. ruby-doc.org/core-2.5.6/Random.html#method-c-srand
Purplejacket

Відповіді:


952

Використовуйте rand(range)

Із випадкових чисел Ruby :

Якщо вам потрібно випадкове число , щоб імітувати рулон шестигранного штампа, ви будете використовувати: 1 + rand(6). Рулон у лайнах можна було б імітувати за допомогою 2 + rand(6) + rand(6).

Нарешті, якщо вам просто потрібен випадковий плавець, просто телефонуйте randбез аргументів.


Як згадує Марк-Андре Лафортун у своїй відповіді нижче (перейдіть до нього) , у Рубі 1.9.2 є свій Randomклас (що сам Марк-Андре допоміг налагоджувати , отже, ціль 1.9.2 для цієї функції).

Наприклад, у цій грі, де вам потрібно відгадати 10 чисел , ви можете ініціалізувати їх за допомогою:

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

Примітка:

Ось чому еквівалент Random.new.rand(20..30)буде 20 + Random.rand(11), оскільки Random.rand(int)повертає "випадкове ціле число, що більше або дорівнює нулю і менше аргументу ". 20..30включає 30, мені потрібно придумати випадкове число між 0 і 11, виключаючи 11.


2
Хіба це не страшно не рубіноподібно? Я думав, що все є предметом, щонайменше - несподіванкою і що ...
Ден Розенстарк,

1
@yar: Це трохи "приємно". Тепер у Ruby є клас Random (див. Мою відповідь)
Marc-André Lafortune

3
@VonC: Чудово, що ви відредагували свою відповідь, щоб згадати про новий Randomклас, але це жахлива ідея викликати Random.newкілька разів, як у вашому прикладі. Я відредагував свою відповідь, щоб констатувати це.
Марк-Андре Лафортун

2
@VonC ах :) Вибачте, якщо я трохи суворий, це мене просто здивувало
horseyguy

1
Random.rand насправді приймає діапазон. (З 1.9.3, я вважаю.)
Ajedi32

591

Хоча ви можете використовувати rand(42-10) + 10випадкове число між 10і 42(де 10 включно і 42 ексклюзивні), є кращий спосіб, оскільки Ruby 1.9.3, де ви можете зателефонувати:

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

Доступний для всіх версій Ruby, вимагаючи мого backportsдорогоцінного каменя.

Ruby 1.9.2 також представив Randomклас, щоб ви могли створити власні об'єкти генератора випадкових чисел та мати приємний API:

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

Сам Randomклас виступає генератором випадкових випадків, тому ви телефонуєте безпосередньо:

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

Примітки до Random.new

У більшості випадків найпростішим є використання randабо Random.rand. Створення нового випадкового генератора кожного разу, коли вам потрібно випадкове число, - це дуже погана ідея . Якщо ви зробите це, ви отримаєте випадкові властивості алгоритму початкового висіву, які є суворими порівняно із властивостями самого генератора випадкових випадків .

Якщо ви користуєтесь Random.new, ви повинні називати це якомога рідше , наприклад, один раз MyApp::Random = Random.newі використовувати його скрізь в іншому місці.

Випадки, коли Random.newкорисні такі:

  • ви пишете дорогоцінний камінь і не хочете перешкоджати послідовності rand/ Random.rand, на яку можуть покладатися основні програми
  • потрібно окремі відтворювані послідовності випадкових чисел (скажімо одне на нитку)
  • Ви хочете мати можливість зберегти та відновити відтворювану послідовність випадкових чисел (просто, оскільки Randomоб'єкти можуть бути змінені)

1
Відмінно! +1. Я завершив свою власну відповідь, щоб відобразити цю нову функцію (і згадуючи ваш внесок із Bug # 3104;)).
VonC

1
@yar: Мій backportsдорогоцінний камінь - це просто колекція методів, які є новими для RUby 1.8.7, 1.9.1, 1.9.2, але реалізовані в Ruby. Я використовую RubySpec, щоб гарантувати, що результати сумісні з Ruby.
Марк-Андре Лафортун

@ Marc-André Lafortune, дякую за це. Мені завжди було дивно, скільки Рубі реалізовано в не-Ruby (C чи що завгодно) через вимоги швидкості. Але їх перерви
Ден Розенстарк

5
Random.rand(10..42)не працює. Метод Random.randкласу не приймає діапазон. (Ruby 1.9.2p180)
horseyguy

1
@banister: ух, я переконався, що нові api (rand з діапазоном, байтами тощо) доступні безпосередньо через об'єкт Random. rand з діапазоном буде в 1.9.3, і я зробить запит на функцію для байт. Я відредагував свою відповідь
Marc-André Lafortune

46

Якщо ви шукаєте не тільки номер, а й шістнадцятковий або uuid, варто згадати, що SecureRandomмодуль знайшов шлях ActiveSupportдо ядра рубіна в 1.9.2+. Тож без необхідності повноцінного продукту:

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"

Це задокументовано тут: Ruby 1.9.3 - Модуль: SecureRandom (lib / securerandom.rb)


А як бути, якщо вам потрібно чотиризначне випадкове число?
onurozgurozkan

1
onurozgurozkan Я припускаюSecureRandom.random_number(1000..9999)
JayTarka

1
SecureRandom.random_number()не займає дальність, так що ні. Ви, мабуть, хочете чогось типу SecureRandom.random_number(10_000)(для 0-9999) або SecureRandom.random_number(9_000)+1_000(для 1000-9999).
mwp

1
Random.rand (1000..9999)
Джессі Фермер

37

За допомогою randметоду можна генерувати випадкове число . Аргумент, переданий randметоду, повинен бути a integerабо a 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

Я думаю, що використовувати ваші rand(1..6)читання чіткіше, ніж відповіді вгорі rand(6)+1.
ізоморфізм

21

Ну, я зрозумів це. Мабуть, є вбудована (?) Функція, яка називається rand:

rand(n + 1)

Якщо хтось відповість більш детальною відповіддю, я зазначу це як правильну відповідь.


2
Так, він вбудований в модуль Kernel.
Крістоф Шиссль

17

Як що до цього?

n = 3
(0..n).to_a.sample

3
Слід зазначити, що генерування масиву чисел, як це рішення, забезпечує жахливу ефективність на великих діапазонах, оскільки це O (n), а randO (1).
Тревіс


9

Ви можете просто використовувати random_number.

Якщо додатне ціле число задано як n, random_numberповертає ціле число: 0 <= random_number<n.

Використовуйте його так:

any_number = SecureRandom.random_number(100) 

Вихід буде будь-яким числом від 0 до 100.


6
rand(6)    #=> gives a random number between 0 and 6 inclusively 
rand(1..6) #=> gives a random number between 1 and 6 inclusively

Зауважте, що опція діапазону доступна лише в новіших версіях (1,9+ я вважаю) рубінів.


Я вважаю, що опція діапазону доступна лише в ruby 1.9.3+. Не вийшло, 1.9.2коли я намагався принаймні.
Баткінс

6

діапазон = 10..50

rand (діапазон)

або

range.to_a.sample

або

range.to_a.shuffle (це змістить весь масив, і ви можете вибрати випадкове число за першим чи останнім чи будь-яким із цього масиву, щоб вибрати випадкове)


range.to_a.sampleце жахлива ідея, коли зразок великий.
Гжегож


4

Це посилання стане корисним щодо цього;

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

І ще трохи ясності нижче випадкових чисел у рубіні;

Створіть ціле число від 0 до 10

puts (rand() * 10).to_i

Створіть число від 0 до 10 Більш читабельним способом

puts rand(10)

Утворіть число від 10 до 15, включаючи 15

puts rand(10..15)

Невипадкові випадкові числа

Створюйте однакову послідовність чисел щоразу, коли програма запускається

srand(5)

Утворіть 10 випадкових чисел

puts (0..10).map{rand(0..10)}

Також ви можете слідкувати за цим блогом, за кроком дуже чіткою картиною над випадковими носами в рубіні; sitepoint.com/tour-random-ruby
Сем

4

Простий спосіб отримати випадкове число в рубіні,

def random    
  (1..10).to_a.sample.to_s
end

2

Можливо, це вам допоможе. Я використовую це у своєму додатку

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

Це прекрасно працює для мене



1

Спробуйте array#shuffleметод рандомізації

array = (1..10).to_a
array.shuffle.first

1
Якщо вам потрібно зробити цілий масив, принаймні замініть .shuffle.firstна .sample!
Camille Goudeseune

0

Не забудьте спочатку засіяти РНГ срандом () .


2
Що станеться, якщо ви не зателефонуєте srand ()?
Алекс Б

21
srand автоматично викликається з насінням від поточного часу, якщо він ще не був викликаний.
Julian H
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.