Tạo số ngẫu nhiên random bằng VBA (Rnd, Randomize)

Euler

Administrator
Thành viên BQT
Các bạn thân mến, tôi là Euler, là Admin phụ trách dịch thuật trên diễn đàn tuhocvba.net
Hôm nay tôi giới thiệu với các bạn về hàm tạo số ngẫu nhiên. Chúng ta biết rằng, trong thực tế có rất nhiều tình huống để đảm bảo tính khách quan, thay vì chọn theo logic hay quy luật, mọi người kỳ vọng vào một việc ngẫu nhiên để đảm bảo công bằng. Chẳng hạn như việc tạo game, nếu các câu hỏi cứ ra theo tuần tự thì trò chơi thật thiếu hấp dẫn. Vì vậy, người ta sẽ dùng hàm ngẫu nhiên để nhặt câu hỏi một cách ngẫu nhiên. Tương tự, nếu xếp giám thị coi phòng thi mà lại xếp theo tuần tự, thì chẳng còn sự khách quan nào nữa, chúng ta phải sử dụng hàm ngẫu nhiên.
Bạn đã thấy hàm ngẫu nhiên quan trọng chưa nào? Nào cùng tìm hiểu nhé.

1. Rnd, Randomize
2. Chuỗi số ngẫu nhiên
3. Cấu trúc code
4. Tôi muốn lấy số ngẫu nhiên trong phạm vi chỉ định
5. Chương trình mẫu


1. Rnd, Randomize
Để tạo ra số ngẫu nhiên, chúng ta sẽ sử dụng hàm Rnd.
Giá trị trả về của hàm ngẫu nhiên là số có kiểu single . Phạm vi từ 0 cho tới nhỏ hơn 1.
Hàm ngẫu nhiên có khả năng cho các kết quả giống nhau sau mỗi lần gọi nó. Để ngăn chặn điều đó, chúng ta sẽ thực thi Randomize trước khi gọi hàm ngẫu nhiên, để khởi tạo chuỗi số giả lập ngẫu nhiên.

2. Chuỗi số ngẫu nhiên
Chuỗi số ngẫu nhiên có nghĩa là không nên có tính qui tắc nào để có thể đoán được số tiếp theo là gì, tuy nhiên, vì là máy tính thực hiện tính toán đưa ra kết quả ngẫu nhiên cho nên dù thế nào đi nữa vẫn có một quy tắc nào đó.
Có sự lo ngại rằng, từ qui tắc đó, chuỗi số ngẫu nhiên được giải mã từ những mật mã, từ đó có thể đoán định được quy luật ngẫu nhiên. Nếu mà không hiểu bản chất của nó, thì việc tiến hành ngẫu nhiên nhưng lại luôn cho kết quả có thể đoán được, thì tính khách quan không còn nữa. Vì vậy ta cùng tìm hiểu ở phía dưới đây.

Chính vì điều đó, để đảm bảo chuỗi số ngẫu nhiên là không cố định, chúng ta sẽ sử dụng các giá trị được gọi là hạt giống, ứng với mỗi hạt giống sẽ sinh ra một dãy số ngẫu nhiên, để khiến cho qui tắc trên trở nên khó hiểu hơn. (Để việc đoán số tiếp theo là khó có thể làm được).
Tôi ví dụ:
Bạn hãy chạy đoạn code sau:
Mã:
Sub RndTest()
    Call Randomize(1)
  
    Debug.Print Rnd
    Debug.Print Rnd
    Debug.Print Rnd
    Debug.Print Rnd
End Sub
Kết quả là:
Bạn cần đăng nhập để thấy đính kèm

Bây giờ bạn đóng file excel chứa macro trên. Nào, mở lại file và chạy lại thủ tục trên. Thật ngạc nhiên, kết quả bây giờ y hệt với lúc trước. Vậy thì tính ngẫu nhiên ở đâu nữa?

3. Cấu trúc code
Function Rnd([Số]) As Single

Bạn cần đăng nhập để thấy đính kèm

Ví dụ:
Mã:
Sub RndTest()
MsgBox Rnd(-1)
End Sub
Dù tôi có chạy thủ tục trên bao nhiêu lần thì kết quả luôn luôn là:
Bạn cần đăng nhập để thấy đính kèm

