Understanding Python Loops: A Beginner's Guide

I. Giới Thiệu Chung: Tại Sao Vòng Lặp Lại Quan Trọng?

Trong thế giới lập trình, việc phải thực hiện một hành động nhiều lần là điều không thể tránh khỏi. Thay vì viết đi viết lại cùng một đoạn mã, vòng lặp cho phép chúng ta định nghĩa một khối lệnhchỉ định số lần hoặc điều kiện để khối lệnh đó được thực thi. Điều này không chỉ giúp mã nguồn trở nên ngắn gọn, dễ đọc, dễ bảo trì hơn mà còn giảm thiểu khả năng phát sinh lỗi do sao chép thủ công.

Python cung cấp hai loại vòng lặp chính, mỗi loại có ưu điểm và trường hợp sử dụng riêng :

  • Vòng lặp for: Thường được sử dụng khi chúng ta biết trước số lần lặp hoặc muốn duyệt qua từng phần tử của một đối tượng có khả năng lặp (gọi là iterable) như danh sách (list), chuỗi (string), tuple, hoặc dictionary.

  • Vòng lặp while: Được sử dụng khi số lần lặp không xác định trước, và việc lặp lại phụ thuộc vào một điều kiện logic nào đó còn đúng.

Hiểu rõ cách thức hoạt động và khi nào nên sử dụng mỗi loại vòng lặp là chìa khóa để viết mã Python hiệu quả và linh hoạt.

II. Làm Chủ Vòng Lặp for: Lặp Qua Các Đối Tượng Iterable

Vòng lặp for là công cụ không thể thiếu khi cần xử lý từng phần tử trong một tập hợp dữ liệu hoặc thực hiện một hành động với số lần lặp xác định trước.

A. Cú Pháp Cơ Bản và Luồng Hoạt Động

Vòng lặp for trong Python được thiết kế để lặp qua các phần tử của bất kỳ chuỗi hoặc đối tượng iterable nào. Một đối tượng iterable là bất kỳ đối tượng nào có thể trả về từng phần tử của nó một cách tuần tự.

Cú pháp: Cấu trúc cơ bản của vòng lặp for như sau :

# code_before_for
for element in iterable:
    # code_inside_for
# code_after_for

Trong đó:

  • forin là các từ khóa của Python.

  • element là một biến tạm, trong mỗi lần lặp, nó sẽ nhận giá trị của một phần tử từ iterable. Bạn có thể đặt tên bất kỳ cho biến này.

  • iterable là đối tượng mà chúng ta muốn lặp qua, ví dụ như một list, string, tuple, dictionary, hoặc kết quả từ hàm range().

  • Dấu hai chấm (:) ở cuối dòng for là bắt buộc, báo hiệu sự bắt đầu của một khối lệnh.

  • # code_inside_for là khối lệnh sẽ được thực thi trong mỗi lần lặp. Quan trọng là khối lệnh này phải được thụt lề (indentation) so với dòng for. Python sử dụng thụt lề để xác định phạm vi của khối lệnh.

Luồng hoạt động: Luồng thực thi của vòng lặp for có thể được mô tả như sau :

  1. Thực thi code_before_for (nếu có).

  2. Vòng lặp bắt đầu. Python lấy phần tử đầu tiên từ iterable và gán cho element.

  3. Kiểm tra xem đã duyệt hết các phần tử của iterable chưa.

    • Nếu chưa (còn phần tử để duyệt): Thực thi code_inside_for. Sau đó, quay lại bước 2 để lấy phần tử tiếp theo.

    • Nếu đã duyệt hết phần tử cuối cùng: Thoát khỏi vòng lặp.

  4. Thực thi code_after_for (nếu có).

Hình 2.A.1: Lưu đồ mô tả quá trình thực thi vòng lặp for trong Python

Ví dụ đơn giản nhất là lặp một số lần nhất định để thực hiện một hành động:

# Lặp lại 5 lần
for i in range(5):
    print('hello')

Trong ví dụ này, range(5) là một iterable tạo ra một chuỗi số từ 0 đến 4. Biến i sẽ lần lượt nhận các giá trị 0, 1, 2, 3, 4 và lệnh print('hello') sẽ được thực thi 5 lần.

B. Sức Mạnh Của Hàm range()

Hàm range() là một công cụ cực kỳ hữu ích và thường xuyên được sử dụng cùng với vòng lặp for để tạo ra một dãy số, qua đó kiểm soát số lần lặp hoặc tạo ra các chỉ số cần thiết.

