Việc phát sinh số ngẫu nhiên là cần thiết khi chúng ta cần test chương trình. Việc tạo số ngẫu nhiên trong C++ cũng khá đơn giản. Thư viện chuẩn của C++ cung cấp môt hàm gọi là rand (#include <cstdlib>). Bài viết này sẽ giúp chúng ta hiểu hơn về chức năng tạo số ngẫu nhiên trong C++.
1. Tạo một số ngẫu nhiên:
Hàm rand() trả về một số nguyên nằm trong dãy [0, RAND_MAX], với RAND_MAX là một hằng số được định nghĩa trước. Hãy xem ví dụ bên dưới:
// First example
#include <iostream>
#include <cstdlib>
using namespace std; int main() { int r0 = rand(); int r1 = rand(); int r2 = rand(); int r3 = rand(); int r4 = rand(); cout<< "r0 = "<< r0 << endl; cout<< "r1 = "<< r1 << endl; cout<< "r2 = "<< r2 << endl; cout<< "r3 = "<< r3 << endl; cout<< "r4 = "<< r4 << endl; system("pause"); return 0; }
– Output là:
– Nhưng sau khi chạy nhiều lần chương trình trên, bạn vẫn nhận được một output như lúc đầu. Vấn đề này sẽ được giải quyết trong mục 2.
2. Tạo một số ngẫu nhiên thay đổi theo thời gian
– Để tạo một số ngẫu nhiêu sau thay đổi khác nhau trong những lần chạy, bạn sử dụng hàm time (có trong #include<ctime>). Theo như thư viện MSDN (Microsoft Developers Network) nói rằng: time trả về số của giây được trôi qua được tính từ nữa đêm (00:00:00), ngày 1, tháng 1, năm 1970 theo UTC . (“The time function returns the number of seconds elapsed since midnight (00:00:00), January 1, 1970, coordinated universal time (UTC), according to the system clock”).
– Các số ngẫu nhiên giả được tạo ra bắt đầu từ thời điểm bạn thiết lập sử dụng hàm srand. Dòng code dưới đây thiết lập điểm bắt đầu của thời gian hiện hành.
srand(time(0));
– Giá trị được trả về từ time là qua srand. Lưu ý rằng số ngẫu nhiên được tạo ra trước lời gọi rand.
Ví dụ với chương trình đầu tiên: chúng ta thêm srand(time(0)) trước lời gọi rand().
// Second example
#include <iostream>
#include <cstdlib>
#include <ctime>
using namespace std; int main() { srand(time(0)); int r0 = rand(); int r1 = rand(); int r2 = rand(); int r3 = rand(); int r4 = rand(); cout<< "r0 = "<< r0 << endl; cout<< "r1 = "<< r1 << endl; cout<< "r2 = "<< r2 << endl; cout<< "r3 = "<< r3 << endl; cout<< "r4 = "<< r4 << endl; system("pause"); return 0; }
– Output lần đầu:
– Output lần 2:
3. Tạo số ngẫu nhiên nằm trong dãy xác định (Specifying the range)
– Thông thường, một số ngẫu nhiên nằm trong dãy [0, RAND_MAX] không được mô tả. Đúng hơn là chúng ta không thích một dãy được xác định. Một số ngẫu nhiên trong dãy [0, n – 1] có thể được xác định bằng cách sử dụng toán tử % (modulus). Ví dụ như sinh ra một số ngẫu nhiên trong dãy [0, 21], thì bạn có thể viết như sau:
int num = rand();
int val = num % 22;
– Hoặc có thể viết một cách mạch lạc hơn là:
int num = rand() % 22;
– Khi chúng ta cần một dãy không bắt đầu từ 0. Ví dụ như sinh một số ngẫu nhiên nằm trong dãy [22, 100] thì phải làm sao? Chúng ta có thể thực hiện một cách khá đơn giản theo công thức
Để tạo một số ngẫu nhiên trong dãy [a, b] ta sử dụng công thức:
a + rand() % (b – a + 1)
Như muốn sinh một số ngẫu nhiên từ dãy [22, 100] ta viết như sau:
int num = 22 + rand() % (100 – 22 + 1);
hay đúng hơn là:
int num = 22 + rand() % (79);
– Do phần tạo số ngẫu nhiên trong dãy [a, b] một số bạn comment vẫn chưa làm được hoặc kết quả cho ra chưa như ý muốn. Cho nên sau đây tôi xin bổ sung một đoạn chương trình minh họa cho việc sinh số ngẫu nhiêu trong đoạn [22, 100].
#include <iostream> #include <cstdlib> #include <ctime> using namespace std; int main() { srand(time(0)); int number[200]; for(int i = 1; i <= 200; i++) { number[i] = 1 + rand()%(100-22+1); /* hoac co the viet: number[i] = 1 + rand()%(79); */ } for(int i = 1; i <= 200; i++) { cout<<number[i]<<" "; if(i%20 == 0) cout<<"\n\n"; } cout<<"\n"; system("pause"); return 0; }
kết quả khi chạy chương trình lần 1:
kết quả lần chạy thứ 2:
Sở dĩ chương trình của nhiều bạn không thể cho ra kết quả có số 100 (như bạn luphucnguyen@yahoo.com đã comment dưới bài viết này) là do chương trình của chưa sử dụng hàm srand(time(0)); để sinh ra số ngẫu nhiên trong mỗi lần chạy chương trình, hoặc có thể tập ngẫu nhiên bạn muốn sinh ra chưa đủ lớn nên xác suất có mặt các số mà bạn mong muốn nhỏ hơn (trong ví dụ trên mình sinh ra tập 200 số ngẫu nhiên trong đoạn [22, 100] nên xác suất có mặt của số 100 sẽ cao hơn ).
** Lưu ý: Các ví dụ đề đã được chạy thử trên môi trường DevC++.
(Tham khảo Frank Luna,C++ Programming for Games – Module I)
thank!!!!.
thanks a lots!
THANKS
Cám ơn vì bài viết của bạn!
Thanks!
Cảm ơn bạn! Bài viết rất hữu ích!
tks very much
Rất hay. Thanks u very much! ^^
thanhks you!
bài viết rất hay.thanks
hiih
Như muốn sinh một số ngẫu nhiên từ dãy [22, 100] ta viết như sau:
int num = 22 + rand() % (100 – 22 + 1);
– Mình thấy đoạn code này ko chính xác, nếu như thế num chỉ phát sinh ngẫu nhiên từ 22 -> 99 nhưng đề bài là từ 22 -> 100.
Đoạn này mình cũng không hiểu lắm..admin giải thích thêm được không?..mình test thử từ 1 tới 3…nếu dùng int num = 1 +rand()%(3-(1+1)); thì nó luôn ra kết quả là 1..mặc dù đã cho random ngẫu nhiên !!!
Vậy có phải chăng không cần trừ đi số ban đầu mà chỉ cần nhập vào số đích như thế này int num = 1 + rand()%(3);
Nếu làm như trên thì test nó sẽ random từ 1>>3..Chứ không còn ra mỗi kết quả là 1 như lúc trừ đi số ban đầu nữa !!
Có lẽ câu lệnh của bạn dùng chưa đúng như mình đã viết trong bài viết trên:
Câu lệnh của bạn: int num = 1 +rand()%(3-(1+1)) nên thay bằng:
int num = 1 +rand()%(3-1+1);
ps: mình đã bổ sung ví dụ minh họa cho trường hợp của bạn ở cuối bài viết trên. Cảm ơn bạn đã qua tâm đối với blog của mình.
theo minh hiểu thì:
rand() % n thì sẽ có giá trị từ 0 -> n-1;
khi bạn dung lệnh: rand() % (b-a +1) se cho gia trị chạy từ 0 đến b-a;
vd: từ (22-100) thì rand() % (100-22+1) =rand() % 79 sẽ cho giá trị từ đến 78..
cho nên muốn co giá trị từ 22-100 ban cần công thêm 22
rand() % (b-a +1) +a
vd: rand() %79 + 22 se cho giá trị [0,78] + 22; co nghĩa là giá trị sẽ từ khoảng 22-100;
Trường hợp của bạn có thể là do tập hợp số ngẫu nhiên mà bạn muốn sinh ra hơi nhỏ nên xác suất tạo ra số 100 hơi thấp. Bạn thử sinh ra mảng ngẫu nhiên khoảng 200 số nằm trong đoạn [22, 100] thì sẽ thấy bài viết của mình là đúng.
Mình cũng đã bổ sung đoạn chương trình minh họa cho trường hợp của bạn ở cuối bài viết trên.
mình thử rùi 200 mà k xuất hiện số nào lớn hơn 79, mà mình thử 400,500 mà số xuất hiện chỉ có 200
Bạn viết rất hay!
nếu như mảng đó không đầy đủ các con số từ 22 đến 100 thì sao? ( Ý là mình không sử dụng đến một vài số như bỏ 24, 27, 28, 30, 50, 89, 90, 99) vậy nếu random lỡ trúng vào những con số đó thì sao? Giải quyết thế nào nhỉ? Thanks
Đơn giản thôi. Bạn sử dụng if hoặc switch-case để kiểm tra lại số ngẫu nhiên sinh ra được. Nếu nằm trong các số bạn không muốn lấy thì random lại số khác.
mình có xem qua bài của bạn. trong ví dụ bạn cho sinh số ngẫu nhiên trong [22.100] thì đc kq ra đầy đủ các phần tử, nhưng nếu mình muốn sinh số ngẫu nhiên mà chỉ ra các phần tử ko có lặp thì mình nên làm thế nào. Mình đã thử 1 số cách nhưng chương trình chạy khá là chậm @@
Bạn tham khảo bài viết này xem https://thanhcuong.wordpress.com/2011/03/02/sinh-day-ngau-nhien-tang-c-2/.
Hoặc sử dụng cách kiểm tra nếu phần tử đó đã sinh ra rồi thì không add vào mảng nữa.
theo bạn thanhcuong90 thì cách của bạn ấy là tuyệt đối nhưng mình muốn đóng góp 1 ý kiến là khi bạn dùng vòng lặp ( ví dụ dùng for) thì bạn cho phần tử a[i]=i+a+rand()%(b-a+1); như vậy sẽ giảm xác suất trùng lặp các phần tử ! Nhưng cái này càng đúng khi n càng lớn .
Công nhận anh Cương am tường về C ghê, mình bằng 1/2 thế này thì tốt
cho hoi lam sao de tao ra so thap phan trong c vay
thanks a lots 😀
number[i] = 1 + rand()%(100-22+1); tại sao lại là 1+… mình tưởng là 22+ chứ
với lại khi minh thay tập thành 400,hay 300 số ngẫu nhiên xuất hiên trong khoảng từ [22,100] thì vẫn chỉ xuất hiện 200 số, mà các số xuất hiện đều nhỏ hơn 79 @@..
Cảm ơn bài viết của bạn, rất hữu ích!
thanks u very much
nếu như muốn sinh một chuỗi nhị phân. 32bit … thì có thể làm theo cách này không bạn. mình mới học lập trình nên muốn học hỏi từ mọi người
bạn có thể dùng cách tương tự bài viết để sinh ra một số ngẫu nhiên. Sau đó viết hàm để convert số đó sang dạng chuỗi nhị phân 32 bit. (link tham khảo)
rất cảm ơn bài viết của bạn 🙂 bạn có thể cho mình hỏi làm cách nào để sinh số ngẫu nhiên có 4 chữ số mà mỗi chữ số có giá trị từ 0 đến 6 được không ?? cảm ơn bạn đã đọc câu hỏi này 🙂
bài viết rất hay, cảm ơn bạn 🙂
thanks ban nhieu
number[i] = 1 + rand()%(100-22+1); vẫn phải là number[i] = 22 + rand()%(100-22+1);
Cảm ơn bạn nhiều. Bài viết rất hữu ích 🙂
hi, mình nghĩ bạn set int number[201] thì đúng hơn nhé!(mình chạy thì cái cuối nó tự nhận 200)
giải thích cho mình tác dụng của system(“pause”) và int main{ …. return 0;} với, vì mình thấy mấy cái này không có vẫn chạy và vẫn dừng lại chứ k bị exit sau khi thực hiện lệnh! cái này nó không rõ ràng
bài viết rất hay, mình đang tìm bài random nhập vào mà không có hưỡng dẫn nào