Как получить случайное число в Ruby

786

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

Марк А. Николози
источник
Использование srand <some_number>перед написанием randкода даст вам детерминированную (т.е. повторяемую) псевдослучайную последовательность, если вам это нужно. ruby-doc.org/core-2.5.6/Random.html#method-c-srand
Purplejacket

Ответы:

952

использование rand(range)

Из рубиновых случайных чисел :

Если вам нужно случайное число , чтобы имитировать рулон шестигранного штампа, вы будете использовать: 1 + rand(6). Бросок в кости может быть смоделирован с 2 + rand(6) + rand(6).

Наконец, если вам просто нужен случайный float, просто позвоните randбез аргументов.


Как отмечает Марк-Андре Лафортун в своем ответе ниже (см. Выше) , Ruby 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.

VonC
источник
2
Разве это не ужасно не похоже на рубин? Я думал, что все является объектом, наименее неожиданным, и это ...
Дэн Розенстарк
1
@yar: Это немного "perlish". Теперь у Руби есть случайный класс (см. Мой ответ)
Марк-Андре Лафортун
3
@VonC: Здорово, что вы отредактировали свой ответ, упомянув новый Randomкласс, но это ужасная идея - звонить Random.newнесколько раз, как в вашем примере. Я отредактировал свой ответ, чтобы заявить, что.
Марк-Андре Лафортун
2
@VonC ах :) извините, если я был немного резок, это просто удивило меня
скакун
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. Я завершил свой собственный ответ, чтобы отразить эту новую функцию (и упомянуть ваш вклад с ошибкой # 3104;)).
VonC
1
@yar: Моя backportsжемчужина - это просто набор методов, которые являются новыми для RUby 1.8.7, 1.9.1, 1.9.2, но реализованы в Ruby. Я использую RubySpec, чтобы гарантировать, что результаты совместимы с Ruby.
Марк-Андре Лафортун
@ Marc-André Lafortune, спасибо за это. Мне всегда было странно, сколько Ruby реализовано в не-Ruby (C или что-то еще) из-за требований к скорости. Но их перерывы
Дэн Розенстарк
5
Random.rand(10..42)не работает. Метод Random.randкласса не принимает диапазон. (Ruby 1.9.2p180)
скакун
1
@banister: вау, я был уверен, что новый API (rand с диапазоном, байтами и т. д.) был доступен напрямую через объект Random. rand with range будет в 1.9.3, и я сделаю запрос функции для байтов. Я отредактировал свой ответ
Marc-André Lafortune
46

Если вы ищете не только число, но также hex или uuid, стоит упомянуть, что SecureRandomмодуль нашел путь ActiveSupportк ядру ruby ​​в 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)

Томас Фанкхаузер
источник
А что если вам нужно случайное число из 4 цифр?
onurozgurozkan
1
я полагаю, SecureRandom.random_number(1000..9999)
онурозгурозкан
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
MattD
источник
Я думаю, что использование ваших rand(1..6)прочтений яснее, чем ответы в топе rand(6)+1.
изоморфизм
21

Ну, я понял это. Очевидно, есть встроенная (?) Функция с именем rand:

rand(n + 1)

Если кто-то ответит более подробным ответом, я отмечу это как правильный ответ.

Марк А. Николози
источник
2
Да, он встроен в модуль ядра.
Кристоф Шиссл
17

Что насчет этого?

n = 3
(0..n).to_a.sample
Rimian
источник
3
Следует отметить, что генерация массива чисел, подобного этому решению, имеет ужасную производительность на больших диапазонах, так как это O (n), тогда randкак O (1).
Трэвис
13

Простейший ответ на вопрос:

rand(0..n)
sqrcompass
источник
9

Вы можете просто использовать random_number .

Если положительное целое число задано как n, random_numberвозвращает целое число: 0 <= random_number<n.

Используйте это так:

any_number = SecureRandom.random_number(100) 

Вывод будет любым числом от 0 до 100.

techdreams
источник
6
rand(6)    #=> gives a random number between 0 and 6 inclusively 
rand(1..6) #=> gives a random number between 1 and 6 inclusively

Обратите внимание, что опция range доступна только в более новых (1.9+ версиях) ruby.

мистифицировать
источник
Я считаю, что опция диапазона доступна только в ruby 1.9.3+. Это не сработало, 1.9.2когда я пытался по крайней мере.
Баткинс
6

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

Rand (диапазон)

или

range.to_a.sample

или

range.to_a.shuffle (это перетасует весь массив, и вы можете выбрать случайное число первым или последним или любым из этого массива, чтобы выбрать случайное)

Sumit
источник
range.to_a.sampleужасная идея, когда образец большой.
Гжегож
5

вы можете сделать ранд (диапазон)

x = rand(1..5)
Snifferdog
источник
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)}
Сэм
источник
Также вы можете следить за этим блогом за пошаговой очень четкой картинкой над случайными номерами в ruby; sitepoint.com/tour-random-ruby
Сэм
4

Простой способ получить случайное число в рубине,

def random    
  (1..10).to_a.sample.to_s
end
YSK
источник
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

Он отлично работает для меня

amarradi
источник
2

Как насчет этого?

num = Random.new
num.rand(1..n)
Хуан Дела Круз
источник
1

Попробуйте array#shuffleметод рандомизации

array = (1..10).to_a
array.shuffle.first
LuckyElf
источник
1
Если вам нужно создать целый массив, хотя бы замените его .shuffle.firstна .sample!
Камиль Гудесюн
0

Не забудьте сначала посеять ГСЧ с помощью srand () .

Liebach
источник
2
Что произойдет, если вы не позвоните srand ()?
Алекс Б
21
srand автоматически вызывается с начальным значением текущего времени, если оно еще не было вызвано.
Джулиан Х