Cách sử dụng range(): Hàm range() có thể được sử dụng theo nhiều cách :

  1. range(stop): Tạo ra một dãy số nguyên bắt đầu từ 0 và kết thúc tại stop-1.

    • Ví dụ: range(5) sẽ tạo ra các số 0, 1, 2, 3, 4.
    for i in range(5):
        print(i) # Output: 0, 1, 2, 3, 4 (mỗi số trên một dòng)
  1. range(start, stop): Tạo ra một dãy số nguyên bắt đầu từ start và kết thúc tại stop-1.

    • Ví dụ: range(1, 5) sẽ tạo ra các số 1, 2, 3, 4.
    for i in range(1, 5):
        print(i) # Output: 1, 2, 3, 4 (mỗi số trên một dòng)
  1. range(start, stop, step): Tạo ra một dãy số nguyên bắt đầu từ start, kết thúc tại stop-1, với mỗi số cách nhau một khoảng là step.

    • Ví dụ: range(1, 7, 2) sẽ tạo ra các số 1, 3, 5.
    for i in range(1, 7, 2):
        print(i) # Output: 1, 3, 5 (mỗi số trên một dòng)

Ví dụ minh họa với range(): Hàm range() rất linh hoạt và có thể được sử dụng trong nhiều kịch bản khác nhau bên trong vòng lặp for.

  • In bình phương của các số:

      for i in range(5):
          print(i*i) # Output: 0, 1, 4, 9, 16
    

    Trong ví dụ này, qua mỗi lần lặp, giá trị của i được nhân với chính nó và kết quả được in ra.

  • Tính tổng các số từ 0 đến 4:

      total = 0
      for i in range(5):
          total = total + i # hoặc total += i
      print(total) # Output: 10 (vì 0+1+2+3+4 = 10)
    

    Ở đây, biến total được khởi tạo bên ngoài vòng lặp. Trong mỗi lần lặp, giá trị hiện tại của i được cộng vào total. Việc total được khai báo bên ngoài đảm bảo rằng nó giữ giá trị tích lũy qua các lần lặp.

Lưu ý về phạm vi biến (Variable Scope): Một điểm cực kỳ quan trọng khi làm việc với các biến tích lũy (như biến total ở ví dụ trên) là vị trí khai báo của chúng.

  • Nếu biến tích lũy được khai báo bên ngoài vòng lặp, nó sẽ duy trì và cập nhật giá trị của mình qua tất cả các lần lặp. Đây thường là hành vi mong muốn khi tính tổng, đếm, hoặc tích lũy kết quả.

  • Ngược lại, nếu biến tích lũy được khai báo bên trong vòng lặp, nó sẽ được khởi tạo lại ở mỗi lần lặp. Điều này sẽ dẫn đến kết quả không chính xác nếu mục tiêu là tích lũy giá trị.

      # Ví dụ sai: total được khai báo bên trong vòng lặp
      for i in range(5):
          total_sai = 0 # total_sai bị reset ở mỗi lần lặp
          total_sai = total_sai + i
      # print(total_sai) # Sẽ in ra 4 (giá trị của lần lặp cuối cùng)
    
  • Sự phổ biến của range() trong các ví dụ về vòng lặp for cho thấy nó là một iterable cực kỳ quan trọng và thường là điểm khởi đầu cho người mới học về vòng lặp có số lần lặp xác định trước.

C. Duyệt Qua Các Cấu Trúc Dữ Liệu Phổ Biến

Ngoài range(), vòng lặp for rất mạnh mẽ khi được sử dụng để duyệt qua các phần tử của các cấu trúc dữ liệu phổ biến trong Python.

  • List (Danh sách):

      fruits = ['apple', 'banana', 'melon', 'peach']
      for fruit in fruits:
          print(fruit)
      # Output:
      # apple
      # banana
      # melon
      # peach
    
  • String (Chuỗi ký tự): Một chuỗi cũng là một iterable, nơi mỗi ký tự là một phần tử.

      greeting = 'Hello'
      for char in greeting:
          print(char)
      # Output:
      # H
      # e
      # l
      # l
      # o
    
  • Tuple: Tương tự như list, tuple cũng có thể được duyệt qua bằng vòng lặp for.

      fruits_tuple = ('apple', 'banana', 'melon')
      for fruit in fruits_tuple:
          print(fruit)
      # Output:
      # apple
      # banana
      # melon
    
  • Dictionary (Từ điển): Khi duyệt qua một dictionary bằng vòng lặp for mặc định, bạn sẽ duyệt qua các key của nó.

      parameters = {'learning_rate': 0.1, 'optimizer': 'Adam', 'metric': 'Accuracy'}
    
      # Duyệt qua keys
      for key in parameters:
          print(key, "->", parameters[key]) # Hoặc parameters.get(key)
      # Output:
      # learning_rate -> 0.1
      # optimizer -> Adam
      # metric -> Accuracy
    
      # Để duyệt qua values:
      # for value in parameters.values():
      #     print(value)
    
      # Để duyệt qua cả key và value (items):
      # for key, value in parameters.items():
      #     print(key, "->", value)
    

