Luyện tập câu lệnh phát sinh ngẫu nhiên random pascal

Thông thường trong nghiên cứu hay kiểm thử chương trình, người ta cần những bộ giá trị ngẫu nhiên với số lượng lớn để kiểm tra khả năng tính tóan và tính đúng của chương trình. Công việc này nếu thực hiện việc nhập số liệu bằng tay sẽ rất mất thời gian và tốn công sức. Vì vậy, chúng ta áp dụng kĩ thuật sinh số ngẫu nhiên kết hợp với mảng một chiều để có được những tập mẫu số lượng lớn, trong khoảng thời gian ngắn và tận dụng được khả năng tính toán của máy tính.

Việc sinh số liệu ngẫu nhiên trong Pascal được thực hiện dựa trên 3 hàm sau:

  1. Hàm random(): sẽ cho một số thực ngẫu nhiên trong [0, 1].
  2. Hàm random(n) với n là một số nguyên: sẽ cho một số nguyên ngẫu nhiên từ 0 đến n.
  3. Hàm randomize: được gọi đến nhằm đảm bảo cứ mỗi lần chạy chương trình thì số liệu ngẫu nhiên của lần này sẽ khác lần trước. 
Xét ví dụ sau: tạo số liệu ngẫu nhiên cho một mảng số nguyên gồm 100 phần tử với giá trị ngẫu nhiên được lấy từ 0 đến 2000.

  1. Viết chương trình sinh chuỗi kí tự ngẫu nhiên chỉ gồm các kí tự tù A đến Z trong bảng mã ASCII. Số liệu ngẫu nhiên thu được lưu trong mảng 1 chiều 30 phần tử kiểu char

Mục tiêu

Làm quen cách viết các chương trình đơn giản, cách sử dụng:


Mô tả bài toán

Nhập (random), xuất mảng một chiều các số nguyên tăng dần


Hướng dẫn

Định nghĩa

Để thực hiện chương trình này, vui lòng xem trước 2 bài:

  • Phát sinh số ngẫu nhiên trong C++ (Random number generation)
  • Mảng 1 chiều trong C++ (Arrays)

Bài tập mang tính tham khảo, hỗ trợ các bạn làm quen và luyện tập với các bàn toán lập trình cơ bản trong C++.

Kteam khuyến khích các bạn tự phân tích đề bài > tự giải bài toán > debug để kiểm tra kết quả và fix lỗi trong quá trình giải. Sau đó, bạn có thể tham khảo source code mẫu để hoàn chỉnh bài tập. 

Để được hỗ trợ tốt nhất, bạn có thể đặt câu hỏi ở phần bình luận bên dưới bài viết hoặc ở mục Hỏi & Đáp.


Source code tham khảo

#include 
#include  // for srand() and rand()
#include  // for time()
using namespace std;

// định nghĩa số phần tử mảng
#define MAX 1000

// khai báo prototype
void nhapMang(int arr[], int &n);
void xuatMang(int arr[], int n);

int main()
{
	int myArray[MAX]; // mảng myArray có MAX phần tử
	int nSize; // nSize là số phần tử được sử dụng, do user nhập

	// nhập xuất mảng tự động
	nhapMang(myArray, nSize);
	xuatMang(myArray, nSize);

	return 0;
}

// hàm nhập mảng
void nhapMang(int arr[], int &n)
{
	// khởi tạo số ngẫu nhiên
	srand(time(NULL));

	cout << "Nhap so luong phan tu n : ";
	cin >> n;

	if (n > 0)
{
	arr[i] = rand() % 100
// khởi tạo ngẫu nhiên từng phần tử từ chỉ số 1 đến n – 1
	for (int i = 1; i < n; i++)
	{
		arr[i] = arr[i - 1] + rand() % 100;
	}
}
}

// hàm xuất mảng
void xuatMang(int arr[], int n)
{
	// xuất từng phần tử cho mảng từ chỉ số 0 đến n – 1
	for (int i = 0; i < n; i++)
	{
		cout << "arr[" << i << "] = " << arr[i] << endl;
	}
}