Có nghĩa là ứng với -1 thì số ngẫu nhiên là 0.224007
Tương tự, nếu tôi chạy code sau:
Mã:
Sub RndTest()
MsgBox Rnd(0)
End Sub
thì dù có chạy bao nhiêu lần, kết quả cũng luôn giống nhau.
Và bây giờ tôi thử:
Mã:
Sub RndTest()
MsgBox Rnd(2)
End Sub
lúc này thì kết quả chạy lần trước và lần sau không còn thấy trùng lặp nữa.
Sub Randomize([Số])
Bạn cần đăng nhập để thấy đính kèm


4. Tôi muốn lấy số ngẫu nhiên trong phạm vi chỉ định
Hàm ngẫu nhiên Rnd sẽ trả về kết quả là số nằm trong khoảng 0~1. Thực tế, chúng ta thường muốn lấy số ngẫu nhiên trong một phạm vi lớn hơn, chẳng hạn như từ 1~10.
Khi đó công thức của nó là:
Int((Max – Min + 1) * Rnd + Min)

5. Chương trình mẫu

Tôi đưa ra chương trình mẫu, để bạn đọc nhanh chóng sử dụng cho các mục đích của mình.
Mã:
Sub DiceRndSample()
    Dim iMin    '// Giá trị nhỏ nhất
    Dim iMax    '// Giá trị lớn nhất
    Dim ret     '// Giá trị ngẫu nhiên nằm trong khoảng: nhnhaats~lớn nhất
  
    iMin = 1
    iMax = 6
  
    '// Reset chuỗi số ngẫu nhiên
    Call Randomize
  
    '// Lấy giá trị trong phạm vi Min~Max
    ret = Int((iMax - iMin + 1) * Rnd + iMin)
    Debug.Print ret
End Sub
Kết quả các lần chạy:
Bạn cần đăng nhập để thấy đính kèm

Chào tạm biệt các bạn, hẹn gặp lại các bạn trong các bài viết chuyên đề khác.
Nếu có góp ý về bài dịch, xin hãy phản hồi trong topic này. Cảm ơn các bạn.
Nguồn tham khảo:
 
V

vothanhthu

Guest
Nếu để tạo một dãy số ngẫu nhiên từ 1 đến n, mỗi số trong phạm vi từ A đến B. Sao cho tổng của dãy số đó bằng C, trong đó các tham số n, A, B, C điều do ta quy định. Thì sao nhỉ?
 
B

bvtvba

Guest
Nếu để tạo một dãy số ngẫu nhiên từ 1 đến n, mỗi số trong phạm vi từ A đến B. Sao cho tổng của dãy số đó bằng C, trong đó các tham số n, A, B, C điều do ta quy định. Thì sao nhỉ?
Cái này phải giải toán trước khi code.
Chẳng hạn tạo một dãi số a1,a2,...a100 là các số tự nhiên trong khoảng 1 tới 1000 sao cho tổng của chúng là 50: Đây là việc không làm được.
Tóm lại nếu không giải bằng toán trước thì không thể code được, còn cứ lấy ngẫu nhiên bừa phứa rồi sau đó mới check lại điều kiện thì dễ làm cho chương trình chạy vô tận.
Chủ topic là một người giỏi sử dụng ngẫu nhiên, cũng về chủ đề sắp xếp giám thị được đưa ra trên GPE nhưng không ai đưa ra được lời giải nào, thì ở tuhocvba.net, bạn chủ topic đã giải quyết được bài toán ngẫu nhiên với nhiều điều kiện ràng buộc.
 

Euler

Administrator
Thành viên BQT
Ta có bài toán như sau: Sắp xếp các số từ 1 đến 10 một cách ngẫu nhiên.
Bằng cách kết hợp random và ta có thể giải quyết được bài toán này. Cách giải quyết này đã được vbano1 sử dụng trong bài toán .

Bạn cần đăng nhập để thấy đính kèm


Cách giải: Từ ô G5 tới ô G14 tôi nhập hàm :
Mã:
=RAND()
Như vậy tôi đã tạo ra 10 số ngẫu nhiên ở cột G.

Sau đó tôi dùng hàm Rank để xác định vị trí của các số ngẫu nhiên trong dãy. (Xếp giảm dần từ cao đến thấp).
Ở ô I5 tôi nhập công thức là:
Mã:
=RANK(G5,$G$5:$G$14)
Ô I6 nhập công thức là:
Mã:
=RANK(G6,$G$5:$G$14)
...

Như vậy kết quả là tôi đã có dãy số từ 1 đến 10 được sắp xếp ngẫu nhiên trên cột I.
Từ đó có thể thấy, bài toán sắp xếp giám thị hành lang và bài toán sắp xếp dãy số 1 đến 10 một cách ngẫu nhiên là giống nhau về bản chất.
Nguồn tham khảo:
 
Top