Hướng dẫn dùng random choosing python

Vietnamese (Tiếng Việt) translation by Dai Phong (you can also view the original English article)

Sự ngẫu nhiên luôn xảy ra ở xung quanh chúng ta. Khi bạn tung một đồng xu hoặc một con súc sắc, bạn không bao giờ có thể chắc chắn về kết quả cuối cùng. Tính bất định này có nhiều ứng dụng như xác định người thắng cuộc khi rút thăm may mắn hoặc tạo ra các test case cho một bài test với các giá trị ngẫu nhiên được tạo ra dựa trên một thuật toán.

Biết được sự hữu ích này, Python đã cung cấp cho chúng ta mô-đun random. Bạn có thể sử dụng nó trong các game để sinh ra đối thủ ngẫu nhiên hoặc để xáo trộn các phần tử trong một danh sách.

Random Hoạt động Như thế nào?

Gần như tất cả các hàm trong mô-đun này phụ thuộc vào hàm random() cơ bản, nó sẽ tạo ra một số float ngẫu nhiên lớn hơn hoặc bằng không và nhỏ hơn một. Python sử dụng Mersenne Twister để tạo ra các số float. Nó tạo ra số float chính xác 53-bit với 2**19937-1 dấu chấm động. Nó thực sự là trình tạo số ngẫu nhiên cho mục đích thông thường được sử dụng rộng rãi nhất.

Đôi khi, bạn muốn trình tạo số ngẫu nhiên tạo ra chuỗi các con số mà nó tạo ra lần đầu tiên. Điều này có thể đạt được bằng cách cung cấp cùng cả hai lần giá trị seed vào trình tạo số ngẫu nhiên bằng hàm seed(s, version). Nếu tham số s bị bỏ qua, trình tạo số ngẫu nhiên sẽ sử dụng thời gian hiện tại của hệ thống để tạo ra các con số. Dưới đây là một ví dụ:

import random random.seed(100) random.random() # returns 0.1456692551041303 random.random() # returns 0.45492700451402135

Hãy nhớ rằng, không giống như tung một đồng xu, mô-đun này tạo ra các con số giả ngẫu nhiên hoàn toàn xác định, vì vậy nó không thích hợp cho các mục đích mật mã.

Tạo Số nguyên Ngẫu nhiên

Mô-đun này có hai hàm khác nhau để tạo ra các số nguyên ngẫu nhiên. Bạn có thể sử dụng randrange(a) để tạo ra một số nguyên ngẫu nhiên nhỏ hơn a.

Tương tự, bạn có thể sử dụng randrange(a, b[,step]) để tạo một số ngẫu nhiên từ range(a, b, step). Ví dụ, sử dụng random.randrange(0, 100, 3) sẽ trả về chỉ những con số giữa 0 và 100 mà đồng thời chia hết cho 3.

Nếu bạn biết cả giới hạn dưới và giới hạn trên, thì bạn có thể sử dụng một hàm đơn giản và trực quan hơn được gọi là randint(a, b). Nó chỉ đơn giản là một hàm thay thế cho randrange(a, b+1).

import random random.randrange(100) # returns 65 random.randrange(100) # returns 98 random.randrange(0, 100, 3) # returns 33 random.randrange(0, 100, 3) # returns 75 random.randint(1,6) # returns 4 random.randint(1,6) # returns 6

Hàm cho Dãy số

Để chọn một phần tử ngẫu nhiên từ một dãy số không rỗng, bạn có thể sử dụng hàm choice(seq). Với randint(), bạn bị giới hạn chọn trong các con số từ một khoảng nhất định. Hàm choice(seq) cho phép bạn chọn một số từ bất kỳ dãy số nào bạn muốn.

Một lợi thế khác của hàm này là nó không giới hạn ở chỉ các con số. Nó có thể chọn bất kỳ loại phần tử ngẫu nhiên nào từ một dãy. Chẳng hạn như, tên của người thắng trong cuộc thi rút thăm may mắn giữa 5 người khác nhau, được cung cấp dưới dạng chuỗi, có thể được xác định bằng hàm này một cách dễ dàng.

Nếu bạn muốn xáo trộn một dãy thay vì chọn một phần tử ngẫu nhiên từ nó, bạn có thể sử dụng hàm shuffle(seq). Việc này sẽ dẫn đến một sự xáo trộn dãy số thích hợp. Đối với một dãy có chỉ có 10(n) phần tử, có thể có tổng cộng 3628800(n!) chỉnh hợp khác nhau. Với một dãy lớn hơn, số hoán vị có thể sẽ cao hơn—điều này hàm ý rằng hàm này có thể không bao giờ tạo ra tất cả các hoán vị của một dãy lớn.

Giả sử bạn phải chọn 50 sinh viên từ 100 nhóm sinh viên để đi du lịch.

Tại thời điểm này, bạn có thể tạm thời sử dụng hàm choice(seq). Vấn đề là bạn sẽ phải gọi nó khoảng 50 lần trong trường hợp tốt nhất, nơi nó không chọn hai lần cùng một sinh viên.

