Comment obtenir un nombre aléatoire en Ruby


Réponses:


952

Utilisation rand(range)

De Ruby Random Numbers :

Si vous avez besoin d' un nombre entier aléatoire pour simuler un rouleau d'un dé à six faces, vous pouvez utiliser: 1 + rand(6). Un roulement dans le craps pourrait être simulé avec 2 + rand(6) + rand(6).

Enfin, si vous avez juste besoin d'un flottant aléatoire, appelez simplement randsans argument.


Comme Marc-André Lafortune le mentionne dans sa réponse ci-dessous (allez en voter) , Ruby 1.9.2 a sa propre Randomclasse (que Marc-André lui-même a aidé à déboguer , d'où la cible 1.9.2 pour cette fonctionnalité).

Par exemple, dans ce jeu où vous devez deviner 10 nombres , vous pouvez les initialiser avec:

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

Remarque:

C'est pourquoi l'équivalent de Random.new.rand(20..30)serait 20 + Random.rand(11), puisque Random.rand(int)renvoie «un entier aléatoire supérieur ou égal à zéro et inférieur à l'argument ». 20..30comprend 30, je dois trouver un nombre aléatoire entre 0 et 11, à l'exclusion de 11.


2
N'est-ce pas terriblement non rubis? Je pensais que tout était un objet, la moindre surprise et que ...
Dan Rosenstark

1
@yar: C'est un peu "perlish". Maintenant Ruby a sa classe Random (voir ma réponse)
Marc-André Lafortune

3
@VonC: C'est génial que vous ayez modifié votre réponse pour mentionner la nouvelle Randomclasse, mais c'est une idée terrible d'appeler Random.newplusieurs fois comme dans votre exemple. J'ai édité ma réponse pour le dire.
Marc-André Lafortune

2
@VonC ah :) désolé si j'étais un peu dur, ça m'a juste surpris
horseyguy

1
Random.rand n'accepte une gamme, en fait. (Depuis 1.9.3, je crois.)
Ajedi32

591

Bien que vous puissiez utiliser rand(42-10) + 10pour obtenir un nombre aléatoire entre 10et 42(où 10 est inclusif et 42 exclusif), il existe un meilleur moyen depuis Ruby 1.9.3, où vous pouvez appeler:

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

Disponible pour toutes les versions de Ruby en nécessitant mon backportsbijou.

Ruby 1.9.2 a également introduit la Randomclasse afin que vous puissiez créer vos propres objets générateurs de nombres aléatoires et dispose d'une belle API:

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

La Randomclasse elle-même agit comme un générateur aléatoire, vous appelez donc directement:

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

Remarques sur Random.new

Dans la plupart des cas, le plus simple est d'utiliser randou Random.rand. Créer un nouveau générateur aléatoire chaque fois que vous voulez un nombre aléatoire est une très mauvaise idée . Si vous faites cela, vous obtiendrez les propriétés aléatoires de l'algorithme d'amorçage initial qui sont atroces par rapport aux propriétés du générateur aléatoire lui-même .

Si vous utilisez Random.new, vous devez donc l'appeler aussi rarement que possible , par exemple une fois comme MyApp::Random = Random.newet l'utiliser partout ailleurs.

Les cas où cela Random.newest utile sont les suivants:

  • vous écrivez un joyau et ne voulez pas interférer avec la séquence de rand/ sur Random.randlaquelle les programmes principaux peuvent s'appuyer
  • vous voulez des séquences reproductibles séparées de nombres aléatoires (disons une par fil)
  • vous voulez pouvoir sauvegarder et reprendre une séquence reproductible de nombres aléatoires (facile car les Randomobjets peuvent être rassemblés)

1
Excellent! +1. J'ai complété ma propre réponse pour refléter cette nouvelle fonctionnalité (et mentionner votre contribution avec le bogue # 3104;)).
VonC

1
@yar: Mon backportsbijou est simplement une collection de méthodes qui sont nouvelles pour RUby 1.8.7, 1.9.1, 1.9.2, mais implémentées dans Ruby. J'utilise RubySpec pour m'assurer que les résultats sont compatibles avec Ruby.
Marc-André Lafortune

@ Marc-André Lafortune, merci pour ça. Cela a toujours été étrange pour moi de voir combien de Ruby est implémenté en non-Ruby (C ou autre) en raison des exigences de vitesse. Mais ce sont les pauses
Dan Rosenstark