Kết luận

Bạn có thể củng cố kiến thức C++ từ khóa Lập trình C++ cơ bản.

Hoặc tìm hiểu thêm các bài tập khác trong khóa Bài toán kinh điển trong lập trình

Cảm ơn các bạn đã theo dõi bài viết. Hãy để lại bình luận hoặc góp ý của bạn để phát triển bài viết tốt hơn. Đừng quên “Luyện tập – Thử thách – Không ngại khó”.


Thảo luận

Nếu bạn có bất kỳ khó khăn hay thắc mắc gì về khóa học, đừng ngần ngại đặt câu hỏi trong phần BÌNH LUẬN bên dưới hoặc trong mục HỎI & ĐÁP trên thư viện Howkteam.com để nhận được sự hỗ trợ từ cộng đồng.

Ở bài học trước, mình đã chia sẻ cho các bạn về TỪ KHÓA BREAK & CONTINUE. Từ khóa break được dùng để kết thúc các vòng lặp while, do-while, for và câu điều kiện switch. Từ khóa continue sẽ nhảy đến cuối vòng lặp hiện tại, và thực thi lần lặp tiếp theo.

Trong bài hôm nay, mình sẽ giới thiệu cho các bạn về phương pháp Phát sinh số ngẫu nhiên trong C++ (Random number generation). Bạn có thể ứng dụng nó vào những chương trình cần phát sinh số ngẫu nhiên, các trò chơi, hoặc để ứng dụng vào những bài học về mảng tiếp theo.


Nội dung

Để đọc hiểu bài này tốt nhất các bạn nên có kiến thức cơ bản về:

Trong bài ta sẽ cùng tìm hiểu các vấn đề:

  • Tổng quan về phát sinh số ngẫu nhiên
  • Phát sinh số ngẫu nhiên trong C++
  • Phát sinh số ngẫu nhiên trong C++ 11

Tổng quan về phát sinh số ngẫu nhiên

Phát sinh các số ngẫu nhiên được ứng dụng rất nhiều trong lập trình, đặc biệt là trong các trò chơi, các chương trình cần dữ liệu ngẫu nhiên, ….

Ví dụ về trò chơi bắn máy bay, nếu nó không có những sự kiện ngẫu nhiên, những máy bay sẽ luôn luôn xuất hiện cùng 1 vị trí, tấn công bạn theo cùng một cách, những vật thể xuất hiện trên đường không bao giờ thay đổi, vv ... và đó không phải là một trò chơi hay.

Luyện tập câu lệnh phát sinh ngẫu nhiên random pascal

Vậy số ngẫu nhiên được tạo ra bằng cách nào?

Trong cuộc sống, bạn thường tạo ra số ngẫu nhiên bằng cách như lắc 1 con xúc xắc, rút 1 lá thăm, tung 1 đồng xu, … và rất nhiều vấn đề ngẫu nhiên trong cuộc sống khác.

Trong lập trình, mọi thứ đều được tạo nên từ 2 số 0 và 1, chỉ có đúng hoặc sai, không có trường hợp ở giữa. Máy tính không thể lắc 1 con xúc xắc, rút 1 lá thăm, tung 1 đồng xu, … Kết quả mà nó đưa ra, luôn là kết quả có thể dự đoán trước, ví dụ 1 + 1 luôn luôn là 2, không thể là 1 giá trị khác.

Vì vậy, các máy tính không có khả năng tạo ra số ngẫu nhiên. Muốn tạo số ngẫu nhiên, lập trình viên phải tự xây dựng 1 hệ thống phát sinh số ngẫu nhiên.

Phát sinh số ngẫu nhiên là 1 vấn đề rất cần thiết trong lập trình, để đáp ứng nhu cầu đó, C++ đã xây dựng sẵn 1 số thuật toán phát sinh số ngẫu nhiên.


Ngôn ngữ C++ cung cấp 2 hàm có chức năng khởi tạo và phát sinh số ngẫu nhiên, 2 hàm này thuộc thư viện cstdlib:

