Cara mendapatkan nomor acak di Ruby


Jawaban:


952

Menggunakan rand(range)

Dari Ruby Random Numbers :

Jika Anda membutuhkan integer acak untuk mensimulasikan gulungan mati enam sisi, Anda akan menggunakan: 1 + rand(6). Gulungan craps dapat disimulasikan dengan 2 + rand(6) + rand(6).

Akhirnya, jika Anda hanya perlu float acak, panggil saja randtanpa argumen.


Seperti Marc-André LaFortune menyebutkan dalam jawabannya di bawah ini (pergi upvote itu) , Ruby 1.9.2 memiliki sendiri Randomkelas (yang Marc-André dirinya membantu untuk debug , maka sasaran 1.9.2 untuk fitur itu).

Misalnya, dalam game ini Anda harus menebak 10 angka , Anda dapat menginisialisasi dengan:

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

catatan:

Inilah sebabnya mengapa setara dengan Random.new.rand(20..30)itu 20 + Random.rand(11), karena Random.rand(int)mengembalikan "bilangan bulat acak lebih besar dari atau sama dengan nol dan kurang dari argumen ." 20..30termasuk 30, saya harus membuat angka acak antara 0 dan 11, tidak termasuk 11.


2
Bukankah ini seperti non-ruby? Saya pikir semuanya adalah objek, paling tidak mengejutkan dan itu ...
Dan Rosenstark

1
@yar: Ini agak "perlish". Sekarang Ruby memiliki kelas Acak (lihat jawaban saya)
Marc-André Lafortune

3
@VonC: Sangat bagus Anda mengedit jawaban Anda untuk menyebutkan Randomkelas baru , tapi itu ide yang buruk untuk menelepon Random.newbeberapa kali seperti pada contoh Anda. Saya sudah mengedit jawaban saya untuk menyatakan itu.
Marc-André Lafortune

2
@VonC ah :) maaf jika saya agak keras, itu hanya mengejutkan saya
horseyguy

1
Random.rand memang menerima rentang, sebenarnya. (Sejak 1.9.3, saya percaya.)
Ajedi32

591

Meskipun bisa digunakan rand(42-10) + 10 untuk mendapatkan nomor acak antara 10dan 42(di mana 10 inklusif dan 42 eksklusif), ada cara yang lebih baik sejak Ruby 1.9.3, tempat Anda dapat menelepon:

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

Tersedia untuk semua versi Ruby dengan meminta saya backports permata .

Ruby 1.9.2 juga memperkenalkan Randomkelas sehingga Anda dapat membuat objek penghasil angka acak Anda sendiri dan memiliki API yang bagus:

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

Itu Random kelas itu sendiri bertindak sebagai generator acak, sehingga Anda menghubungi langsung:

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

Catatan aktif Random.new

Dalam kebanyakan kasus, yang paling sederhana adalah menggunakan randatau Random.rand. Membuat generator acak baru setiap kali Anda menginginkan nomor acak adalah ide yang sangat buruk . Jika Anda melakukan ini, Anda akan mendapatkan properti acak dari algoritma seeding awal yang mengerikan dibandingkan dengan properti generator acak itu sendiri .

Jika Anda menggunakan Random.new, Anda harus menyebutnya sesering mungkin , misalnya sekali MyApp::Random = Random.newdan menggunakannya di tempat lain.

Kasus dimana Random.new yang membantu adalah sebagai berikut:

  • Anda sedang menulis permata dan tidak ingin mengganggu urutan rand / Random.randbahwa program utama mungkin mengandalkan
  • Anda ingin memisahkan urutan nomor acak yang dapat direproduksi (katakan satu per utas)
  • Anda ingin dapat menyimpan dan melanjutkan urutan nomor acak yang dapat direproduksi (semudah Randomobjek dapat menyusun)

