In trạng thái trước khi sửa để thấy đường đi
Với hai số nguyên **dương** 20 và 16, thuật toán trừ số bé khỏi số lớn giữ ƯCLN và dừng khi hai số bằng nhau. Dòng `print` ở đầu vòng lặp cho thấy các giá trị **trước** mỗi lần trừ:
```python
m, n = 20, 16
while m != n:
print(m, n)
if m < n:
n = n - m
else:
m = m - n
print("Kết quả:", m)
```
Bốn cặp được in là `(20,16)`, `(4,16)`, `(4,12)`, `(4,8)`; sau đó m=n=4 và in `Kết quả: 4`. Nếu đổi thứ tự `print` và phép trừ, bảng theo dõi sẽ là trạng thái **sau** mỗi lần trừ. Phải ghi rõ vị trí quan sát mới hiểu đúng bảng.
Bài luyện
Trong mã với m=20, n=16, cặp đầu tiên được in là gì?
Dòng print đứng trước phép trừ đầu tiên.
Đây là cặp sau lần trừ đầu.
Đây là lúc vòng lặp dừng.
Phép trừ đầu giảm m, không giảm n.
Lời giải
Vòng lặp bắt đầu với m=20, n=16 và in ngay cặp đó, rồi mới tính `m=20-16=4`.
Bài luyện
Sau cặp `4 8`, trạng thái kế tiếp là gì?
4 12 là trạng thái trước.
m<n nên n=8-4=4; m giữ 4.
Không hoán đổi hai biến.
Không trừ 8 cho 8.
Lời giải
Với m=4<n=8, nhánh `n=n-m` cho n=4. Hai số bằng nhau, vòng lặp kết thúc.
Tạm dừng để xem biến
Điểm dừng (breakpoint) do **trình gỡ lỗi của phần mềm lập trình** hỗ trợ. Đặt tại một dòng trong vòng lặp, chạy chương trình và quan sát m,n khi chương trình tạm dừng; tiếp tục từng bước để xem biến đổi. Cách này không thay phép thử đầu vào và đầu ra, mà giúp tìm **lệnh đầu tiên** làm trạng thái khác dự kiến.
Nhiệm vụ thực hành: lưu mã ƯCLN trên vào tệp `.py`, chạy với 20 và 16, đối chiếu bốn cặp in và kết quả 4. Thử thêm 9 và 9: vòng lặp không chạy, kết quả 9. Mã trừ này yêu cầu **cả hai số dương**; nếu một số bằng 0, nó có thể không dừng. Vì vậy phải kiểm đầu vào trước khi dùng, hoặc chọn một thuật toán có xử lí số 0.
Bài luyện
Với cùng mã, nếu m=n=9 từ đầu, điều gì xảy ra?
Điều kiện m!=n sai ngay.
Không vào while; lệnh cuối in 9.
Mã không có phép chia.
m vẫn bằng 9.
Lời giải
`9!=9` sai, nên thân vòng lặp không chạy. Lệnh sau vòng lặp in `Kết quả: 9`.
Bài luyện
Vì sao không dùng nguyên mã trừ này với m=0, n=5?
0 vẫn là số nguyên.
m<n nên n giảm 0 mỗi lượt, trạng thái không đổi.
Python in được số 0.
0 khác 5.
Lời giải
Với m=0<n=5, nhánh `n=n-m` giữ n=5; m vẫn 0. Điều kiện m!=n luôn đúng nên vòng lặp không dừng.
Đang học