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.


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)

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)


¿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

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.


2
Sí, está integrado en el módulo Kernel.
Christoph Schiessl

17

¿Qué hay de esto?

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

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


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.


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.


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)


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


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)}

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

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í



1

Pruebe el array#shufflemétodo de aleatorización

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

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.


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
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.