: Trình bày cú pháp lệnh lặp với số lần chưa biết trước? Cho ví dụ.
Áp dụng: Viế…
Áp dụng: Viết chương trình tính và đưa ra tổng sau:
S = 1 + 1/3 + 1/5 +1/7 +.+1/N+cho đến khi S > 3,15.
Phần 1: Cú pháp lệnh lặp với số lần chưa biết trước
Trong lập trình, đôi khi chúng ta cần lặp đi lặp lại một công việc nào đó cho đến khi một điều kiện nào đó được thỏa mãn, chứ không phải lặp lại một số lần cố định. Lúc này, chúng ta sẽ sử dụng câu lệnh lặp với số lần chưa biết trước.
Trong ngôn ngữ lập trình Pascal mà chúng ta đang học, câu lệnh lặp với số lần chưa biết trước có hai dạng chính:
1. Dạng WHILE-DO:
Cú pháp:
WHILE <điều kiện> DO
BEGIN
…
END;
Hoặc nếu chỉ có một câu lệnh duy nhất trong khối lặp:
WHILE <điều kiện> DO
Giải thích:
* \(WHILE\): Là từ khóa bắt đầu của câu lệnh lặp.
* \(<điều kiện>\): Là một biểu thức logic, có thể trả về giá trị Đúng (True) hoặc Sai (False).
* \(DO\): Là từ khóa theo sau điều kiện.
* \(BEGIN…END\): Dùng để nhóm nhiều câu lệnh lại thành một khối. Nếu chỉ có một câu lệnh trong khối lặp, chúng ta có thể bỏ \(BEGIN\) và \(END\).
Nguyên tắc hoạt động:
* Chương trình sẽ kiểm tra \(<điều kiện>\) trước khi thực hiện các câu lệnh bên trong khối lặp.
* Nếu \(<điều kiện>\) là Đúng, chương trình sẽ thực hiện các câu lệnh bên trong khối lặp. Sau khi thực hiện xong, chương trình sẽ quay lại kiểm tra \(<điều kiện>\) một lần nữa.
* Nếu \(<điều kiện>\) là Sai, chương trình sẽ bỏ qua khối lệnh bên trong và tiếp tục thực hiện các câu lệnh sau câu lệnh lặp.
* Điều quan trọng là, trong khối lệnh của câu lệnh lặp, phải có ít nhất một câu lệnh làm thay đổi giá trị của các biến trong \(<điều kiện>\), sao cho cuối cùng \(<điều kiện>\) sẽ trở thành Sai, nếu không chương trình sẽ bị lặp vô hạn.
2. Dạng REPEAT-UNTIL:
Cú pháp:
REPEAT
…
UNTIL <điều kiện>;
Giải thích:
* \(REPEAT\): Là từ khóa bắt đầu của câu lệnh lặp.
* \(UNTIL\): Là từ khóa theo sau khối lệnh và trước điều kiện kết thúc.
* \(<điều kiện>\): Là một biểu thức logic, có thể trả về giá trị Đúng (True) hoặc Sai (False).
Nguyên tắc hoạt động:
* Chương trình sẽ THỰC HIỆN các câu lệnh bên trong khối lặp TRƯỚC, sau đó mới kiểm tra \(<điều kiện>\).
* Nếu \(<điều kiện>\) là Sai, chương trình sẽ tiếp tục quay lại thực hiện các câu lệnh bên trong khối lặp.
* Nếu \(<điều kiện>\) là Đúng, chương trình sẽ thoát khỏi vòng lặp và tiếp tục thực hiện các câu lệnh sau câu lệnh lặp.
* Điểm khác biệt lớn nhất so với WHILE-DO là khối lệnh trong REPEAT-UNTIL luôn được thực hiện ít nhất một lần.
* Tương tự như WHILE-DO, cần có câu lệnh làm thay đổi giá trị của biến trong \(<điều kiện>\) để tránh lặp vô hạn.
Trong hai dạng này, REPEAT-UNTIL thường được ưu tiên khi chúng ta muốn khối lệnh bên trong được thực hiện ít nhất một lần, còn WHILE-DO dùng khi có thể không cần thực hiện khối lệnh nào cả nếu điều kiện ban đầu đã sai.
Phần 2: Áp dụng – Bài toán tính tổng S
Đề bài yêu cầu chúng ta viết chương trình tính và đưa ra tổng sau:
S = 1 + 1/3 + 1/5 + 1/7 + … + 1/N cho đến khi S > 3.15.
Chúng ta cần phân tích bài toán này:
1. Khởi tạo: Biến tổng S cần được khởi tạo bằng 0 trước khi cộng các phân số.
2. Các số hạng: Các số hạng của tổng có dạng 1/(số lẻ). Các số lẻ này là 1, 3, 5, 7, …
3. Điều kiện dừng: Chúng ta dừng việc cộng khi tổng S lớn hơn 3.15.
4. Chọn câu lệnh lặp: Vì chúng ta không biết trước sẽ cộng bao nhiêu số hạng để S > 3.15, nên đây là bài toán phù hợp với câu lệnh lặp với số lần chưa biết trước. Trong trường hợp này, việc tính toán S cần ít nhất một lần khởi tạo (s = 0), và chúng ta cần lặp cho đến khi S đạt điều kiện. Dạng REPEAT-UNTIL có vẻ phù hợp hơn vì chúng ta sẽ thực hiện việc tính toán ít nhất một lần.
Bây giờ, chúng ta sẽ đi từng bước để xây dựng chương trình.
Bước 1: Khai báo biến
Chúng ta cần các biến để:
* Lưu trữ tổng S.
* Lưu trữ mẫu số của phân số (số lẻ).
* Có thể cần một biến tạm để lưu giá trị của số hạng.
Ta sẽ khai báo các biến sau:
\(S\): kiểu thực (Real) để lưu tổng, vì tổng có thể có phần thập phân.
\(MauSo\): kiểu số nguyên (Integer) để lưu mẫu số của phân số (1, 3, 5, …).
\(SoHang\): kiểu thực (Real) để lưu giá trị của từng số hạng 1/MauSo.
Bước 2: Khởi tạo giá trị ban đầu
Trước khi vào vòng lặp, chúng ta cần khởi tạo giá trị cho các biến:
* \(S\) phải được gán bằng 0.
* Mẫu số đầu tiên chúng ta cộng là 1/1, vậy \(MauSo\) ban đầu có thể là 1.
Bước 3: Xây dựng vòng lặp
Chúng ta sẽ sử dụng câu lệnh REPEAT-UNTIL.
* Phần thực hiện (REPEAT…): Bên trong vòng lặp, chúng ta cần thực hiện các công việc sau:
* Tính giá trị của số hạng hiện tại: \(SoHang := 1 / MauSo;\)
* Cập nhật tổng S: \(S := S + SoHang;\)
* Tính mẫu số cho lần lặp tiếp theo. Mẫu số tăng lên 2 đơn vị (từ 1 lên 3, từ 3 lên 5, …). Vậy: \(MauSo := MauSo + 2;\)
* Điều kiện dừng (UNTIL <điều kiện>): Chúng ta dừng khi S > 3.15. Vậy điều kiện là \(S > 3.15\).
Bước 4: Xuất kết quả
Sau khi vòng lặp kết thúc (tức là S đã lớn hơn 3.15), chúng ta cần đưa giá trị cuối cùng của S ra màn hình.
Bước 5: Viết mã chương trình hoàn chỉnh
Program TinhTong;
Uses Crt; { Sử dụng Unit Crt để có lệnh ClrScr}
Var
S: Real; { Biến lưu tổng }
MauSo: Integer; { Biến lưu mẫu số (là số lẻ) }
SoHang: Real; { Biến lưu giá trị số hạng 1/MauSo }
Begin
ClrScr; { Xóa màn hình }
{ Khởi tạo giá trị ban đầu }
S := 0;
MauSo := 1;
{ Vòng lặp tính tổng }
REPEAT
{ Tính số hạng }
SoHang := 1 / MauSo;
{ Cộng số hạng vào tổng }
S := S + SoHang;
{ Cập nhật mẫu số cho lần lặp tiếp theo }
MauSo := MauSo + 2;
UNTIL S > 3.15; { Điều kiện dừng }
{ Xuất kết quả }
WriteLn(‘Tong S = ‘, S:0:4); { In S với 4 chữ số sau dấu phẩy }
ReadLn; { Đợi nhấn Enter để kết thúc }
End.
Giải thích chi tiết chương trình:
1. \(Program TinhTong;\): Khai báo tên chương trình.
2. \(Uses Crt;\): Khai báo sử dụng unit Crt để có các thủ tục như ClrScr (xóa màn hình).
3. \(Var S: Real; MauSo: Integer; SoHang: Real;\): Khai báo các biến với kiểu dữ liệu phù hợp. \(Real\) cho S và SoHang vì chúng có thể có phần thập phân. \(Integer\) cho MauSo vì mẫu số là các số nguyên 1, 3, 5,…
4. \(Begin … End.\): Khối lệnh chính của chương trình.
5. \(ClrScr;\): Xóa màn hình trước khi chạy.
6. \(S := 0;\): Khởi tạo biến tổng S bằng 0.
7. \(MauSo := 1;\): Khởi tạo mẫu số đầu tiên là 1, tương ứng với số hạng 1/1.
8. \(REPEAT\): Bắt đầu vòng lặp.
9. \(SoHang := 1 / MauSo;\): Tính giá trị của số hạng thứ nhất (ví dụ: 1/1 = 1), thứ hai (ví dụ: 1/3), thứ ba (ví dụ: 1/5),…
10. \(S := S + SoHang;\): Cộng giá trị số hạng vừa tính vào biến tổng S.
11. \(MauSo := MauSo + 2;\): Tăng mẫu số lên 2 đơn vị để có mẫu số lẻ tiếp theo (từ 1 thành 3, từ 3 thành 5, …).
12. \(UNTIL S > 3.15;\): Điều kiện để thoát khỏi vòng lặp. Khi giá trị của S lớn hơn 3.15, vòng lặp sẽ dừng lại.
13. \(WriteLn(‘Tong S = ‘, S:0:4);\): Sau khi thoát khỏi vòng lặp, dòng lệnh này sẽ in ra màn hình chuỗi “Tong S = ” và giá trị cuối cùng của biến S. \(:0:4\) là định dạng hiển thị, nghĩa là hiển thị toàn bộ phần nguyên và 4 chữ số sau dấu phẩy.
14. \(ReadLn;\): Dừng chương trình lại để người dùng có thể đọc kết quả, chờ người dùng nhấn phím Enter rồi mới kết thúc chương trình.
Các em thấy không, với kiến thức về câu lệnh lặp với số lần chưa biết trước, chúng ta đã giải quyết được một bài toán tính toán có điều kiện dừng rất thú vị. Các em hãy thử tự mình gõ chương trình này vào máy tính và chạy thử để quan sát kết quả nhé! Nếu có bất kỳ câu hỏi nào, đừng ngần ngại hỏi thầy/cô.
Để lặp một khối lệnh một số lần chưa biết trước, ta có thể sử dụng cấu trúc lặp while hoặc repeat-until.
Cấu trúc while: Cú pháp:
while điều kiện lặp do
// Khối lệnh cần lặp
end;
Ví dụ:
var
i: integer;
begin
i := 1;
while i <= 10 do
begin
writeln(‘i = ‘, i);
i := i + 1;
end;
end.
—————————————————————————————-
Cấu trúc repeat-until: Cú pháp:
repeat
// Khối lệnh cần lặp
until điều kiện lặp;
Ví dụ:
var
i: integer;
begin
i := 1;
repeat
writeln(‘i = ‘, i);
i := i + 1;
until i > 10;
end.
—————————————————————————————-
Viết chương trình tính và đưa ra tổng:
program TinhTong;
var
i: integer;
S, a: real;
begin
i := 1;
S := 0;
a := 1;
while (S <= 3.15) do
begin
S := S + a;
a := 1 / (2 * i + 1);
i := i + 1;
end;
writeln(‘Tong S la: ‘, S:0:2);
writeln(‘So phan tu tinh den khi S > 3.15 la: ‘, i – 1);
readln;
end.