Việc hiểu rõ cách duyệt các iterable khác nhau là nền tảng. Nếu không nắm vững điều này, sẽ khó khăn khi sử dụng các câu lệnh điều khiển luồng như breakcontinue một cách hiệu quả, vì người dùng có thể không kiểm soát được chính xác khi nào và tại sao vòng lặp nên dừng hoặc bỏ qua một bước.

D. Điều Khiển Luồng Vòng Lặp: breakcontinue

Trong nhiều trường hợp, chúng ta cần thay đổi luồng thực thi mặc định của vòng lặp for. Python cung cấp hai từ khóa cho mục đích này: breakcontinue.

  • Từ khóa break: Từ khóa break được sử dụng để thoát hoàn toàn khỏi vòng lặp for (hoặc while) chứa nó, ngay cả khi chưa duyệt hết tất cả các phần tử của iterable hoặc điều kiện của while vẫn còn đúng. Luồng điều khiển của chương trình sẽ chuyển đến câu lệnh đầu tiên ngay sau khối vòng lặp.

      # Duyệt các số từ 0 đến 9, nhưng dừng lại nếu gặp số 5
      for i in range(10):
          if i == 5:
              print("Gặp số 5, thoát vòng lặp!")
              break  # Thoát khỏi vòng lặp for
          print('Giá trị i là', i)
      print("Đã thoát khỏi vòng lặp for.")
      # Output:
      # Giá trị i là 0
      # Giá trị i là 1
      # Giá trị i là 2
      # Giá trị i là 3
      # Giá trị i là 4
      # Gặp số 5, thoát vòng lặp!
      # Đã thoát khỏi vòng lặp for.
    

    Trong ví dụ trên, khi i bằng 5, câu lệnh break được thực thi, và vòng lặp kết thúc ngay lập tức. Các giá trị 6, 7, 8, 9 không được xử lý.

  • Từ khóa continue: Từ khóa continue được sử dụng để bỏ qua phần còn lại của khối lệnh trong lần lặp hiện tại và chuyển ngay sang lần lặp tiếp theo. Các câu lệnh phía sau continue (trong cùng khối lặp) sẽ không được thực thi trong lần lặp đó.

      # Duyệt các số từ 0 đến 9, bỏ qua việc in số 5
      for i in range(10):
          if i == 5:
              print("Bỏ qua số 5...")
              continue  # Bỏ qua phần còn lại của lần lặp này, sang i tiếp theo
          print('Giá trị i là', i)
      print("Đã kết thúc vòng lặp for.")
      # Output:
      # Giá trị i là 0
      # Giá trị i là 1
      # Giá trị i là 2
      # Giá trị i là 3
      # Giá trị i là 4
      # Bỏ qua số 5...
      # Giá trị i là 6
      # Giá trị i là 7
      # Giá trị i là 8
      # Giá trị i là 9
      # Đã kết thúc vòng lặp for.
    

    Trong ví dụ này, khi i bằng 5, continue được gọi. Lệnh print('Giá trị i là', i) không được thực thi cho i=5, và vòng lặp tiếp tục với i=6.

III. Khám Phá Vòng Lặp while: Lặp Khi Điều Kiện Còn Đúng

Khác với vòng lặp for thường dùng khi số lần lặp xác định hoặc duyệt qua tập hợp, vòng lặp while cho phép thực thi một khối lệnh liên tục chừng nào một điều kiện cụ thể vẫn còn đúng.

A. Khái niệm và Cú Pháp Cơ Bản

Vòng lặp while (có nghĩa là "trong khi") sẽ lặp đi lặp lại một khối mã nguồn miễn là một biểu thức điều kiện (condition) được đánh giá là True.

Cú pháp: Cấu trúc cơ bản của vòng lặp while như sau :

# code_before_while
while condition:
    # code_inside_while
# code_after_while

Trong đó:

  • while là từ khóa của Python.

  • condition là một biểu thức logic. Trước mỗi lần lặp, Python sẽ đánh giá biểu thức này. Nếu nó là True, khối lệnh bên trong vòng lặp sẽ được thực thi. Nếu là False, vòng lặp sẽ kết thúc.

  • Dấu hai chấm (:) ở cuối dòng while là bắt buộc.

  • # code_inside_while là khối lệnh sẽ được thực thi lặp đi lặp lại. Khối lệnh này cũng phải được thụt lề.

Luồng hoạt động:

  1. Thực thi code_before_while (nếu có).

  2. Đánh giá condition.

  3. Nếu conditionTrue: a. Thực thi code_inside_while. b. Quay lại bước 2.

  4. Nếu conditionFalse: Thoát khỏi vòng lặp.

  5. Thực thi code_after_while (nếu có).