5
Random.rand(10..42)ne marche pas. La Random.randméthode de classe n'accepte pas de plage. (Ruby 1.9.2p180)
horseyguy

1
@banister: wow, j'étais convaincu que le nouvel api (rand avec plage, octets, etc ...) était disponible directement via l'objet Random. rand avec plage sera en 1.9.3, et je ferai une demande de fonctionnalité pour les octets. J'ai édité ma réponse
Marc-André Lafortune

46

Si vous recherchez non seulement un nombre, mais également hex ou uuid, il convient de mentionner que le SecureRandommodule a trouvé son chemin ActiveSupportvers le noyau rubis dans 1.9.2+. Donc, sans avoir besoin d'un cadre complet:

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"

Il est documenté ici: Ruby 1.9.3 - Module: SecureRandom (lib / securerandom.rb)


Et si vous avez besoin d'un nombre aléatoire à 4 chiffres?
onurozgurozkan

1
onurozgurozkan je présumeSecureRandom.random_number(1000..9999)
JayTarka

1
SecureRandom.random_number()ne prend pas de gamme, donc non. Vous voudriez probablement quelque chose comme SecureRandom.random_number(10_000)(pour 0-9999) ou SecureRandom.random_number(9_000)+1_000(pour 1000-9999).
mwp

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

37

Vous pouvez générer un nombre aléatoire avec la randméthode. L'argument passé à la randméthode doit être un integerou un rangeet renvoie un nombre aléatoire correspondant dans la plage:

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

Je pense que l'utilisation de vos rand(1..6)lectures est plus claire que celle de la réponse du haut rand(6)+1.
isomorphismes

21

Eh bien, je l'ai compris. Apparemment, il existe une fonction intégrée (?) Appelée rand:

rand(n + 1)

Si quelqu'un répond par une réponse plus détaillée, je la marquerai comme la bonne réponse.


2
Oui, il est intégré au module Kernel.
Christoph Schiessl

17

Et ça?

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

3
Il convient de noter que la génération d'un tableau de nombres comme cette solution offre des performances terribles sur de grandes plages car c'est O (n) tandis que randO (1).
Travis


9

Vous pouvez simplement utiliser random_number.

Si un entier positif est donné par n, random_numberretourne un entier: 0 <= random_number<n.

Utilisez-le comme ceci:

any_number = SecureRandom.random_number(100) 

La sortie sera un nombre compris entre 0 et 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

Notez que l'option de plage n'est disponible que dans les versions plus récentes (1.9+ je crois) de ruby.


Je pense que l'option de plage n'est disponible qu'en ruby 1.9.3+. Cela n'a pas fonctionné 1.9.2quand j'ai essayé au moins.
Batkins

6

plage = 10..50

rand (plage)

ou

range.to_a.sample

ou

range.to_a.shuffle (cela va mélanger tout le tableau et vous pouvez choisir un nombre aléatoire en premier ou en dernier ou n'importe lequel de ce tableau pour en choisir un au hasard)


range.to_a.sampleest une mauvaise idée quand l'échantillon est gros.
Grzegorz


4

Ce lien va être utile à ce sujet;

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

Et un peu plus de clarté ci-dessous sur les nombres aléatoires en rubis;

Génère un entier de 0 à 10

puts (rand() * 10).to_i

Générer un nombre de 0 à 10 de manière plus lisible

puts rand(10)

Générer un nombre de 10 à 15 dont 15

puts rand(10..15)

Nombres aléatoires non aléatoires

Générez la même séquence de nombres à chaque exécution du programme

srand(5)

Générez 10 nombres aléatoires

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

Vous pouvez également suivre ce blog pour obtenir une image très claire étape par étape sur des numéros aléatoires en rubis; sitepoint.com/tour-random-ruby
Sam

4

Un moyen facile d'obtenir un nombre aléatoire en rubis est,

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

2

Peut-être que cela vous aidera. J'utilise ceci dans mon application

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

Ça fonctionne bien pour moi



1

Essayez la array#shuffleméthode de randomisation

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

1
Si vous devez créer un tableau complet, remplacez-le au moins .shuffle.firstpar .sample!
Camille Goudeseune

0

N'oubliez pas de semer le RNG avec srand () en premier.


2
Que se passe-t-il si vous n'appelez pas srand ()?
Alex B

21
srand est automatiquement appelé, la graine étant de l'heure actuelle si elle n'a pas déjà été appelée.
Julian H
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.