Como obter um número aleatório em Ruby


Respostas:


952

Usar rand(range)

Dos números aleatórios do Ruby :

Se você precisava de um número inteiro aleatório para simular um rolo de um dado de seis lados, você usaria: 1 + rand(6). Um rolo de dados pode ser simulado com 2 + rand(6) + rand(6).

Finalmente, se você precisar apenas de uma flutuação aleatória, basta ligar randsem argumentos.


Como Marc-André Lafortune menciona em sua resposta abaixo (vá para votação) , Ruby 1.9.2 tem sua própria Randomclasse (que o próprio Marc-André ajudou a depurar , daí o alvo 1.9.2 para esse recurso).

Por exemplo, neste jogo em que você precisa adivinhar 10 números , você pode inicializá-los com:

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

Nota:

É por isso que o equivalente a Random.new.rand(20..30)seria 20 + Random.rand(11), pois Random.rand(int)retorna "um número inteiro aleatório maior ou igual a zero e menor que o argumento ". 20..30inclui 30, preciso criar um número aleatório entre 0 e 11, excluindo 11.


2
Isso não é terrivelmente não-rubi? Eu pensei que tudo é um objeto, menos surpresa e que ...
Dan Rosenstark

1
@ yar: É um pouco "perlish". Agora Ruby tem sua classe aleatório (ver minha resposta)
Marc-André Lafortune

3
@VonC: É ótimo você ter editado sua resposta para mencionar a nova Randomturma, mas é uma péssima idéia ligar Random.newvárias vezes, como no seu exemplo. Eu editei minha resposta para afirmar isso.
Marc-André Lafortune

2
@VonC ah :) desculpe se eu era um pouco dura, ele apenas me surpreendeu
horseyguy

1
Random.rand não aceitar um intervalo, na verdade. (Desde 1.9.3, eu acredito.)
Ajedi32

591

Embora você possa usar rand(42-10) + 10para obter um número aleatório entre 10e 42(onde 10 é inclusivo e 42 exclusivo), existe uma maneira melhor desde o Ruby 1.9.3, onde você pode chamar:

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

Disponível para todas as versões do Ruby, exigindo minha backportsgema.

O Ruby 1.9.2 também introduziu a Randomclasse para que você possa criar seus próprios objetos geradores de números aleatórios e tenha uma ótima API:

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

A Randomprópria classe atua como um gerador aleatório, então você chama diretamente:

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

Notas sobre Random.new

Na maioria dos casos, o mais simples é usar randou Random.rand. Criar um novo gerador aleatório sempre que você desejar um número aleatório é uma péssima idéia . Se você fizer isso, obterá as propriedades aleatórias do algoritmo de propagação inicial que são atrozes em comparação com as propriedades do próprio gerador aleatório .

Se você usar Random.new, deverá chamá-lo o mais raramente possível , por exemplo, uma vez MyApp::Random = Random.newe usá-lo em qualquer outro lugar.

Os casos em que Random.newsão úteis são os seguintes:

  • você está escrevendo uma gema e não quer interferir com a sequência de rand/ na Random.randqual os principais programas podem confiar
  • você deseja sequências reproduzíveis separadas de números aleatórios (digamos uma por segmento)
  • você deseja salvar e retomar uma sequência reproduzível de números aleatórios (fácil como os Randomobjetos podem ser organizados)