``

Hình 3.A.1: Lưu đồ mô tả quá trình thực thi vòng lặp while trong Python

Một điểm cực kỳ quan trọng khi sử dụng vòng lặp while là phải đảm bảo rằng có một cơ chế nào đó bên trong vòng lặp để làm cho condition cuối cùng trở thành False. Nếu không, vòng lặp sẽ chạy vô tận (infinite loop), khiến chương trình bị treo.

B. Vòng Lặp while Với Điều Kiện Cụ Thể

Đây là cách sử dụng phổ biến nhất của vòng lặp while, nơi một biến thường được sử dụng để theo dõi số lần lặp hoặc một trạng thái nào đó.

Ví dụ: In các số từ 0 đến 4.

i = 0  # Khởi tạo biến điều khiển
while i < 5:  # Điều kiện lặp
    print(i)
    i = i + 1  # Quan trọng: cập nhật biến điều khiển để điều kiện có thể sai
print('Phần code này khi đã thoát while')

Luồng thực thi của ví dụ trên :

  1. i được gán giá trị 0.

  2. i < 5 (0 < 5) là True. In 0. i trở thành 1.

  3. i < 5 (1 < 5) là True. In 1. i trở thành 2.

  4. i < 5 (2 < 5) là True. In 2. i trở thành 3.

  5. i < 5 (3 < 5) là True. In 3. i trở thành 4.

  6. i < 5 (4 < 5) là True. In 4. i trở thành 5.

  7. i < 5 (5 < 5) là False. Vòng lặp kết thúc.

  8. In 'Phần code này khi đã thoát while'.

Việc nhấn mạnh "cập nhật biến điều kiện" (ví dụ i = i + 1) là cực kỳ quan trọng vì đây là nguồn gốc phổ biến của lỗi vòng lặp vô tận, một lỗi gây khó chịu và khó hiểu cho người mới học. Nếu thiếu bước cập nhật này, điều kiện i < 5 sẽ luôn đúng (nếu i ban đầu nhỏ hơn 5), dẫn đến chương trình không bao giờ thoát khỏi vòng lặp.

C. Kỹ Thuật while Truebreak

Đôi khi, điều kiện để thoát khỏi vòng lặp phức tạp hơn hoặc cần được kiểm tra ở giữa khối lệnh, thay vì chỉ ở đầu mỗi lần lặp. Trong những trường hợp như vậy, kỹ thuật while True: kết hợp với break trở nên rất hữu ích.

Cấu trúc này tạo ra một vòng lặp về mặt lý thuyết là vô tận (True luôn là True), nhưng dựa vào một câu lệnh if bên trong để kiểm tra một điều kiện cụ thể và thực thi break để thoát khỏi vòng lặp.

Ví dụ: Sinh số ngẫu nhiên liên tục cho đến khi sinh ra số 5 thì dừng.

import random  # Cần import module random

while True:  # Vòng lặp này sẽ chạy mãi mãi trừ khi có break
    num = random.randint(0, 10)  # Sinh số nguyên ngẫu nhiên từ 0 đến 10
    print('Số sinh ra có giá trị là', num)
    if num == 5:
        print("Đã tìm thấy số 5!")
        break  # Thoát khỏi vòng lặp while True
print('Đã thoát khỏi while')

Trong ví dụ này, vòng lặp sẽ tiếp tục sinh số và in ra cho đến khi num bằng 5, lúc đó break sẽ được thực thi và chương trình thoát khỏi vòng lặp.

Kỹ thuật while True:... if condition: break cung cấp một cấu trúc lặp linh hoạt. Nó cho phép kiểm tra điều kiện thoát ở bất kỳ đâu bên trong vòng lặp, không chỉ ở đầu. Điều này hữu ích khi logic để xác định việc thoát vòng lặp phức tạp hoặc cần thực hiện một số hành động trước khi kiểm tra, ví dụ như luôn nhận input từ người dùng trước, sau đó mới kiểm tra xem input đó có phải là lệnh thoát hay không.

Nhìn chung, vòng lặp while thường được ưu tiên khi số lần lặp không được xác định trước khi vòng lặp bắt đầu, mà phụ thuộc vào một điều kiện có thể thay đổi trong quá trình thực thi chương trình. Đây là điểm khác biệt cơ bản so với vòng lặp for kết hợp với range(), nơi số lần lặp thường đã được biết.

IV. Các Lỗi Lập Trình Thường Gặp (Và Cách Phòng Tránh!)

Việc viết mã không thể tránh khỏi lỗi, đặc biệt là với những người mới học. Hiểu và nhận biết các lỗi phổ biến là bước đầu tiên để gỡ lỗi (debug) hiệu quả và viết mã tốt hơn. Dưới đây là tổng hợp các lỗi thường gặp trong Python, đặc biệt liên quan đến các khái niệm cơ bản và vòng lặp, dựa trên các ví dụ minh họa.

