Cómo obtener un número aleatorio en Ruby

Respuestas:

952

Utilizar rand(range)

De Ruby Random Numbers :

Si se necesitaba un número entero aleatorio para simular una tirada de un dado de seis caras, que tendría que utilizar: 1 + rand(6). Se podría simular un rollo de dados 2 + rand(6) + rand(6).

Finalmente, si solo necesita un flotante aleatorio, simplemente llame randsin argumentos.


Como Marc-André Lafortune menciona en su respuesta a continuación (ir a votar) , Ruby 1.9.2 tiene su propia Randomclase (que el propio Marc-André ayudó a depurar , de ahí el objetivo 1.9.2 para esa característica).

Por ejemplo, en este juego donde necesitas adivinar 10 números , puedes inicializarlos con:

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

Nota:

Es por eso que el equivalente de Random.new.rand(20..30)sería 20 + Random.rand(11), ya que Random.rand(int)devuelve "un entero aleatorio mayor o igual que cero y menor que el argumento ". 20..30incluye 30, necesito encontrar un número aleatorio entre 0 y 11, excluyendo 11.

VonC
fuente
2
¿No es esto terriblemente no rubí? Pensé que todo es un objeto, menos sorpresa y que ...
Dan Rosenstark
1
@ año: Es un poco "perlish". Ahora Ruby tiene su clase aleatoria (ver mi respuesta)
Marc-André Lafortune
3
@VonC: Es genial que haya editado su respuesta para mencionar la nueva Randomclase, pero es una idea terrible llamar Random.newvarias veces como en su ejemplo. He editado mi respuesta para decir eso.
Marc-André Lafortune
2
@VonC ah :) lo siento si fui un poco duro, simplemente me sorprendió
horseyguy
1
Random.rand no aceptar un rango, en realidad. (Desde 1.9.3, creo.)
Ajedi32
591

Si bien puede usar rand(42-10) + 10para obtener un número aleatorio entre 10y 42(donde 10 es inclusivo y 42 exclusivo), hay una mejor manera desde Ruby 1.9.3, donde puede llamar:

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

Disponible para todas las versiones de Ruby al requerir mi backportsgema.

Ruby 1.9.2 también introdujo la Randomclase para que pueda crear sus propios objetos generadores de números aleatorios y tiene una buena API:

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

La Randomclase en sí misma actúa como un generador aleatorio, por lo que llama directamente:

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

Notas sobre Random.new

En la mayoría de los casos, lo más simple es usar rando Random.rand. Crear un nuevo generador aleatorio cada vez que desee un número aleatorio es una muy mala idea . Si hace esto, obtendrá las propiedades aleatorias del algoritmo de inicialización inicial que son atroces en comparación con las propiedades del generador aleatorio en sí .

Si lo usa Random.new, debería llamarlo tan raramente como sea posible , por ejemplo una vez MyApp::Random = Random.newy usarlo en cualquier otro lugar.

Los casos en los que Random.newes útil son los siguientes:

  • estás escribiendo una gema y no quieres interferir con la secuencia de rand/ en la Random.randque los principales programas podrían estar confiando
  • desea secuencias reproducibles separadas de números aleatorios (digamos uno por hilo)
  • desea poder guardar y reanudar una secuencia reproducible de números aleatorios (tan fácil como los Randomobjetos se pueden ordenar)