1
Luar biasa! +1. Saya telah menyelesaikan jawaban saya sendiri untuk mencerminkan fitur baru itu (dan menyebutkan kontribusi Anda dengan Bug # 3104;)).
VonC

1
@yar: backportsPermata saya hanyalah kumpulan metode yang baru untuk RUby 1.8.7, 1.9.1, 1.9.2, tetapi diimplementasikan di Ruby. Saya menggunakan RubySpec untuk memastikan bahwa hasilnya kompatibel dengan Ruby.
Marc-André Lafortune

@ Marc-André Lafortune, terima kasih untuk itu. Itu selalu aneh bagi saya berapa banyak Ruby diimplementasikan dalam non-Ruby (C atau apa pun) karena persyaratan kecepatan. Tapi mereka yang istirahat
Dan Rosenstark

5
Random.rand(10..42)tidak bekerja. The Random.randmetode kelas tidak menerima berbagai. (Ruby 1.9.2p180)
horseyguy

1
@banister: wow, saya yakin bahwa api baru (rand dengan range, byte, dll ...) tersedia langsung melalui objek Acak. Rand dengan kisaran akan berada di 1.9.3, dan saya akan membuat permintaan fitur untuk byte. Saya telah mengedit jawaban saya
Marc-André Lafortune

46

Jika Anda tidak hanya mencari nomor tetapi juga hex atau uuid, perlu disebutkan bahwa SecureRandommodul menemukan jalannya dari ActiveSupportinti ruby ​​di 1.9.2+. Jadi tanpa perlu kerangka penuh sesak nafas:

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"

Ini didokumentasikan di sini: Ruby 1.9.3 - Modul: SecureRandom (lib / securerandom.rb)


Bagaimana jika Anda membutuhkan 4 digit angka acak?
onurozgurozkan

1
onurozgurozkan I presumeSecureRandom.random_number(1000..9999)
JayTarka

1
SecureRandom.random_number()tidak mengambil rentang, jadi tidak. Anda mungkin menginginkan sesuatu seperti SecureRandom.random_number(10_000)(untuk 0-9999) atau SecureRandom.random_number(9_000)+1_000(untuk 1000-9999).
mwp

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

37

Anda dapat menghasilkan angka acak dengan randmetode ini. Argumen yang diteruskan ke randmetode harus berupa integeratau range, dan mengembalikan nomor acak yang sesuai dalam rentang:

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

Saya pikir menggunakan rand(1..6)bacaan Anda lebih jelas daripada jawaban teratas rand(6)+1.
isomorfisma

21

Yah, aku sudah menemukannya. Rupanya ada fungsi builtin (?) Yang disebut rand:

rand(n + 1)

Jika seseorang menjawab dengan jawaban yang lebih terperinci, saya akan menandainya sebagai jawaban yang benar.


2
Ya, itu sudah ada di modul Kernel.
Christoph Schiessl

17

Bagaimana dengan ini?

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

3
Perlu dicatat bahwa menghasilkan array angka seperti solusi ini memberikan kinerja yang mengerikan pada rentang besar karena O (n) sedangkan randO (1).
Travis


9

Anda cukup menggunakan random_number.

Jika bilangan bulat positif diberikan sebagai n, random_numbermengembalikan bilangan bulat: 0 <=random_number <n.

Gunakan seperti ini:

any_number = SecureRandom.random_number(100) 

Output akan berupa angka antara 0 dan 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

Perhatikan bahwa opsi rentang hanya tersedia di versi ruby ​​yang lebih baru (1,9+ saya percaya).


Saya percaya opsi rentang hanya tersedia di ruby 1.9.3+. Itu tidak berhasil 1.9.2ketika saya mencoba setidaknya.
Batkins

6

range = 10..50

rand (range)

atau

range.to_a.sample

atau

range.to_a.shuffle (ini akan mengacak seluruh array dan Anda dapat memilih nomor acak dengan yang pertama atau terakhir atau yang lainnya dari array ini untuk memilih yang acak)


range.to_a.sampleadalah ide yang buruk ketika sampel besar.
Grzegorz


4

Tautan ini akan membantu mengenai hal ini;

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

Dan beberapa kejelasan lagi di bawah ini atas angka acak di ruby;

Hasilkan integer dari 0 hingga 10

puts (rand() * 10).to_i

Hasilkan angka dari 0 hingga 10 Dengan cara yang lebih mudah dibaca

puts rand(10)

Hasilkan angka dari 10 hingga 15 Termasuk 15

puts rand(10..15)

Angka Acak Non-Acak

Hasilkan urutan angka yang sama setiap kali program dijalankan

srand(5)

Hasilkan 10 angka acak

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

Anda juga dapat mengikuti blog ini untuk langkah demi langkah gambar yang sangat jelas atas nos acak di ruby; sitepoint.com/tour-random-ruby
Sam

4

Cara mudah untuk mendapatkan nomor acak di ruby ​​adalah,

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

2

Mungkin itu membantu Anda. Saya menggunakan ini di aplikasi saya

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

Ini bekerja dengan baik untuk saya



1

Coba array#shufflemetode untuk pengacakan

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

1
Jika Anda harus membuat seluruh array, setidaknya ganti .shuffle.firstdengan .sample!
Camille Goudeseune

0

Jangan lupa untuk menaburkan RNG dengan srand () terlebih dahulu.


2
Apa yang terjadi jika Anda tidak memanggil srand ()?
Alex B

21
srand secara otomatis dipanggil dengan seed yang berasal dari waktu saat ini jika belum dipanggil.
Julian H
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.