Sự đa dạng của các lỗi được trình bày – từ lỗi cú pháp cơ bản như SyntaxError, IndentationError đến các lỗi logic hoặc runtime như TypeError, ValueError, IndexError, NameError, và cả những lỗi liên quan đến cấu trúc chương trình như ModuleNotFoundError, RecursionError – phản ánh các khía cạnh khác nhau mà người học Python cần nắm vững. Việc này cho thấy tầm quan trọng của việc không chỉ học cú pháp mà còn phải hiểu cách Python hoạt động và các vấn đề có thể phát sinh trong quá trình thực thi.

Bảng 4.1: Bảng Tổng Hợp Các Lỗi Thường Gặp

Tên Lỗi (Error Name)Mô Tả Ngắn Gọn (Brief Description)Ví Dụ Phổ Biến (Common Example Snippet)Gợi Ý Khắc Phục/Phòng Tránh (Quick Fix/Prevention Tip)
NameErrorSử dụng một biến hoặc hàm chưa được định nghĩa hoặc sai tên (Python phân biệt chữ hoa chữ thường).a = 5 c = a + b Print(a)Đảm bảo tất cả các biến đã được gán giá trị trước khi sử dụng. Kiểm tra kỹ lỗi chính tả và quy ước viết hoa/thường cho tên biến và hàm (print chứ không phải Print).
SyntaxErrorMã nguồn vi phạm các quy tắc ngữ pháp của Python. Trình thông dịch không thể hiểu được mã.s = 'Hello AIVIETNAM" if number < 10 (thiếu :) print "aivietnam.ai" (Python 2 syntax)Kiểm tra kỹ lưỡng cú pháp, đặc biệt là các dấu câu như dấu ngoặc đơn, ngoặc kép, dấu hai chấm. Đảm bảo sử dụng cú pháp print() của Python 3.
ZeroDivisionErrorCố gắng thực hiện phép chia một số cho 0.a = 5 b = 0 c = a / bTrước khi thực hiện phép chia, hãy kiểm tra xem mẫu số có bằng 0 hay không. Sử dụng câu lệnh if để xử lý trường hợp này.
TypeErrorMột phép toán hoặc hàm được áp dụng cho một đối tượng có kiểu dữ liệu không tương thích.s = 'AI' n = 5 c = s + n a_number = 5 a_string ='value' result = a_string + a_numberĐảm bảo các toán hạng trong một phép toán có kiểu dữ liệu tương thích. Nếu cần, hãy thực hiện chuyển đổi kiểu dữ liệu một cách tường minh (ví dụ: str(n) để chuyển số thành chuỗi, hoặc int(s) để chuyển chuỗi số thành số).
IndentationErrorLỗi thụt lề không đúng cách. Python sử dụng thụt lề để xác định các khối mã.a = 5 b = 6 (thụt lề không cần thiết)Tuân thủ quy tắc thụt lề của Python một cách nhất quán. Sử dụng cùng một số lượng dấu cách (thường là 4) cho mỗi cấp độ thụt lề.
ModuleNotFoundErrorPython không thể tìm thấy module mà bạn đang cố gắng import.import mymodule (nếu mymodule không tồn tại) import torch (nếu torch chưa được cài đặt)Kiểm tra xem tên module có đúng không. Đảm bảo module đã được cài đặt trong môi trường Python của bạn (ví dụ: sử dụng pip install <tên_module>).
IndexErrorCố gắng truy cập một phần tử trong chuỗi, danh sách, hoặc tuple bằng một chỉ mục nằm ngoài phạm vi hợp lệ.name = "AI" print(name[2])Kiểm tra độ dài của chuỗi/danh sách/tuple trước khi truy cập phần tử. Nhớ rằng chỉ mục bắt đầu từ 0. Chỉ mục hợp lệ cuối cùng là length - 1.
ValueErrorMột hàm nhận được một đối số có kiểu dữ liệu đúng nhưng giá trị của nó không hợp lệ cho phép toán đó.import math print(math.sqrt(-4)) value2 = int('hello')Đảm bảo giá trị của đối số nằm trong miền xác định của hàm (ví dụ: math.sqrt() yêu cầu số không âm). Kiểm tra xem chuỗi có thể được chuyển đổi thành số một cách hợp lệ trước khi dùng int() hoặc float().
RecursionErrorLỗi đệ quy xảy ra khi một hàm gọi chính nó quá nhiều lần, vượt quá giới hạn độ sâu đệ quy.def a_function(n): return a_function(n) a_function(5)Trong hàm đệ quy, đảm bảo có một "điều kiện dừng" (base case) để kết thúc việc gọi đệ quy. Kiểm tra xem điều kiện dừng có được đạt tới không.