Khởi tạo số ngẫu nhiên (initialize random number generator)

Để khởi tạo số ngẫu nhiên, bạn sử dụng hàm srand() thuộc thư viện cstdlib:

void srand(unsigned int seed);

Lưu ý:

  • Hàm srand() nhận vào một đối số kiểu số nguyên không dấu, được gọi là seed (hạt giống).
  • Với mỗi seed khác nhau, hàm srand() sẽ tạo ra những bộ số ngẫu nhiên khác nhau. Những số ngẫu nhiên này sẽ được lấy ra bởi hàm rand().
  • Hai khởi tạo số ngẫu nhiên khác nhau với cùng một seed sẽ tạo ra cùng một kết quả.
  • Chỉ nên gọi hàm srand() 1 lần trước khi phát sinh số ngẫu nhiên.

Kết quả phát sinh số ngẫu nhiên của hàm rand() phụ thuộc vào giá trị của seed (hạt giống), nếu mỗi lần khởi tạo đều sử dụng cùng 1 seed, các số ngẫu nhiên nhận được sẽ là như nhau.

Vì vậy, giá trị của seed (hạt giống) cũng phải là 1 số ngẫu nhiên trong mỗi lần truyền vào hàm srand(). Nghe có vẻ khá mâu thuẩn, chúng ta đang cần 1 số ngẫu nhiên để tạo ra các số ngẫu nhiên. Vậy, vấn đề là người ta phải tìm ra 1 số thay đổi mỗi khi chương trình được chạy, không phải là số do người dùng chọn.

Một giải pháp cho vấn đề này là dựa trên thời gian hệ thống. Mỗi lần chương trình được chạy, thời gian sẽ khác nhau. Nên người ta lấy giá trị thời gian hệ thống làm seed (hạt giống), kết quả sẽ là những số ngẫu nhiên khác nhau trong mỗi lần chạy chương trình.

Để lấy được thời gian từ hệ thống, bạn có thể sử dụng hàm time() thuộc thư viện ctime. Hàm này sẽ trả về số giây từ 00:00 giờ, ngày 01 tháng 1 năm 1970.

Ví dụ:

#include 
#include  // for rand() and srand()
#include  // for time()
using namespace std;

int main()
{
	// initialize random number generator
	srand(time(0)); // set initial seed value to system clock

	// generate random number
	// ...

	return 0;
}

Ví dụ trên chỉ mới khởi tạo số ngẫu nhiên từ thời gian hệ thống, cách phát sinh các số ngẫu nhiên sẽ được giới thiệu ở phần tiếp theo.


Phát sinh số ngẫu nhiên (generate random number)

Để phát sinh 1 số ngẫu nhiên, bạn sử dụng hàm rand() thuộc thư viện cstdlib:

int rand(void);

int rand(void);

Lưu ý:

  • Hàm rand() trả về 1 số nguyên ngẫu nhiên trong khoảng từ 0 đến RAND_MAX.
  • RAND_MAX là 1 hằng số có giá trị 32767, được định nghĩa trong thư viện cstdlib.

Ví dụ về phát sinh số ngẫu nhiên:

int v1 = rand();		// v1 in the range 0 to 32767
int v2 = rand() % 100;		// v2 in the range 0 to 99
int v3 = rand() % 100 + 1;	// v3 in the range 1 to 100
int v4 = rand() % 30 + 1985;	// v4 in the range 1985-2014

Một số ví dụ về phát sinh số ngẫu nhiên

Ví dụ về trò chơi đoán số từ 1 số phát sinh ngẫu nhiên:

#include 
#include  // for rand() and srand()
#include  // for time()
using namespace std;