Một giải pháp tốt hơn là sử dụng hàm sample(seq, k). Nó sẽ trả về một danh sách các phần duy nhất k từ dãy đã cho. Dãy ban đầu không thay đổi. Các phần tử trong danh sách kết quả sẽ theo thứ tự lựa chọn. Nếu k lớn hơn số lượng các phần tử trong dãy, một giá trị ValueError sẽ được sinh ra.

import random ids = [1, 8, 10, 12, 15, 17, 25] random.choice(ids) # returns 8 random.choice(ids) # returns 15 names = ['Tom', 'Harry', 'Andrew', 'Robert'] random.choice(names) # returns Tom random.choice(names) # returns Robert random.shuffle(names) names # returns ['Robert', 'Andrew', 'Tom', 'Harry'] random.sample(names, 2) # returns ['Andrew', 'Robert'] random.sample(names, 2) # returns ['Tom', 'Robert'] names # returns ['Robert', 'Andrew', 'Tom', 'Harry']

Như bạn có thể thấy, shuffle(seq) đã thay đổi danh sách ban đầu, nhưng sample(seq, k) giữ nguyên danh sách.

Tạo Số Float Ngẫu nhiên

Trong phần này, bạn sẽ tìm hiểu về các hàm có thể được sử dụng để tạo các số ngẫu nhiên dựa trên những sự phân bổ giá trị thực cụ thể. Các tham số của hầu hết các hàm này được đặt tên theo biến tương ứng trong phương trình thật sự của những phân bổ đó.

Khi bạn chỉ muốn một số từ 0 đến 1, bạn có thể sử dụng hàm random(). Nếu bạn muốn số nằm trong một dãy cụ thể, bạn có thể sử dụng hàm uniform(a, b) với a và b tương ứng như các giới hạn dưới và trên.

Giả sử bạn cần tạo ra một số ngẫu nhiên giữa low và high sao cho có xác suất cao hơn nằm trong vùng lân cận của một số mode khác. Bạn có thể làm điều này với hàm triangular(low, high, mode). Các giá trị low và high sẽ là 0 và 1 theo mặc định. Tương tự như vậy, giá trị mode mặc định nằm giữa điểm của giá trị low và high, dẫn đến phân bổ đối xứng.

Có rất nhiều hàm khác cũng tạo ra các số ngẫu nhiên dựa trên những sự phân bổ khác nhau. Ví dụ, bạn có thể sử dụng normalvariate(mu, sigma) để tạo ra một số ngẫu nhiên dựa trên một sự phân bổ bình thường, với mu là trung bình và sigma như là độ lệch chuẩn.

import random random.random() # returns 0.8053547502449923 random.random() # returns 0.05966180559620815 random.uniform(1, 20) # returns 11.970525425108205 random.uniform(1, 20) # returns 7.731292430291898 random.triangular(1, 100, 80) # returns 42.328674062298816 random.triangular(1, 100, 80) # returns 73.54693076132074

Xác suất Trọng số

Như chúng ta vừa mới thấy, có thể tạo ra các số ngẫu nhiên với các sự phân bổ đồng nhất cũng như sự phân bổ tam giác hoặc bình thường. Ngay cả trong một phạm vi hữu hạn giống như 0 đến 100, thì vẫn có một số lượng vô hạn các số float có thể được tạo ra. Điều gì sẽ xảy ra nếu có một tập hợp các phần tử hữu hạn và bạn muốn thêm trọng số vào một số giá trị cụ thể trong khi chọn một số ngẫu nhiên? Vấn đề này khá phổ biến trong hệ thống xổ số nơi số lượng ít có thưởng được cho một trọng số cao.

Nếu ứng dụng của bạn chấp nhận có trọng số là giá trị số nguyên, thì bạn có thể tạo một danh sách các phần tử có tần số phụ thuộc vào trọng số của chúng. Sau đó bạn có thể sử dụng hàm choice(seq) để chọn một phần tử từ danh sách trọng số này một cách ngẫu nhiên. Đây là một ví dụ minh hoạ việc lựa chọn một khoản tiền thưởng ngẫu nhiên.

import random w_prizes = [('$1', 300), ('$2', 50), ('$10', 5), ('$100', 1)] prize_list = [prize for prize, weight in w_prizes for i in range(weight)] random.choice(prize_list) # returns '$1'

Trong trường hợp của tôi, nó đã mất mười thử nghiệm để có được một giải thưởng 2$ được lựa chọn từ danh sách. Cơ hội nhận được giải thưởng 100$ sẽ thấp hơn nhiều. Tương tự, bạn cũng có thể thêm độ lệch cho các chương trình khác.

Phần Tóm tắt

Mô-đun này có thể hữu ích trong nhiều tình huống như xáo trộn các câu hỏi trong bài tập hoặc tạo ra tên hoặc mật khẩu người dùng ngẫu nhiên bằng cách sử dụng hàm shuffle(). Bạn cũng có thể tạo ra các số ngẫu nhiên đồng nhất cũng như cung cấp trọng số cho các con số trong một phạm vi cụ thể. Trong hướng dẫn tiếp theo, chúng ta sẽ sử dụng các hàm từ mô-đun này để tạo ra dữ liệu ngẫu nhiên cho phân tích thống kê.

Bạn có nghĩ ra ứng dụng thú vị nào trong việc tạo ra số ngẫu nhiên không? Hãy cho chúng tôi biết trong phần bình luận nhé.