Số ngẫu nhiên hữu ích cho nhiều mục đích khác nhau như trong trò chơi, mã hóa và mô phỏng xây dựng. Về mặt kỹ thuật, máy tính không thể tạo ra các số ngẫu nhiên hoàn toàn bằng tính toán. Về cơ bản là không thể tạo ra các số thực sự ngẫu nhiên trên bất kỳ thiết bị xác định nào. Điều tốt nhất bạn có thể hy vọng là các số giả ngẫu nhiên, một dòng các số xuất hiện như thể chúng được tạo ngẫu nhiên.
Trong bài viết này, chúng ta sẽ xem xét các cách khác nhau mà bạn có thể tạo các số ngẫu nhiên trong Ruby.
Tạo số ngẫu nhiên với Kernel # rand
Để bắt đầu, hãy tạo các số ngẫu nhiên với rand
phương pháp. Khi phương thức được gọi mà không có đối số, nó trả về một số thực lớn hơn hoặc bằng 0,0 và nhỏ hơn 1,0.
rand()
> 0.7308136972953823
Để lấy một số nguyên, bạn truyền một số nguyên vào hàm. Hàm sẽ trả về một giá trị nguyên ngẫu nhiên lớn hơn hoặc bằng 0 và nhỏ hơn số nguyên được truyền vào hàm. Mỗi lần chạy phần sau, bạn sẽ nhận được một số nằm trong khoảng từ 0 đến 7.
rand(8)
> 5
Đối với một số ngẫu nhiên trong một phạm vi cụ thể, hãy chuyển Phạm vi thành rand
.
Sau đây sử dụng một bao gồm Phạm vi tạo số ngẫu nhiên từ giới hạn thấp hơn (1
), tối đa (và bao gồm) giới hạn trên (10
).
rand(1..10)
> 6
Ví dụ tiếp theo sử dụng không bao gồm Phạm vi tạo số ngẫu nhiên từ giới hạn dưới, lên đến (nhưng không bao gồm) giới hạn trên.
rand(1...10)
> 9
Phạm vi cũng có thể nằm giữa các giá trị dấu phẩy động.
rand(1.5..3.0)
> 1.7494305393711571
Bạn cũng có thể sử dụng giới hạn phạm vi phủ định với rand
.
rand(-5..-1)
> -5
Việc chuyển một số âm có thể cho kết quả đáng ngạc nhiên, như được hiển thị bên dưới.
rand(-100)
> 94
rand(-0.5)
> 0.7692627344737486
Điều này là do đối số n
được chuyển vào rand
, rand
trả về các số ngẫu nhiên từ 0 đến (nhưng không bao gồm) n.to_i.abs
. Đối với ví dụ trên (-100).to_i.abs
là 100
và (-0.5).to_i.abs
là 0
, do đó kết quả là các số ngẫu nhiên.
Gọi rand(0)
tương tự như cách gọi rand()
. Bạn sẽ nhận được các số ngẫu nhiên từ 0,0 đến 1,0 (không bao gồm).
Tạo chuỗi lặp lại với Kernel # srand
Trước khi chuyển sang phương pháp tạo số ngẫu nhiên tiếp theo, trước tiên chúng ta hãy xem xét srand
chức năng.
Kernel#srand
đặt hạt giống cho Kernel#rand
. Chúng tôi có thể sử dụng nó để tạo chuỗi số ngẫu nhiên có thể lặp lại giữa các lần chạy khác nhau của chương trình.
Để hiểu điều này có nghĩa là gì, trước tiên chúng ta cần hiểu cách các số ngẫu nhiên được tạo ra.
Tạo Số "Ngẫu nhiên" từ Hạt giống
Như đã nói trước đó, máy tính không tạo ra các số thực sự ngẫu nhiên hoàn toàn từ tính toán. Những gì họ làm là tạo ra một chuỗi số có vẻ ngẫu nhiên. Để làm điều này, máy tính bắt đầu với một số hạt giống, nó chạy qua một số thuật toán và sau đó đưa ra một kết quả dường như ngẫu nhiên.
Số hạt giống được tạo bởi máy tính bằng cách sử dụng kết hợp các phần tử khác nhau, ví dụ:dấu thời gian, ID tiến trình của chương trình, e.t.c. Bởi vì các phần tử này khác nhau đối với mỗi yêu cầu tạo một số ngẫu nhiên, số hạt giống sẽ luôn khác nhau, điều này sẽ tạo ra một chuỗi số khác nhau, do đó kết quả đầu ra là số ngẫu nhiên. Nếu bạn chạy thuật toán với cùng một hạt giống, thì bạn sẽ nhận được cùng một dãy số mỗi lần. Đây là những gì Kernel#srand
cho phép chúng tôi làm.
srand
thường được sử dụng trong thử nghiệm. Nó có thể hữu ích cho việc kiểm tra mã trong ứng dụng của bạn liên quan đến tính ngẫu nhiên, với các giá trị là ngẫu nhiên nhưng vẫn đủ dự đoán để kiểm tra. Nó cũng có thể giúp cô lập hoặc tái tạo lỗi.
Dưới đây chúng tôi sử dụng srand
để đặt hạt giống và sau đó gọi rand
đầu tiên để tạo ra một vài số ngẫu nhiên riêng lẻ và sau đó tạo ra một vài chuỗi số ngẫu nhiên.
srand(777)
rand()
> 0.152663734901322
rand()
> 0.3023566097075212
10.times.map { rand(10) }
> [7, 1, 7, 4, 7, 9, 8, 7, 2, 0]
10.times.map { rand(10) }
> [1, 2, 4, 5, 7, 1, 7, 2, 2, 7]
Nếu bạn chạy srand
lại với cùng một hạt giống và thực hiện các cuộc gọi giống như chúng tôi đã thực hiện trước đó, bạn sẽ thấy rằng chúng tôi nhận được các số ngẫu nhiên giống nhau.
srand(777)
rand()
> 0.152663734901322
rand()
> 0.3023566097075212
10.times.map { rand(10) }
> [7, 1, 7, 4, 7, 9, 8, 7, 2, 0]
10.times.map { rand(10) }
> [1, 2, 4, 5, 7, 1, 7, 2, 2, 7]
Tạo số ngẫu nhiên với ngẫu nhiên
Bạn cũng có thể tạo các số ngẫu nhiên với lớp Ngẫu nhiên.
Phương thức lớp rand
cung cấp chức năng cơ bản của Kernel#rand
cùng với việc xử lý tốt hơn các giá trị dấu chấm động.
Random.rand(1...10)
> 5
Không giống như Kernel#rand
, nếu Random.rand
được cho là phủ định hoặc 0
, nó tạo ra ArgumentError.
Tạo số ngẫu nhiên dựa trên phân phối chuẩn
Trong thế giới thực, nhiều thứ có xu hướng tuân theo Phân phối Thông thường. Nếu bạn có một phạm vi giá trị mà một số giá trị nằm dưới, hiếm khi bạn nhận được phân phối bằng nhau của tất cả các giá trị. Hầu hết, phần lớn dữ liệu có xu hướng nằm trong phạm vi nhỏ hơn, với tỷ lệ phần trăm nhỏ hơn nằm trong phạm vi lớn hơn. Hãy lấy chiều cao của một người đàn ông trưởng thành làm ví dụ. Chiều cao ngắn nhất được ghi lại là 54,6 cm (21,5 inch) trong khi chiều cao nhất là 267 cm (8'9 "). Nếu bạn muốn tạo dữ liệu để mô phỏng chiều cao của nam giới trong một quần thể, bạn có thể không muốn sử dụng rand
với những giới hạn này. Bạn không muốn xác suất kiếm được một người đàn ông 8'9 "giống với xác suất có được một người đàn ông 6 ', bởi vì xác suất sau này phổ biến hơn.
Các ví dụ khác về những thứ tuân theo Phân phối Thông thường là:
- Sai số trong phép đo
- Huyết áp
- Điểm kiểm tra
- Cân nặng của một người đàn ông / phụ nữ trưởng thành
Để tạo các số ngẫu nhiên tốt hơn cho các trường hợp sử dụng như vậy, bạn có thể sử dụng rubystats
đá quý.
$ gem install rubystats
require 'rubystats'
adult_male_height = Rubystats::NormalDistribution.new(178, 10)
sample = 50.times.map { adult_male_height.rng.round(1) }
> [183.2, 169.5, 189.7, 171.9, 176.0, 179.3, 189.3, 175.3, 188.3, 190.0, 185.5, 182.8, 187.2, 191.6, 185.4, 178.4, 187.1, 183.3, 189.6, 179.7, 172.7, 174.4, 153.8, 197.4, 176.0, 174.6, 181.1, 182.0, 204.7, 185.2, 175.9, 167.7, 160.6, 170.5, 169.3, 160.6, 165.6, 166.4, 182.6, 179.7, 183.1, 171.9, 185.4, 175.4, 179.7, 176.9, 160.6, 173.8, 181.9, 190.2]
Ở trên, chúng tôi chuyển chiều cao trung bình của nam giới (178cm) và độ lệch chuẩn là 10cm cho NormalDistribution.new
, trước khi tạo 50 giá trị nằm trong phân phối chuẩn này. Nếu bạn tò mò về toán học, bài viết này có thể khiến bạn quan tâm.
Làm tròn ngẫu nhiên
Điều đó đưa chúng ta đến phần cuối của cuộc thảo luận này. Chúng tôi đã đề cập đến một số cách khác nhau để tạo các số 'ngẫu nhiên' trong Ruby, với rand
, srand
, Random
và Rubystats
. Chúng tôi cũng đã đề cập ngắn gọn về cách các số 'ngẫu nhiên' được tạo ra và xem xét lý do tại sao các thiết bị xác định không thể tạo ra các số ngẫu nhiên thực.
Bạn nên lưu ý rằng các phương pháp được đề cập không phải là lý tưởng cho tất cả các trường hợp sử dụng yêu cầu sự ngẫu nhiên. Các số nguyên hoặc dấu phẩy động được tạo bởi các phương pháp có thể lý tưởng để tạo ra cơ hội trong trò chơi hoặc để tạo mô phỏng, nhưng trong các tình huống đòi hỏi một số bảo mật, chẳng hạn như khi tạo mã thông báo đặt lại mật khẩu, bạn nên cân nhắc sử dụng SecureRandom. Với SecureRandom
, bạn có thể tạo các chuỗi thập lục phân, base64, nhị phân và UUID khó bẻ khóa hơn nhiều so với các số đơn giản.
Chúng tôi hy vọng bạn tìm thấy một số điều thú vị này. Nếu bạn có bất kỳ nhận xét hoặc câu hỏi nào về những gì chúng tôi đề cập, vui lòng liên hệ với chúng tôi @AppSignal. Bạn cũng có thể gửi cho chúng tôi yêu cầu của bạn về các chủ đề bạn muốn đề cập.
Chúng tôi đã cập nhật bài viết này vào ngày 1 tháng 8 năm 2018 để bao gồm ghi chú về SecureRandom