1
Excelente! +1. Eu completei minha própria resposta para refletir esse novo recurso (e mencionando sua contribuição com o Bug # 3104;)).
VonC 5/05

1
@yar: Minha backportsgem é simplesmente uma coleção de métodos que são novos no RUby 1.8.7, 1.9.1, 1.9.2, mas implementados no Ruby. Eu uso o RubySpec para garantir que os resultados sejam compatíveis com o Ruby.
Marc-André Lafortune 5/05

@ Marc-André Lafortune, obrigado por isso. Sempre foi estranho para mim o quanto de Ruby é implementado em não-Ruby (C ou o que seja) devido a requisitos de velocidade. Mas eles são os intervalos
Dan Rosenstark 5/05

5
Random.rand(10..42)não funciona. O Random.randmétodo de classe não aceita um intervalo. (Ruby 1.9.2p180)
horseyguy

1
@banister: uau, eu estava convencido de que a nova API (margem com intervalo, bytes, etc ...) estava disponível diretamente através do objeto Random. rand com range estará em 1.9.3, e eu farei uma solicitação de recurso para bytes. Eu editei minha resposta
Marc-André Lafortune

46

Se você não está apenas procurando por um número, mas também por hexadecimal ou uuid, vale a pena mencionar que o SecureRandommódulo encontrou o caminho do ActiveSupportnúcleo de rubi no 1.9.2+. Portanto, sem a necessidade de uma estrutura completa:

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"

Está documentado aqui: Ruby 1.9.3 - Módulo: SecureRandom (lib / securerandom.rb)


E se você precisar de um número aleatório de 4 dígitos?
Onurozgurozkan

1
onurozgurozkan eu presumoSecureRandom.random_number(1000..9999)
JayTarka

1
SecureRandom.random_number()não tem um alcance, então não. Você provavelmente desejaria algo como SecureRandom.random_number(10_000)(para 0-9999) ou SecureRandom.random_number(9_000)+1_000(para 1000-9999).
Mwp 27/10/2015

1
Random.rand (1000..9999)
Jesse Farmer

37

Você pode gerar um número aleatório com o randmétodo O argumento passado para o randmétodo deve ser um integerou rangeae retorna um número aleatório correspondente dentro do intervalo:

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

Eu acho que usar suas rand(1..6)leituras mais claras do que as respostas principais rand(6)+1.
Isomorphismes

21

Bem, eu descobri. Aparentemente, existe uma função interna (?) Chamada rand:

rand(n + 1)

Se alguém responder com uma resposta mais detalhada, marcarei isso como a resposta correta.


2
Sim, está embutido no módulo Kernel.
Christoph Schiessl 13/10/08

17

Que tal isso?

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

3
Note-se que a geração de uma matriz de números como esta solução oferece um desempenho terrível em grandes intervalos, pois é O (n) enquanto randO (1).
Travis


9

Você pode simplesmente usar random_number.

Se um número inteiro positivo for dado como n, random_numberretornará um número inteiro: 0 <=random_number <n.

Use-o assim:

any_number = SecureRandom.random_number(100) 

A saída será qualquer número entre 0 e 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

Observe que a opção range está disponível apenas nas versões mais recentes (mais de 1.900 eu acredito) do ruby.


Acredito que a opção de intervalo esteja disponível apenas em ruby 1.9.3+. Não funcionou 1.9.2quando tentei pelo menos.
Batkins

6

range = 10..50

margem (intervalo)

ou

range.to_a.sample

ou

range.to_a.shuffle (isso embaralha toda a matriz e você pode escolher um número aleatório primeiro ou último ou qualquer um deles para selecionar um aleatório)


range.to_a.sampleé uma péssima ideia quando a amostra é grande.
Grzegorz


4

Este link será útil em relação a isso;

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

E um pouco mais de clareza abaixo sobre os números aleatórios em rubi;

Gere um número inteiro de 0 a 10

puts (rand() * 10).to_i

Gere um número de 0 a 10 de uma maneira mais legível

puts rand(10)

Gere um número de 10 a 15, incluindo 15

puts rand(10..15)

Números aleatórios não aleatórios

Gere a mesma sequência de números sempre que o programa for executado

srand(5)

Gere 10 números aleatórios

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

Além disso, você pode seguir este blog para obter uma imagem muito clara passo a passo sobre números aleatórios em rubi; sitepoint.com/tour-random-ruby
Sam

4

A maneira mais fácil de obter números aleatórios em ruby ​​é,

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

2

Talvez isso te ajude. Eu uso isso no meu aplicativo

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

Isso funciona bem para mim



1

Tente array#shufflemétodo para randomização

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

1
Se você precisar criar uma matriz inteira, pelo menos substitua .shuffle.firstpor .sample!
Camille Goudeseune 18/09/19

0

Não se esqueça de propagar o RNG com srand () primeiro.


2
O que acontece se você não chamar srand ()?
Alex B

21
srand é chamado automaticamente com a semente do momento atual, se ainda não foi chamado.
Julian H
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.