Jak zdobyć losową liczbę w Ruby


Odpowiedzi:


952

Posługiwać się rand(range)

Z rubinowych liczb losowych :

Jeśli potrzebne losową liczbę całkowitą symulować rolkę sześciu jednostronnej matrycy, można użyć: 1 + rand(6). Można symulować rzut w bzdury 2 + rand(6) + rand(6).

Wreszcie, jeśli potrzebujesz tylko losowej liczby zmiennoprzecinkowej, po prostu zadzwoń randbez argumentów.


Jak wspomina Marc-André Lafortune w swojej odpowiedzi poniżej (idź dalej) , Ruby 1.9.2 ma swoją Randomklasę (sam Marc-André pomógł w debugowaniu , stąd cel 1.9.2 dla tej funkcji).

Na przykład w tej grze, w której musisz odgadnąć 10 liczb , możesz je zainicjować za pomocą:

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

Uwaga:

Dlatego odpowiednikiem Random.new.rand(20..30)byłoby 20 + Random.rand(11), ponieważ Random.rand(int)zwraca „losową liczbę całkowitą większą lub równą zero i mniejszą niż argument ”. 20..30obejmuje 30, muszę wymyślić losową liczbę od 0 do 11, z wyłączeniem 11.


2
Czy to nie jest strasznie nie-rubinowe? Myślałem, że wszystko jest przedmiotem, co najmniej zaskakuje i że ...
Dan Rosenstark

1
@yar: To trochę „wyginąć”. Teraz Ruby ma klasę losową (patrz moja odpowiedź)
Marc-André Lafortune

3
@VonC: To wspaniale, że zredagowałeś swoją odpowiedź, aby wspomnieć o nowej Randomklasie, ale to straszny pomysł dzwonić Random.newwiele razy, tak jak w twoim przykładzie. Zredagowałem moją odpowiedź, aby to stwierdzić.
Marc-André Lafortune

2
@VonC ah :) przepraszam, jeśli byłem trochę szorstki, to mnie po prostu zaskoczyło
horseyguy

