Cách lấy số ngẫu nhiên trong Ruby


786

Làm thế nào để tôi tạo một số ngẫu nhiên giữa 0n?


Sử dụng srand <some_number>trước khi viết randmã sẽ cung cấp cho bạn một chuỗi giả ngẫu nhiên xác định (nghĩa là có thể lặp lại), nếu bạn cần điều đó. ruby-doc.org/core-2.5.6/Random.html#method-c-srand
Purplejacket

Câu trả lời:


952

Sử dụng rand(range)

Từ số ngẫu nhiên của Ruby :

Nếu bạn cần một số nguyên ngẫu nhiên để mô phỏng một cuộn súc sắc sáu mặt, bạn sẽ sử dụng : 1 + rand(6). Một cuộn trong craps có thể được mô phỏng với 2 + rand(6) + rand(6).

Cuối cùng, nếu bạn chỉ cần một số float ngẫu nhiên, chỉ cần gọi randmà không có đối số.


Như Marc-André Lafortune đã đề cập trong câu trả lời của mình dưới đây (hãy nêu lên) , Ruby 1.9.2 có Randomlớp riêng (mà chính Marc-André đã giúp gỡ lỗi , do đó, mục tiêu 1.9.2 cho tính năng đó).

Chẳng hạn, trong trò chơi này , nơi bạn cần đoán 10 số , bạn có thể khởi tạo chúng bằng:

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

Ghi chú:

Đây là lý do tại sao tương đương Random.new.rand(20..30)sẽ là 20 + Random.rand(11), kể từ khi Random.rand(int)trở lại “một lớn hơn số nguyên ngẫu nhiên hơn hoặc bằng không và ít hơn so với lập luận .” 20..30bao gồm 30, tôi cần đưa ra một số ngẫu nhiên trong khoảng từ 0 đến 11, ngoại trừ 11.


2
Đây không phải là không giống như ruby? Tôi nghĩ mọi thứ đều là một vật thể, ít gây ngạc nhiên nhất và ...
Dan Rosenstark

1
@yar: Đó là một chút "perlish". Bây giờ Ruby có lớp Ngẫu nhiên (xem câu trả lời của tôi)
Marc-André Lafortune

3
@VonC: Thật tuyệt khi bạn chỉnh sửa câu trả lời của mình để đề cập đến Randomlớp mới , nhưng đó là một ý tưởng khủng khiếp để gọi Random.newnhiều lần như trong ví dụ của bạn. Tôi đã chỉnh sửa câu trả lời của mình để nói rằng.
Marc-André Lafortune

2
@VonC ah :) xin lỗi nếu tôi hơi khắc nghiệt, điều đó làm tôi ngạc nhiên
Horseyguy

1
Random.rand không chấp nhận một phạm vi, thực sự. (Kể từ ngày 1.9.3, tôi tin.)
Ajedi32

591

Mặc dù bạn có thể sử dụng rand(42-10) + 10để có được một số ngẫu nhiên giữa 1042(trong đó 10 bao gồm và 42 độc quyền), có một cách tốt hơn kể từ Ruby 1.9.3, nơi bạn có thể gọi:

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

Có sẵn cho tất cả các phiên bản của Ruby bằng cách yêu cầu backportsđá quý của tôi .

Ruby 1.9.2 cũng đã giới thiệu Randomlớp để bạn có thể tạo các đối tượng tạo số ngẫu nhiên của riêng mình và có API đẹp:

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

Các Randomlớp học riêng của mình hoạt động như một máy phát ngẫu nhiên, vì vậy bạn gọi trực tiếp:

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

Ghi chú về Random.new

Trong hầu hết các trường hợp, đơn giản nhất là sử dụng randhoặc Random.rand. Tạo một trình tạo ngẫu nhiên mới mỗi khi bạn muốn một số ngẫu nhiên là một ý tưởng thực sự tồi tệ . Nếu bạn làm điều này, bạn sẽ nhận được các thuộc tính ngẫu nhiên của thuật toán seeding ban đầu rất tàn bạo so với các thuộc tính của chính trình tạo ngẫu nhiên .

Nếu bạn sử dụng Random.new, do đó bạn nên gọi nó càng hiếm khi càng tốt , ví dụ như một lần MyApp::Random = Random.newvà sử dụng nó ở mọi nơi khác.

Các trường hợp Random.newhữu ích là như sau:

  • bạn đang viết một viên ngọc và không muốn can thiệp vào chuỗi rand/ Random.randmà các chương trình chính có thể dựa vào
  • bạn muốn các chuỗi có thể lặp lại của các số ngẫu nhiên (giả sử một chuỗi trên mỗi luồng)
  • bạn muốn có thể lưu và tiếp tục một chuỗi số ngẫu nhiên Randomcó thể lặp lại (dễ dàng như các đối tượng có thể sắp xếp lại)