V. Ứng Dụng Vòng Lặp: Giải Quyết Các Bài Toán Thực Tế Bằng Code

Vòng lặp không chỉ là một cấu trúc cú pháp; chúng là công cụ nền tảng để triển khai các thuật toán, cho phép chúng ta giải quyết nhiều vấn đề thực tế từ đơn giản đến phức tạp. Phần này sẽ khám phá một số ứng dụng cụ thể của vòng lặp trong việc tính toán các giá trị toán học.

A. Ước Tính Số Pi: Sức Mạnh Của Chuỗi Vô Hạn

Số Pi (π) là một hằng số toán học quan trọng, biểu thị tỷ số giữa chu vi của một đường tròn và đường kính của nó. Có nhiều chuỗi vô hạn có thể được sử dụng để ước tính giá trị của π.

  • Chuỗi Gregory-Leibniz: Một trong những chuỗi đơn giản nhất để ước tính π là chuỗi Gregory-Leibniz :

  • Để triển khai bằng vòng lặp for, chúng ta sẽ tính tổng của n số hạng đầu tiên của chuỗi, sau đó nhân với 4.

      ate_pi_gregory_leibniz(n_terms):
          pi_estimate = 0.0
          for i in range(1, n_terms + 1): # Lặp từ 1 đến n_terms
              term = ((-1)**(i + 1)) / (2*i - 1)
              pi_estimate += term
          return pi_estimate * 4
    
      # Ước tính Pi với 1000 số hạng
      n = 1000
      pi_gl = estimate_pi_gregory_leibniz(n)
      print(f'Ước tính Pi (Gregory-Leibniz, n={n}): {pi_gl}') 
      # Output mẫu: Ước tính Pi (Gregory-Leibniz, n=1000): 3.140592653839794
      # Tài liệu gốc cho thấy với n=1000 (nhưng range(1,n) tức là 999 số hạng), kết quả là 3.142593654340044 [1]
      # Sự khác biệt có thể do cách tính n trong tài liệu.
    

    Hình ảnh 5.A.1: Minh họa trực quan tổng tích lũy của chuỗi Gregory-Leibniz qua mỗi bước.

  • Chuỗi Nilakantha: Chuỗi Nilakantha hội tụ nhanh hơn chuỗi Gregory-Leibniz, nghĩa là cần ít số hạng hơn để đạt được độ chính xác tương tự:

  •   def estimate_pi_nilakantha(n_terms):
          pi_estimate = 0.0
          for i in range(n_terms): # Lặp từ 0 đến n_terms-1
              numerator = (-1)**i
              denominator = (2*i + 2) * (2*i + 3) * (2*i + 4)
              term = numerator / denominator
              pi_estimate += term
          return 3 + (4 * pi_estimate)
    
      # Ước tính Pi với 1000 số hạng
      n = 1000
      pi_nilakantha = estimate_pi_nilakantha(n)
      print(f'Ước tính Pi (Nilakantha, n={n}): {pi_nilakantha}')
      # Output mẫu từ tài liệu gốc với n=1000: 3.1415926533405423 [1]
    

    Hình ảnh 5.A.2: Minh họa trực quan tổng tích lũy của chuỗi Nilakantha qua mỗi bước.

B. Tính Căn Bậc Hai: Phương Pháp Lặp Newton

Phương pháp Newton (còn gọi là phương pháp Newton-Raphson) là một thuật toán lặp hiệu quả để tìm nghiệm gần đúng của một hàm số. Nó có thể được áp dụng để tính căn bậc hai của một số a bằng cách tìm nghiệm của phương trình x2−a=0.

Công thức lặp của phương pháp Newton để tính căn bậc hai là :

​​ Trong đó:

  • a là số cần tính căn bậc hai.

  • xn​ là ước tính của căn bậc hai ở bước lặp thứ n.

  • xn+1​ là ước tính được cải thiện ở bước lặp thứ n+1.

Các bước thực hiện:

  1. Chọn một giá trị khởi tạo x0​. Một lựa chọn phổ biến là x0​=a/2.

  2. Lặp lại việc tính xn+1​ từ xn​ bằng công thức trên cho một số lần lặp nhất định hoặc cho đến khi đạt được độ chính xác mong muốn.

    Hình 5.B.1: Lưu đồ mô tả quá trình thực thi tính căn bậc hai phương pháp lặp newton

def compute_square_root_newton(a, num_iterations):
    if a < 0:
        return "Không thể tính căn bậc hai cho số âm"

    # Khởi tạo x0
    x = float(a) / 2.0  # Sử dụng float để đảm bảo phép chia chính xác

    # Lặp num_iterations lần
    for _ in range(num_iterations):
        if x == 0: # Tránh lỗi chia cho 0 nếu a = 0 và x0 = 0
            return 0.0
        x = (x + a / x) / 2.0  # Áp dụng công thức lặp Newton
    return x