int main()
{
	int nSecret, nGuess;

	// initialize random seed
	srand(time(NULL));

	// generate secret number between 1 and 10
	nSecret = rand() % 10 + 1;

	do {
		cout << "Guess the number (1 to 10): ";
		cin >> nGuess;

		if (nSecret < nGuess) 
			cout << "The secret number is lower" << endl;
		else if (nSecret > nGuess) 
			cout << "The secret number is higher" << endl;
	} while (nSecret != nGuess);

	cout << "Congratulations!" << endl;

	return 0;
}

Output:

Luyện tập câu lệnh phát sinh ngẫu nhiên random pascal

Chương trình trên phát sinh một số ngẫu nhiên từ 1 đến 10, và yêu cầu người dùng lặp lại việc chọn 1 số sao cho trùng với số ngẫu nhiên của hệ thống.

Ví dụ phát sinh một dãy 10 chữ số ngẫu nhiên:

#include 
#include  // for rand() and srand()
#include  // for time()
using namespace std;

int main()
{
	srand(time(0)); // set initial seed value to system clock

	for (int count = 0; count < 10; ++count)
	{
		cout << rand() << "\t";

		// If we've printed 5 numbers, start a new row
		if ((count + 1) % 5 == 0)
			cout << endl;
	}

	return 0;
}

Output:

Luyện tập câu lệnh phát sinh ngẫu nhiên random pascal


Phát sinh số ngẫu nhiên trong C++ 11

C++ 11 cung cấp thêm rất nhiều thuật toán phát sinh số ngẫu nhiên thuộc thư viện random.

Ví dụ về 1 thuật toán phát sinh số ngẫu nhiên Mersenne Twister thường được sử dụng:

#include 
#include 
using namespace std;

int main()
{
	random_device rd;	// only used once to initialize (seed) engine
	mt19937 rng(rd());	// random-number engine used (Mersenne-Twister in this case)

	// output 10 random number
	for (int i = 0; i < 10; i++)
	{
		auto random_integer = rng();
		cout << random_integer << "\t";

		if ((i + 1) % 5 == 0)
			cout << endl;
	}

	// output 10 random number in the range 1 to 100 
	uniform_int_distribution uni(1, 100);
	for (int i = 0; i < 10; i++)
	{
		auto random_integer = uni(rng);
		cout << random_integer << "\t";

		if ((i + 1) % 5 == 0)
			cout << endl;
	}
	
	return 0;
}

Output:

Luyện tập câu lệnh phát sinh ngẫu nhiên random pascal

Thuật toán trên tạo ra các số nguyên không dấu 32 bit, nên sẽ có phạm vi lớn hơn rất nhiều so với sử dụng hàm rand(). Bạn cũng có thể sử dụng kiểu mt19937_64 cho biến rng để có phạm vi số lớn hơn (64 bit).

Ví dụ trên có sử dụng từ khóa auto, chi tiết về nó sẽ được hướng dẫn trong bài TỪ KHÓA AUTO TRONG C++ (The auto keyword).

Vẫn còn rất nhiều thuật toán phát sinh số ngẫu nhiên khác, các bạn có thể tìm hiểu thêm và chia sẽ lại cho mọi người nhé.


Kết luận

Qua bài học này, bạn đã hiểu rõ về phương pháp Phát sinh số ngẫu nhiên trong C++ (Random number generation). Bạn có thể ứng dụng nó vào những chương trình cần phát sinh số ngẫu nhiên, các trò chơi, hoặc để ứng dụng vào những bài học về mảng tiếp theo.

Trong bài tiếp theo, mình sẽ giới thiệu cho các bạn về MẢNG 1 CHIỀU TRONG C++ (Arrays).

Cảm ơn các bạn đã theo dõi bài viết. Hãy để lại bình luận hoặc góp ý của mình để phát triển bài viết tốt hơn. Đừng quên “Luyện tập – Thử thách – Không ngại khó”.


Thảo luận

Nếu bạn có bất kỳ khó khăn hay thắc mắc gì về khóa học, đừng ngần ngại đặt câu hỏi trong phần BÌNH LUẬN bên dưới hoặc trong mục HỎI & ĐÁP trên thư viện Howkteam.com để nhận được sự hỗ trợ từ cộng đồng.