Jak wygenerować losową liczbę między aib w Ruby?


189

Na przykład, aby wygenerować losową liczbę od 3 do 10, używam: rand(8) + 3

Czy jest na to lepszy sposób (coś takiego rand(3, 10))?


4
def my_rand(x, y); rand(y - x) + x; end
Theo,

@ Nawiasem mówiąc, Theo y - x + 1.
Nakilon,

1
Spróbuj wpisać poprawną odpowiedź na 10 i 10 ** 24 jako limity: 0 będzie bardzo długo czekać :)
Sayan Malakshinov

5
Działa to:rand(3..10)
Eikes

Odpowiedzi:


324

AKTUALIZACJA: Ruby 1.9.3 Kernel#randakceptuje również zakresy

rand(a..b)

http://www.rubyinside.com/ruby-1-9-3-introduction-and-changes-5428.html

Konwersja na tablicę może być zbyt droga i nie jest konieczna.


(a..b).to_a.sample

Lub

[*a..b].sample

Array # sample

Standard w Ruby 1.8.7+.
Uwaga: w 1.8.7 został nazwany # wybór i w późniejszych wersjach przemianowany.

Ale i tak generowanie macierzy wymaga zasobów, a rozwiązanie, które już napisałeś, jest najlepsze, co możesz zrobić.


Dzięki! Myślę, że pozostanę przy starej i dobrej metodzie :)
Misha Moroshko,

32
To naprawdę zły pomysł, szczególnie jeśli twoje aib mają nieznane rozmiary. Spróbuj (100000000000000000..100000000000000) .to_a.sample i zobacz, co mam na myśli
:)

4
@pixelearth, jeśli masz lepszy pomysł, który odpowiada na pytanie, możesz pisać.
Nakilon,

rand(a..b)nie działa, to dzieli: TypeError: can't convert Range into Integer. Nie jest nawet obsługiwany w Ruby 2.0
fguillen,

2
@fguillen Działa dla mnie w wersji 1.9.3, nie wiem, dlaczego to nie działa dla ciebie.
Michael Dorst,

87
Random.new.rand(a..b) 

Gdzie ajest twoja najniższa wartość i bnajwyższa wartość.


4
Ważną różnicą do zapamiętania jest to, że jeśli po prostu dzwonisz rand(), to dzwonisz Kernel#rand, co obsługuje tylko maxargument. Jeśli chcesz przekroczyć zakres, musisz użyć Random#rand, co oznacza, że ​​musisz wdrożyć w ten sposób. +1
grumpit

2
należy dodać, że powyższe stosuje się do 1.9.2
grumpit

czy zawiera a i b?
Abhradip


11

Zwróć uwagę na różnicę między operatorami zakresu:

3..10  # includes 10
3...10 # doesn't include 10

3

Zobacz odpowiedź: jest w Ruby 1.9.2, ale nie we wcześniejszych wersjach. Osobiście uważam, że rand (8) + 3 jest w porządku, ale jeśli jesteś zainteresowany, sprawdź klasę Random opisaną w linku.




2

Oto szybki punkt odniesienia zarówno dla, jak #samplei dla #rand:

irb(main):014:0* Benchmark.bm do |x|
irb(main):015:1*   x.report('sample') { 1_000_000.times { (1..100).to_a.sample } }
irb(main):016:1>   x.report('rand') { 1_000_000.times { rand(1..100) } }
irb(main):017:1> end
       user     system      total        real
sample  3.870000   0.020000   3.890000 (  3.888147)
rand  0.150000   0.000000   0.150000 (  0.153557)

Więc robienie rand(a..b)jest właściwą rzeczą

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.