1
Random.rand ma przyjąć szereg, właściwie. (
Wydaje

591

Chociaż możesz użyć, rand(42-10) + 10aby uzyskać losowy numer pomiędzy 10i 42(gdzie 10 jest włącznie, a 42 wyłącznie), istnieje lepszy sposób od Ruby 1.9.3, w którym możesz dzwonić:

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

Dostępne dla wszystkich wersji Ruby, wymagając mojego backportsklejnotu.

Ruby 1.9.2 również wprowadziło Randomklasę, dzięki czemu możesz tworzyć własne obiekty generatora liczb losowych i ma ładne API:

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

Sama Randomklasa działa jak generator losowy, więc wywołujesz bezpośrednio:

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

Uwagi na temat Random.new

W większości przypadków najprostszym jest użycie randlub Random.rand. Tworzenie nowego losowego generatora za każdym razem, gdy chcesz losową liczbę, jest naprawdę złym pomysłem . Jeśli to zrobisz, otrzymasz losowe właściwości początkowego algorytmu inicjowania, które są okropne w porównaniu do właściwości samego generatora losowego .

Jeśli używasz Random.new, powinieneś wywoływać go tak rzadko, jak to możliwe , na przykład raz MyApp::Random = Random.newi używać go wszędzie indziej.

Przypadki, w których Random.newjest pomocne są następujące:

  • piszesz klejnot i nie chcesz zakłócać sekwencji rand/ Random.rand, na której mogą polegać główne programy
  • chcesz osobnych, powtarzalnych sekwencji liczb losowych (powiedz jeden na wątek)
  • chcesz mieć możliwość zapisywania i wznawiania powtarzalnej sekwencji liczb losowych (łatwe, jak Randomobiekty mogą być zestawiane)

1
Świetny! +1. Ukończyłem własną odpowiedź, aby odzwierciedlić tę nową funkcję (i wspominając twój wkład w Bug # 3104;)).
VonC

1
@yar: Mój backportsklejnot to po prostu zbiór metod, które są nowe w RUby 1.8.7, 1.9.1, 1.9.2, ale zaimplementowane w Ruby. Używam RubySpec, aby zapewnić zgodność wyników z Ruby.
Marc-André Lafortune

@ Marc-André Lafortune, dzięki za to. Zawsze było dla mnie dziwne, ile Ruby jest zaimplementowane w języku innym niż Ruby (C lub cokolwiek innego) z powodu wymagań prędkości. Ale to są przerwy
Dan Rosenstark

5
Random.rand(10..42)nie działa. Metoda Random.randklasy nie akceptuje zakresu. (Ruby 1.9.2p180)
horseyguy

1
@banister: wow, byłem przekonany, że nowy interfejs API (rand z zakresem, bajtami itp.) był dostępny bezpośrednio przez obiekt Random. rand z zakresem będzie w wersji 1.9.3, a ja poproszę o podanie bajtów. Zredagowałem swoją odpowiedź
Marc-André Lafortune,

46

Jeśli szukasz nie tylko liczby, ale także heksa lub uuida, warto wspomnieć, że SecureRandommoduł znalazł drogę ActiveSupportdo rubinowego rdzenia w wersji 1.9.2+. Więc bez potrzeby tworzenia pełnych ram:

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"

Jest to udokumentowane tutaj: Ruby 1.9.3 - Moduł: SecureRandom (lib / securerandom.rb)


Co jeśli potrzebujesz 4 cyfr losowej liczby?
onurozgurozkan

1
onurozgurozkan ZakładamSecureRandom.random_number(1000..9999)
JayTarka,

1
SecureRandom.random_number()nie ma zasięgu, więc nie. Prawdopodobnie chcesz coś takiego SecureRandom.random_number(10_000)(dla 0-9999) lub SecureRandom.random_number(9_000)+1_000(dla 1000-9999).
mwp

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

37

randMetodą można wygenerować liczbę losową . Argument przekazany do randmetody powinien mieć wartość integera lub a rangei zwraca odpowiednią liczbę losową z zakresu:

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

Myślę, że używanie twoich rand(1..6)odczytów jest wyraźniejsze niż w przypadku najlepszych odpowiedzi rand(6)+1.
izomorfizm

21

Cóż, wymyśliłem to. Najwyraźniej istnieje wbudowana funkcja (?) O nazwie rand:

rand(n + 1)

Jeśli ktoś odpowie bardziej szczegółową odpowiedzią, oznaczę ją jako poprawną odpowiedź.


2
Tak, jest wbudowany w moduł jądra.
Christoph Schiessl

17

A co z tym?

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

3
Należy zauważyć, że generowanie tablic liczb, takich jak to rozwiązanie, ma straszną wydajność na dużych zakresach, ponieważ jest to O (n), a randO (1).
Travis


9

Możesz po prostu użyć random_number .

Jeśli dodatnia liczba całkowita jest podana jako n, random_numberzwraca liczbę całkowitą: 0 <= random_number<n.

Użyj tego w ten sposób:

any_number = SecureRandom.random_number(100) 

Wyjście będzie dowolnej liczby od 0 do 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

Zauważ, że opcja zasięgu jest dostępna tylko w nowszych (1.9+) wersjach ruby.


Wierzę, że opcja zasięgu jest dostępna tylko w ruby 1.9.3+. Nie zadziałało, 1.9.2kiedy przynajmniej próbowałem.
Batkins,

6

zakres = 10..50

rand (zakres)

lub

zakres. do. próbki

lub

range.to_a.shuffle (to przetasuje całą tablicę i możesz wybrać losową liczbę według pierwszego, ostatniego lub dowolnej z tej tablicy, aby wybrać losową)


range.to_a.sampleto okropny pomysł, gdy próbka jest duża.
Grzegorz


4

Ten link będzie pomocny w tym zakresie;

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

I jeszcze więcej jasności poniżej liczb losowych w rubinie;

Wygeneruj liczbę całkowitą od 0 do 10

puts (rand() * 10).to_i

Wygeneruj liczbę od 0 do 10 w bardziej czytelny sposób

puts rand(10)

Wygeneruj liczbę od 10 do 15, w tym 15

puts rand(10..15)

Nieprzypadkowe liczby losowe

Generuj tę samą sekwencję liczb przy każdym uruchomieniu programu

srand(5)

Wygeneruj 10 liczb losowych

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

Możesz również śledzić tego bloga krok po kroku, bardzo wyraźny obraz nad losowymi nosami w rubinie; sitepoint.com/tour-random-ruby
Sam

4

Prostym sposobem na uzyskanie losowej liczby w rubinie jest,

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

2

Może ci to pomoże. Używam tego w mojej aplikacji

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

Działa dla mnie dobrze



1

Wypróbuj array#shufflemetodę randomizacji

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

1
Jeśli musisz stworzyć całą tablicę, przynajmniej zastąp .shuffle.first.sample!
Camille Goudeseune,

0

Nie zapomnij najpierw zaszczepić RNG srand () .


2
Co się stanie, jeśli nie wywołasz srand ()?
Alex B

21
srand jest automatycznie wywoływany z ziarnem pochodzącym z bieżącego czasu, jeśli jeszcze nie został wywołany.
Julian H
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.