Marc-André Lafortune
fuente
1
¡Excelente! +1. He completado mi propia respuesta para reflejar esa nueva característica (y mencionar su contribución con el Bug # 3104;)).
VonC
1
@yar: My backportsgem es simplemente una colección de métodos que son nuevos para RUby 1.8.7, 1.9.1, 1.9.2, pero implementados en Ruby. Uso RubySpec para asegurar que los resultados sean compatibles con Ruby.
Marc-André Lafortune
@ Marc-André Lafortune, gracias por eso. Siempre me ha resultado extraño cuánto de Ruby se implementa en no Ruby (C o lo que sea) debido a los requisitos de velocidad. Pero ellos son los descansos
Dan Rosenstark 05 de
55
Random.rand(10..42)No funciona. El Random.randmétodo de clase no acepta un rango. (Ruby 1.9.2p180)
horseyguy
1
@banister: wow, estaba convencido de que la nueva api (rand con rango, bytes, etc.) estaba disponible directamente a través del objeto Random. rand con rango estará en 1.9.3, y haré una solicitud de función para bytes. He editado mi respuesta
Marc-André Lafortune
46

Si no solo está buscando un número, sino también hexadecimal u uid, vale la pena mencionar que el SecureRandommódulo encontró su camino desde ActiveSupportel núcleo de rubí en 1.9.2+. Entonces, sin la necesidad de un marco completo:

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 aquí: Ruby 1.9.3 - Módulo: SecureRandom (lib / securerandom.rb)

Thomas Fankhauser
fuente
¿Qué pasa si necesita un número aleatorio de 4 dígitos?
onurozgurozkan 01 de
1
onurozgurozkan PresumoSecureRandom.random_number(1000..9999)
JayTarka
1
SecureRandom.random_number()no toma un rango, así que no. Probablemente desee algo como SecureRandom.random_number(10_000)(para 0-9999) o SecureRandom.random_number(9_000)+1_000(para 1000-9999).
mwp
1
Random.rand (1000..9999)
Jesse Farmer el
37

Puede generar un número aleatorio con el randmétodo El argumento pasado al randmétodo debe ser un integero a range, y devuelve un número aleatorio correspondiente dentro del rango:

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
fuente
Creo que usar tus rand(1..6)lecturas es más claro que las respuestas principales rand(6)+1.
isomorphismes
21

Bueno, lo descubrí. Aparentemente hay una función incorporada (?) Llamada rand:

rand(n + 1)

Si alguien responde con una respuesta más detallada, lo marcaré como la respuesta correcta.

Mark A. Nicolosi
fuente
2
Sí, está integrado en el módulo Kernel.
Christoph Schiessl
17

¿Qué hay de esto?

n = 3
(0..n).to_a.sample
Rimian
fuente
3
Cabe señalar que generar un conjunto de números como el que proporciona esta solución tiene un rendimiento terrible en grandes rangos, ya que es O (n) mientras que randes O (1).
Travis
13

La respuesta más simple a la pregunta:

rand(0..n)
sqrcompass
fuente
9

Puedes simplemente usar random_number.

Si un entero positivo se da como n, random_numberdevuelve un entero: 0 <= random_number<n.

Úselo así:

any_number = SecureRandom.random_number(100) 

La salida será cualquier número entre 0 y 100.

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

Tenga en cuenta que la opción de rango solo está disponible en las versiones más nuevas (1.9+ creo) de ruby.

Josh
fuente
Creo que la opción de rango solo está disponible en ruby 1.9.3+. No funcionó 1.9.2cuando lo intenté al menos.
Batkins
6

rango = 10..50

rand (rango)

o

rango.a_una.muestra

o

range.to_a.shuffle (esto barajará toda la matriz y puede elegir un número aleatorio por primera o última o cualquiera de esta matriz para elegir uno aleatorio)

sumitir
fuente
range.to_a.sampleEs una idea horrible cuando la muestra es grande.
Grzegorz
5

puedes hacer rand (rango)

x = rand(1..5)
Snifferdog
fuente
4

Este enlace será útil con respecto a esto;

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

Y algo más de claridad a continuación sobre los números aleatorios en rubí;

Genera un entero de 0 a 10

puts (rand() * 10).to_i

Genere un número del 0 al 10 de una manera más legible

puts rand(10)

Genere un número del 10 al 15, incluido 15

puts rand(10..15)

Números aleatorios no aleatorios

Genere la misma secuencia de números cada vez que se ejecuta el programa

srand(5)

Genera 10 números aleatorios

puts (0..10).map{rand(0..10)}
Sam
fuente
También puede seguir este blog para obtener una imagen muy clara paso a paso sobre nos aleatorios en ruby; sitepoint.com/tour-random-ruby
Sam
4

La forma fácil de obtener un número aleatorio en rubí es,

def random    
  (1..10).to_a.sample.to_s
end
ysk
fuente
2

Quizás te ayude. Lo uso en mi aplicación

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

Funciona bien para mí

amarradi
fuente
2

¿Que tal este?

num = Random.new
num.rand(1..n)
Juan Dela Cruz
fuente
1

Pruebe el array#shufflemétodo de aleatorización

array = (1..10).to_a
array.shuffle.first
LuckyElf
fuente
1
Si debe hacer una matriz completa, al menos reemplácela .shuffle.firstcon .sample!
Camille Goudeseune
0

No olvide sembrar el RNG con srand () primero.

Liebach
fuente
2
¿Qué pasa si no llamas a srand ()?
Alex B
21
srand se llama automáticamente con la semilla desde la hora actual si aún no se ha llamado.
Julian H