# Tính căn bậc hai của 9 với 5 lần lặp
num_a = 9
iterations = 5
sqrt_a = compute_square_root_newton(num_a, iterations)
print(f'Căn bậc hai của {num_a} (Newton, {iterations} lần lặp): {sqrt_a}') # Output: 3.0

# Tính căn bậc hai của 16 với 5 lần lặp
num_b = 16
sqrt_b = compute_square_root_newton(num_b, iterations)
print(f'Căn bậc hai của {num_b} (Newton, {iterations} lần lặp): {sqrt_b}') # Output: 4.000000000000004

Tài liệu gốc minh họa chi tiết các bước lặp để tính 9​, bắt đầu từ x0​=4.5, sau đó x1​=3.25, x2​=3.009, x3​=3.00001, cho thấy sự hội tụ nhanh chóng về giá trị 3.

C. Tính Diện Tích Hình Tròn Đơn Vị: Xấp Xỉ Bằng Tích Phân Số

Chúng ta có thể ước tính diện tích của một hình tròn đơn vị (bán kính r=1, diện tích thực là πr2=π) bằng cách sử dụng phương pháp tích phân số, cụ thể là tổng Riemann. Ý tưởng là chia diện tích dưới đường cong thành nhiều hình chữ nhật nhỏ và tính tổng diện tích của chúng.

Đối với hình tròn đơn vị x2+y2=1, phương trình của nửa trên hình tròn là y=1−x2​. Chúng ta sẽ tính diện tích dưới đường cong này từ x=−1 đến x=1, sau đó nhân đôi kết quả (hoặc tính diện tích của một phần tư hình tròn từ x=0 đến x=1 rồi nhân 4).

Công thức tổng Riemann cho diện tích ước tính là:

Trong đó:

  • f(xi​)=1−xi2​​ là chiều cao của hình chữ nhật thứ i.

  • Δxi​ là chiều rộng của hình chữ nhật thứ i.

  • n là số lượng hình chữ nhật.

import math

def compute_y(x_val):
    # Đảm bảo giá trị bên trong căn không âm
    if 1 - x_val*x_val < 0:
        return 0 # Hoặc xử lý lỗi phù hợp
    return math.sqrt(1 - x_val*x_val)

def estimate_circle_area(num_rectangles_half_circle):
    # Tính cho nửa hình tròn từ x = -1 đến x = 1
    delta_x = 2.0 / num_rectangles_half_circle # Chiều rộng của mỗi hình chữ nhật
    current_x = -1.0
    half_area_estimate = 0.0

    for _ in range(num_rectangles_half_circle):
        # Lấy chiều cao ở điểm bắt đầu của hình chữ nhật (left Riemann sum)
        y_val = compute_y(current_x)
        rectangle_area = y_val * delta_x
        half_area_estimate += rectangle_area
        current_x += delta_x

    return half_area_estimate * 2 # Nhân đôi để được diện tích cả hình tròn

# Ước tính diện tích với số lượng hình chữ nhật khác nhau
n1 = 20  # Số hình chữ nhật cho nửa hình tròn
area1 = estimate_circle_area(n1*2) # [1] dùng n cho toàn bộ, delta_x = 2/n
# [1], page 61: delta_x = 0.01, n = int(2/delta_x) = 200
# Với n=200 hình chữ nhật cho toàn bộ phạm vi [-1, 1]
# (tức là 100 cho mỗi nửa nếu chia đều, hoặc delta_x = 2/200 = 0.01)

# Theo code [1], page 61:
delta_x_doc = 0.01
n_doc = int(2.0 / delta_x_doc) # n_doc = 200
x_doc = -1.0
half_area_doc = 0.0
for _ in range(n_doc):
    y_doc = compute_y(x_doc)
    half_area_doc += delta_x_doc * y_doc
    x_doc += delta_x_doc
area_doc_n200 = half_area_doc * 2
print(f'Ước tính diện tích hình tròn (n={n_doc}, delta_x={delta_x_doc}): {area_doc_n200}')
# Output từ [1], page 61: 3.1404170317790423

# Minh họa sự cải thiện độ chính xác
# [1], page 59: n=20 (cho toàn bộ), A_est = 3.1045
# [1], page 60: n=2000 (cho toàn bộ), A_est = 3.14155

Tài liệu gốc cho thấy khi tăng số lượng hình chữ nhật n (tức là giảm Δx), ước tính diện tích sẽ ngày càng gần với giá trị thực của π. Ví dụ, với n=20, Aest​≈3.1045; với n=200, Aest​≈3.1404; và với n=2000, Aest​≈3.14155.