1
Thông minh! +1. Tôi đã hoàn thành câu trả lời của riêng mình để phản ánh tính năng mới đó (và đề cập đến đóng góp của bạn với Bug # 3104;)).
VonC

1
@yar: Đá backportsquý của tôi chỉ đơn giản là một tập hợp các phương thức mới đối với RUby 1.8.7, 1.9.1, 1.9.2, nhưng được triển khai trong Ruby. Tôi sử dụng RubySpec để đảm bảo rằng kết quả tương thích với Ruby.
Marc-André Lafortune

@ Marc-André Lafortune, cảm ơn vì điều đó. Tôi luôn thấy lạ khi có bao nhiêu Ruby được triển khai trong phi Ruby (C hoặc bất cứ thứ gì) do yêu cầu tốc độ. Nhưng đó là giờ nghỉ
Dan Rosenstark

5
Random.rand(10..42)không hoạt động. Các Random.randphương pháp lớp học không chấp nhận một phạm vi. (Ruby 1.9.2p180)
Horseyguy

1
@banister: wow, tôi đã bị thuyết phục rằng api mới (rand với phạm vi, byte, v.v.) có sẵn trực tiếp thông qua đối tượng Random. rand với phạm vi sẽ ở 1.9.3 và tôi sẽ đưa ra yêu cầu tính năng cho byte. Tôi đã chỉnh sửa câu trả lời của mình
Marc-André Lafortune

46

Nếu bạn không chỉ tìm kiếm một số mà còn hex hoặc uuid, điều đáng nói là SecureRandommô-đun đã tìm được đường ActiveSupportđến lõi ruby ​​trong 1.9.2+. Vì vậy, không cần một khuôn khổ đầy đủ:

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"

Nó được ghi lại ở đây: Ruby 1.9.3 - Mô-đun: SecureRandom (lib / securandom.rb)


Nếu bạn cần 4 chữ số ngẫu nhiên thì sao?
onurozgurozkan

1
onurozgurozkan tôi đoánSecureRandom.random_number(1000..9999)
JayTarka

1
SecureRandom.random_number()không có một phạm vi, vì vậy không. Bạn có thể sẽ muốn một cái gì đó như SecureRandom.random_number(10_000)(cho 0-9999) hoặc SecureRandom.random_number(9_000)+1_000(cho 1000-9999).
mwp

1
Random.rand (1000..9999)
Nông dân Jesse

37

Bạn có thể tạo một số ngẫu nhiên với randphương thức. Đối số được truyền cho randphương thức phải là một integerhoặc a rangevà trả về một số ngẫu nhiên tương ứng trong phạm vi:

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

Tôi nghĩ rằng việc sử dụng rand(1..6)bài đọc của bạn rõ ràng hơn câu trả lời hàng đầu rand(6)+1.
đẳng cấu

21

Vâng, tôi đã tìm ra nó. Rõ ràng có một hàm dựng sẵn (?) Được gọi là rand:

rand(n + 1)

Nếu ai đó trả lời bằng câu trả lời chi tiết hơn, tôi sẽ đánh dấu đó là câu trả lời đúng.


2
Có, nó được tích hợp trong mô-đun Kernel.
Christoph Schiessl

17

Cái này thì sao?

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

3
Cần lưu ý rằng việc tạo ra một dãy số như giải pháp này cung cấp có hiệu suất khủng khiếp trên phạm vi lớn vì nó là O (n) trong khi đó randlà O (1).
Travis


9

Bạn chỉ có thể sử dụng random_number.

Nếu một số nguyên dương được cho là n, random_numbertrả về một số nguyên: 0 <= random_number<n.

Sử dụng nó như thế này:

any_number = SecureRandom.random_number(100) 

Đầu ra sẽ là bất kỳ số nào trong khoảng từ 0 đến 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

Lưu ý rằng tùy chọn phạm vi chỉ khả dụng trong các phiên bản ruby ​​mới hơn (1.9+ tôi tin).


Tôi tin rằng tùy chọn phạm vi chỉ có sẵn trong ruby 1.9.3+. Nó đã không hoạt động 1.9.2khi tôi cố gắng ít nhất.
Batkins

6

phạm vi = 10,50

rand (phạm vi)

hoặc là

phạm vi.to_a.sample

hoặc là

range.to_a.shuffle (điều này sẽ xáo trộn toàn bộ mảng và bạn có thể chọn một số ngẫu nhiên bằng cách đầu tiên hoặc cuối cùng hoặc bất kỳ từ mảng này để chọn một ngẫu nhiên)


range.to_a.samplelà một ý tưởng khủng khiếp khi mẫu lớn.
Grzegorz


4

Liên kết này sẽ hữu ích về việc này;

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

Và một số rõ ràng hơn dưới đây về các số ngẫu nhiên trong ruby;

Tạo một số nguyên từ 0 đến 10

puts (rand() * 10).to_i

Tạo số từ 0 đến 10 Theo cách dễ đọc hơn

puts rand(10)

Tạo số từ 10 đến 15 Bao gồm 15

puts rand(10..15)

Số ngẫu nhiên không ngẫu nhiên

Tạo cùng một dãy số mỗi khi chương trình được chạy

srand(5)

Tạo 10 số ngẫu nhiên

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

Ngoài ra, bạn có thể theo dõi blog này từng bước hình ảnh rất rõ ràng trên số nos ngẫu nhiên trong ruby; sitepoint.com/tour-random-ruby
Sam

4

Cách dễ dàng để có được số ngẫu nhiên trong ruby ​​là,

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

2

Có lẽ nó giúp bạn. Tôi sử dụng điều này trong ứng dụng của tôi

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/opes/random.rb

Việc này ổn với tôi



1

Thử array#shufflephương pháp ngẫu nhiên

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

1
Nếu bạn phải tạo toàn bộ một mảng, ít nhất là thay thế .shuffle.firstbằng .sample!
Camille Goudeseune

0

Đừng quên tạo RNG bằng srand () trước.


2
Điều gì xảy ra nếu bạn không gọi srand ()?
Alex B

21
srand được tự động gọi với hạt giống từ thời điểm hiện tại nếu nó chưa được gọi.
Julian H
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.