VI. Tổng Kết và "Bí Kíp" Bỏ Túi: Cẩm Nang Vòng Lặp Python

Qua các phần trên, chúng ta đã cùng nhau khám phá sâu rộng về hai cấu trúc vòng lặp chính trong Python: forwhile. Vòng lặp for tỏ ra cực kỳ hữu ích khi cần duyệt qua các phần tử của một iterable (như list, string, tuple, dictionary) hoặc khi số lần lặp đã được xác định trước, thường kết hợp với hàm range(). Ngược lại, vòng lặp while là lựa chọn lý tưởng khi số lần lặp phụ thuộc vào một điều kiện logic có thể thay đổi trong quá trình thực thi.

Các từ khóa điều khiển luồng như break (để thoát khỏi vòng lặp) và continue (để bỏ qua lần lặp hiện tại và chuyển sang lần tiếp theo) cung cấp sự linh hoạt cần thiết để xử lý các tình huống phức tạp hơn bên trong vòng lặp.

Việc nhận diện và hiểu rõ các lỗi thường gặp không chỉ giúp quá trình gỡ lỗi trở nên dễ dàng hơn mà còn rèn luyện tư duy lập trình cẩn thận và chính xác. Cuối cùng, các ứng dụng thực tế như ước tính số Pi, tính căn bậc hai, hay tính diện tích hình tròn đã minh họa sức mạnh của vòng lặp trong việc triển khai các thuật toán toán học và khoa học.

Để củng cố kiến thức và có một tài liệu tham khảo nhanh, "Bí Kíp Bỏ Túi" dưới đây tổng hợp những điểm cốt lõi. Một điểm đáng chú ý là "Bí Kíp Bỏ Túi" (Cheat Sheet) được cung cấp trong tài liệu gốc không chỉ tóm tắt về vòng lặp mà còn bao gồm các module hữu ích như mathrandom, cùng với danh sách các lỗi thường gặp.

Bảng 6.1: Bí Kíp Vòng Lặp Python (Python Loop Cheat Sheet)

MụcNội dung chi tiết và Ví dụ
Vòng Lặp for
Cú phápfor element in iterable: # code_inside_for
range()range(stop): 0 đến stop-1 range(start, stop): start đến stop-1 range(start, stop, step): start đến stop-1, bước nhảy step Ví dụ: for i in range(3): print(i) (Output: 0, 1, 2)
Duyệt listmy_list = ['a', 'b'] for x in my_list: print(x) (Output: a, b)
Duyệt stringmy_str = "Hi" for char in my_str: print(char) (Output: H, i)
Vòng Lặp while
Cú phápwhile condition: # code_inside_while
Ví dụ điều kiệni = 0 while i < 3: print(i) i += 1 (Output: 0, 1, 2)
while True: breaki = 0 while True: print(i) if i == 2: break i += 1 (Output: 0, 1, 2)
Từ khóa Điều Khiển
breakThoát hoàn toàn khỏi vòng lặp hiện tại.
continueBỏ qua phần còn lại của lần lặp hiện tại, chuyển sang lần lặp tiếp theo.
Module math (một số hàm)
math.sqrt(x)Căn bậc hai của x.
math.piHằng số Pi (≈3.14159).
math.fabs(x)Giá trị tuyệt đối của x.
math.factorial(x)Giai thừa của x.
math.log(x[, base])Logarit của x.
math.exp(x)ex.
math.floor(x)Làm tròn xuống số nguyên gần nhất.
math.ceil(x)Làm tròn lên số nguyên gần nhất.
Module random (một số hàm)
random.randint(a, b)Số nguyên ngẫu nhiên N sao cho a≤N≤b.
random.random()Số thực ngẫu nhiên trong khoảng [0.0,1.0).
Tóm Tắt Lỗi Thường Gặp
NameErrorSử dụng biến/hàm chưa định nghĩa.
SyntaxErrorLỗi cú pháp (vi phạm ngữ pháp Python).
ZeroDivisionErrorChia cho 0.
TypeErrorPhép toán trên kiểu dữ liệu không tương thích.
IndentationErrorThụt lề sai quy cách.
ModuleNotFoundErrorKhông tìm thấy module khi import.
IndexErrorChỉ mục ngoài phạm vi (list, string, tuple).
ValueErrorĐối số có kiểu đúng nhưng giá trị không hợp lệ.
RecursionErrorĐệ quy quá sâu (vượt giới hạn).

Nguồn tham khảo (tài liệu gốc): 2025-5_M01W01 - [v2] Loops in Python_M01W01Fri - Loops in Python_v4.pdf

0
Subscribe to my newsletter

Read articles from Tâm Fiona Trịnh directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Tâm Fiona Trịnh
Tâm Fiona Trịnh