Cách đếm các chữ số của số nguyên trong Python chuẩn nhất
Cách đếm các chữ số của số nguyên trong Python chuẩn nhất

Chào bạn, để giải quyết bài toán đếm số lượng chữ số của một số nguyên nhập từ bàn phím, chúng ta cần một hướng tiếp cận xử lý được cả giá trị âm, số 0 và ngăn chặn lỗi khi người dùng nhập sai định dạng. Bài viết này sẽ hướng dẫn chi tiết cách viết code vững chắc, chuẩn kỹ thuật phần mềm dành cho sinh viên CNTT.

💡 Trả lời nhanh: Để đếm các chữ số của số nguyên n, cách Pythonic và ngắn gọn nhất là dùng len(str(abs(n))). Cách này loại bỏ dấu trừ (nếu có) bằng abs(), ép về chuỗi bằng str() và đếm độ dài bằng len(). Nếu muốn rèn luyện tư duy thuật toán, hãy dùng vòng lặp while liên tục chia nguyên n //= 10 cho đến khi n == 0 và đếm số lần lặp.


Đề bài 

Viết chương trình Python yêu cầu người dùng nhập vào một số nguyên bất kỳ từ bàn phím. Hãy đếm và in ra màn hình xem số đó bao gồm bao nhiêu chữ số.

Input: Một chuỗi ký tự đại diện cho số nguyên, được nhập từ hàm input(). Ví dụ: 12345, -987, 0.

Output: Một số nguyên dương thể hiện tổng số lượng chữ số. Ví dụ: 5, 3, 1.

Ràng buộc: – Bắt buộc xử lý đúng trường hợp người dùng nhập số âm (không đếm dấu -).

  • Bắt buộc xử lý đúng trường hợp nhập số 0 (có 1 chữ số).

  • Có cơ chế bắt lỗi (try-except) khi người dùng nhập các ký tự không phải là số (như chữ cái, ký tự đặc biệt).


Phân tích 

Bài toán đếm các chữ số của một số trong Python yêu cầu xác định tổng số lượng ký tự số cấu thành nên một số nguyên, có thể giải quyết cực kỳ gọn gàng bằng cách ép kiểu chuỗi (string) hoặc sử dụng tư duy vòng lặp toán học kinh điển. Bản chất của bài toán này không nằm ở việc tính toán giá trị, mà nằm ở việc “bóc tách” từng cấu trúc của số đó ra để đếm.

Đối với sinh viên năm 1, đây là bài tập bản lề để làm quen với việc xác thực dữ liệu đầu vào (Data Validation) và quản lý ngoại lệ (Exception Handling). Dữ liệu đầu vào từ input() luôn là kiểu chuỗi (str). Việc đầu tiên chúng ta phải làm là xác minh xem chuỗi đó có thể chuyển đổi thành số nguyên (int) hay không, để tránh chương trình bị văng lỗi đột ngột.

📌 Góc nhìn thực tế: Trong thực tế chấm bài trên các hệ thống tự động (như HackerRank, LeetCode), sinh viên năm 1 hay nhầm lẫn lớn nhất ở việc quên loại bỏ dấu trừ của số âm trước khi đếm, dẫn đến kết quả sai lệch (ví dụ đếm số -123 ra thành 4 chữ số thay vì 3).

Giả định

Chúng ta giả định bài toán chỉ yêu cầu đếm chữ số của số nguyên (Integer). Nếu người dùng nhập số thực (Float) chứa dấu chấm thập phân (ví dụ 12.34), chương trình sẽ được thiết kế để báo lỗi định dạng không hợp lệ, giúp thu hẹp phạm vi bài toán và tập trung vào logic cốt lõi. Chúng ta sẽ giải bài này theo hai hướng: dùng sức mạnh tích hợp sẵn của ngôn ngữ Python và dùng thuật toán gốc rễ.


Cách giải 1: Đếm bằng hàm len() và thao tác chuỗi 

Cách đếm chữ số bằng hàm len() kết hợp str() là giải pháp Pythonic, tận dụng khả năng ép kiểu linh hoạt của Python để giải quyết trọn vẹn logic trong một dòng code duy nhất.

Ý tưởng

Bản thân số nguyên không có khái niệm “độ dài” trong bộ nhớ máy tính. Tuy nhiên, chuỗi văn bản (String) thì có. Ý tưởng ở đây là lợi dụng tính chất đó. Chúng ta sẽ “làm sạch” số nguyên này bằng cách lấy giá trị tuyệt đối để vứt bỏ dấu trừ (nếu có). Sau khi đã có một số nguyên dương hoàn hảo, ta biến nó thành một chuỗi văn bản. Lúc này, mỗi chữ số trở thành một ký tự, và ta chỉ việc đếm số lượng ký tự bằng hàm độ dài tích hợp sẵn.

Các bước

  1. Nhận giá trị số nguyên n (đã qua bước kiểm tra hợp lệ).

  2. Dùng hàm abs(n) để chuyển n thành số dương, loại trừ dấu -.

  3. Dùng hàm str() bọc ngoài kết quả trên để ép kiểu dữ liệu từ số nguyên sang chuỗi.

  4. Cuối cùng, dùng hàm len() bọc ngoài cùng để đếm số lượng phần tử (ký tự) trong chuỗi đó. Trả về kết quả đếm được.

Minh họa tay

Giả sử người dùng nhập vào biến n = -9876.

  • Bước 1: Xử lý dấu: abs(-9876) sẽ trả về số dương 9876.

  • Bước 2: Ép kiểu chuỗi: str(9876) sẽ biến con số thành một chuỗi ký tự "9876".

  • Bước 3: Đếm độ dài: len("9876") sẽ đếm xem có bao nhiêu ký tự trong ngoặc kép. Kết quả là 4.

Đánh giá

  • Phù hợp người mới vì: Code cực kỳ ngắn gọn, dễ đọc, dễ nhớ và áp dụng ngay được triết lý “đơn giản là nhất” của Python.

  • Ưu điểm: Tốc độ viết code nhanh, hầu như không có rủi ro sinh ra lỗi logic vô hạn (infinite loop) như khi dùng vòng lặp. Xử lý số 0 tự nhiên mà không cần điều kiện phụ.

  • Nhược điểm: Tiêu tốn thêm một phần nhỏ bộ nhớ để khởi tạo một đối tượng chuỗi mới chứa các ký tự của số. Với các số cực kỳ lớn, việc ép kiểu có thể chậm hơn một chút so với toán học thuần túy.

  • Độ phức tạp: O(d) thời gian (với d là số lượng chữ số) do việc duyệt chuỗi để tạo và đếm / O(d) bộ nhớ để lưu trữ đối tượng chuỗi tạm thời.


Cách giải 2: Đếm bằng vòng lặp while 

Khác với Cách 1, cách đếm chữ số bằng vòng lặp while sử dụng thuần túy phép chia nguyên cho 10, giúp rèn luyện tư duy thuật toán chặt chẽ mà không cần cấp phát thêm bộ nhớ cho đối tượng chuỗi.

Ý tưởng

Trong hệ thập phân (cơ số 10), mỗi lần bạn chia lấy phần nguyên một số cho 10, bạn đang “chặt” mất đi chữ số ở hàng đơn vị của số đó. Ví dụ, 123 chia nguyên cho 10 còn 12. Ý tưởng thuật toán là thiết lập một biến đếm bằng 0. Chừng nào con số ban đầu còn lớn hơn 0, ta cứ liên tục “chặt” chữ số cuối cùng đi và cộng thêm 1 vào biến đếm. Quá trình này lặp lại cho tới khi số đó bị chia thành 0 thì dừng lại.

Các bước

  1. Lấy giá trị tuyệt đối của n bằng abs(n) để xử lý số âm.

  2. Kiểm tra biên: Nếu n lúc này bằng 0, lập tức trả về 1 vì vòng lặp sẽ không chạy.

  3. Khởi tạo một biến count = 0 để lưu số lượng chữ số.

  4. Mở vòng lặp while n > 0:

  5. Trong vòng lặp, gán n = n // 10 (chia lấy nguyên).

  6. Tăng count = count + 1.

  7. Khi n giảm về 0, vòng lặp kết thúc. Trả về count.

Minh họa tay

Giả sử biến n = 456. Biến đếm count = 0.

  • Vòng lặp 1: n > 0 là True. Cập nhật n = 456 // 10 = 45. Tăng count = 1.

  • Vòng lặp 2: n > 0 là True. Cập nhật n = 45 // 10 = 4. Tăng count = 2.

  • Vòng lặp 3: n > 0 là True. Cập nhật n = 4 // 10 = 0. Tăng count = 3.

  • Vòng lặp 4: n = 0, điều kiện n > 0 là False. Dừng vòng lặp.

  • Kết quả cuối cùng trả về count = 3.

Khi nào nên dùng Cách 2?

Bạn nên dùng cách giải này trong các bài thi cấu trúc dữ liệu và giải thuật khắt khe, nơi giảng viên cấm sinh viên sử dụng các hàm built-in xử lý chuỗi. Nó cũng hữu ích trong các ngôn ngữ lập trình bậc thấp hơn (như C, C++) khi việc ép số sang chuỗi tốn kém và phức tạp.

Đánh giá

  • Ưu điểm: Tối ưu hóa tuyệt đối về mặt bộ nhớ. Tư duy toán học sắc bén, dễ dàng chuyển đổi mã nguồn sang bất kỳ ngôn ngữ lập trình nào khác mà không phụ thuộc thư viện riêng.

  • Nhược điểm: Code dài hơn, phải tự xử lý thủ công trường hợp méo mó (edge case) như người dùng nhập đúng số 0. Nếu quên toán tử // mà dùng / sẽ gây sai lệch nghiêm trọng.

  • Độ phức tạp: O(d) thời gian (chia d lần cho hệ cơ số 10) / O(1) bộ nhớ vì chỉ dùng một biến đếm kiểu integer duy nhất.


So sánh nhanh 2 cách

Bảng này giúp bạn quyết định nên dùng cách nào để đếm các chữ số mà không cần đọc lại toàn bài.

Tiêu chí Cách 1: Dùng str() và len() Cách 2: Vòng lặp while
Ý tưởng cốt lõi Ép kiểu số thành văn bản rồi đếm ký tự Liên tục chia nguyên cho 10 để đếm số lần chia
Độ phức tạp O(d) thời gian, O(d) bộ nhớ O(d) thời gian, O(1) bộ nhớ
Dễ đọc / dễ hiểu ★★★★★ ★★★☆☆
Hiệu năng tối ưu bộ nhớ ★★★☆☆ ★★★★★
Phù hợp khi Làm project thực tế, cần code nhanh gọn Luyện tư duy thuật toán, đi thi môn lập trình
Không phù hợp khi Bị hạn chế dung lượng RAM siêu nhỏ (hiếm) Làm việc nhóm, cần code dễ bảo trì nhanh chóng

Code đầy đủ 

Cách 1 — Đếm bằng hàm len() và thao tác chuỗi:

# Tên biến nhất quán với phần minh họa tay
import unicodedata

def solve_bang_chuoi(n_str):
    """
    Hàm nhận vào chuỗi nhập liệu, xác thực nó là số nguyên hợp lệ,
    sau đó đếm và trả về số lượng chữ số bằng cách ép kiểu.
    """
    try:
        # Chuẩn hóa chuỗi (phòng hờ ký tự lạ) và ép kiểu int để xác thực
        n_str_clean = unicodedata.normalize('NFC', n_str).strip()
        n = int(n_str_clean) 
        
        # Logic chính: Lấy trị tuyệt đối, ép thành chuỗi, đếm độ dài
        ket_qua = len(str(abs(n)))
        return ket_qua
        
    except ValueError:
        return "Lỗi: Vui lòng chỉ nhập số nguyên hợp lệ!"

# --- TEST NHANH ---
# assert solve_bang_chuoi("-123") == 3
# assert solve_bang_chuoi("0") == 1
# print("Tất cả test pass!")
# --- Nhập liệu ---
if __name__ == "__main__":
    n_input = input("Nhập số nguyên n: ")
    print(f"Số lượng chữ số là: {solve_bang_chuoi(n_input)}")

Cách 2 — Đếm bằng vòng lặp while:

# Điểm khác với Cách 1: Sử dụng thuần toán học, cần xử lý riêng số 0.

def solve_bang_while(n_str):
    """
    Hàm nhận vào chuỗi nhập liệu, xác thực và đếm số lượng 
    chữ số bằng vòng lặp chia lấy nguyên (toán học).
    """
    try:
        n = int(n_str.strip())
        n = abs(n) # Luôn làm việc với số dương
        
        # Xử lý edge case: Nếu số bằng 0, nó có 1 chữ số
        if n == 0:
            return 1
            
        count = 0
        # Logic chính: Băm nhỏ số bằng phép chia nguyên
        while n > 0:
            n = n // 10
            count += 1
            
        return count
        
    except ValueError:
        return "Lỗi: Đầu vào không phải là số nguyên!"

# --- TEST NHANH ---
# assert solve_bang_while("456") == 3

if __name__ == "__main__":
    n_input = input("Nhập số nguyên n: ")
    print(f"Số lượng chữ số là: {solve_bang_while(n_input)}")

Ví dụ chạy thử

STT Input từ bàn phím Output trả về Giải thích chi tiết
1 159753 6 Số dương thông thường, không có khoảng trắng dư thừa, thuật toán đếm đúng 6 ký tự số.
2 -9876 4 Số âm. Nhờ hàm abs() đã biến -9876 thành 9876, do đó dấu trừ bị loại bỏ hoàn toàn, chỉ đếm 4 số.
3 0 1 Edge case (trường hợp biên). Số 0 vẫn tính là có giá trị toán học và cấu thành từ 1 chữ số duy nhất.
4 abc12 Lỗi: Đầu vào không phải là số nguyên! Khối try-except đã phát hiện lỗi ValueError khi int() không thể chuyển đổi chữ cái thành số. Ngăn chặn văng lỗi (crash).

Lỗi thường gặp 

Mỗi lỗi dưới đây phản ánh một sai lầm phổ biến trên giảng đường — bạn có thể đọc thẳng lỗi mình đang gặp phải mà không cần đọc lại từ đầu bài.

Lỗi 1: Đếm thừa cả dấu trừ của số âm

Hiện tượng: Output in ra số lượng chữ số bị dư 1 đơn vị. Ví dụ nhập -123 nhưng hệ thống báo có 4 chữ số thay vì 3.

Nguyên nhân: Vì số nguyên khi ép trực tiếp sang chuỗi mà không xử lý toán học trước, dấu trừ - sẽ được coi là một ký tự hợp lệ dạng văn bản (character). Hàm đếm độ dài sẽ đếm cả ký tự này.

Code sai:

n = -123
# output sai là: 4
print(len(str(n))) 

Code đúng:

n = -123
# output đúng là: 3
print(len(str(abs(n)))) 

Lỗi 2: Chương trình văng lỗi ValueError sập đột ngột

Hiện tượng: Output ra Traceback (most recent call last): ValueError: invalid literal for int() thay vì in ra số lượng chữ số. Chương trình bị thoát khẩn cấp.

Nguyên nhân: Vì dữ liệu nhập từ input() chứa chữ cái hoặc ký tự rác (như khoảng trắng vô tình gõ nhầm). Hàm int() trong Python rất nghiêm ngặt, nó sẽ phá hủy luồng chạy nếu giá trị bên trong không hoàn toàn là số. Giải pháp là bọc logic trong khối bảo vệ bắt lỗi.

Code sai:

# Nhập "abc" -> Sập chương trình
n = int(input("Nhập n: "))

Code đúng:

try:
    # Nhập "abc" -> Nhảy xuống except
    n = int(input("Nhập n: "))
except ValueError:
    print("Vui lòng nhập đúng số!")

Lỗi 3: Vòng lặp đếm ra 0 khi người dùng nhập số 0

Hiện tượng: Output ra 0 thay vì 1 chữ số khi người dùng cố tình nhập giá trị là 0.

Nguyên nhân: Vì điều kiện chạy vòng lặp while được viết là n > 0. Nếu ngay từ đầu n đã bằng 0, vòng lặp bị bỏ qua hoàn toàn, biến đếm không được tăng lên lần nào, giữ nguyên giá trị khởi tạo là 0. Cần phải tách số 0 ra thành một trường hợp đặc biệt riêng biệt.

Code sai:

n = 0
count = 0
while n > 0: # Không bao giờ chạy
    # ...
# output sai là: 0

Code đúng:

n = 0
if n == 0:
    count = 1
else:
    # logic while thông thường...
# output đúng là: 1

Lỗi 4: Dùng phép chia thực thay vì chia lấy nguyên

Hiện tượng: Vòng lặp chạy vô hạn (Infinite Loop) khiến chương trình bị treo cứng, quạt tản nhiệt máy tính kêu to, hoặc báo lỗi tràn bộ nhớ OverflowError.

Nguyên nhân: Vì sử dụng toán tử / (chia số thực) thay vì // (chia nguyên). Ví dụ 12 / 10 = 1.2, rồi 1.2 / 10 = 0.12… Con số sẽ không bao giờ thực sự về bằng 0 tuyệt đối, khiến biểu thức logic n > 0 mãi mãi trả về True, khóa chặt chương trình trong vòng lặp.

Code sai:

while n > 0:
    # output sai là: Vòng lặp vô tận
    n = n / 10 

Code đúng:

while n > 0:
    # output đúng là: Ép n về 0 nhanh chóng
    n = n // 10 

Lỗi 5: Áp dụng trực tiếp len() lên kiểu số nguyên

Hiện tượng: Output báo lỗi TypeError: object of type 'int' has no len() làm sập chương trình ngay lập tức.

Nguyên nhân: Vì khái niệm độ dài chỉ tồn tại ở các cấu trúc dữ liệu dạng mảng, chuỗi (sequence) như List, Tuple, String, Dictionary. Một biến số nguyên (Integer) chỉ lưu duy nhất giá trị đại lượng, không chứa các phần tử rải rác. Do đó, hàm Python tích hợp không thể biết đo độ dài của số như thế nào nếu chưa được ép kiểu thành văn bản.

Code sai:

n = 12345
# output sai là: TypeError
print(len(n))

Code đúng:

n = 12345
# output đúng là: 5
print(len(str(n)))

Câu hỏi thường gặp 

Đếm các chữ số của một số trong Python là làm gì?

Bài toán đếm các chữ số yêu cầu bạn phải tách một con số nguyên vẹn ra và xác định xem có bao nhiêu ký tự số tạo nên nó. Trong Python, công việc này thường đòi hỏi sự kết hợp giữa kỹ năng chuyển đổi định dạng (ép kiểu) hoặc sử dụng các vòng lặp chia nhỏ số nguyên để kiểm soát kết quả cuối cùng.

Tại sao bắt buộc phải ép kiểu khi nhận nhập số từ bàn phím?

Bởi vì hàm input() luôn tự động thu thập mọi thứ người dùng gõ dưới dạng một chuỗi văn bản thuần túy (str). Nếu bạn không thực hiện việc ép kiểu về số nguyên (int), bạn sẽ vô tình đếm cả những khoảng trắng vô nghĩa, hoặc không thể áp dụng các phép toán chia nguyên // bắt buộc trong cách giải thuật toán.

Làm thế nào để đếm các chữ số chẵn lẻ trong Python?

Để mở rộng bài toán đếm chữ số phân loại theo chẵn lẻ, bạn bắt buộc phải dùng vòng lặp while kết hợp phép chia lấy dư % 2. Ở mỗi lần lặp, bạn tách riêng chữ số cuối cùng ra bằng n % 10, sau đó kiểm tra nếu chia hết cho 2 thì tăng biến đếm số chẵn, ngược lại tăng biến đếm số lẻ.

Hàm len trong Python đếm các chữ số như thế nào?

Hàm len() không hề thực sự đếm con số dưới góc độ toán học; nó đơn thuần đếm số lượng ký tự Unicode tồn tại trong một biến kiểu chuỗi (str). Khi bạn ép số 123 thành "123", len() chỉ đi dọc theo mảng ký tự đó từ trái qua phải, đếm được 3 phần tử và báo kết quả, tốc độ này được tối ưu cực nhanh ở tầng ngôn ngữ C bên dưới Python.

Nên sử dụng hàm len hay dùng vòng lặp while để đếm số?

Trong môi trường làm việc chuyên nghiệp, hàm len() luôn là ưu tiên số một vì sự ngắn gọn, rõ ràng và là phong cách lập trình Pythonic chuẩn mực. Tuy nhiên, nếu bạn đang là sinh viên trong kỳ thi môn Cơ sở lập trình yêu cầu tối ưu không gian bộ nhớ tuyệt đối (độ phức tạp O(1)), việc sử dụng vòng lặp chia lấy nguyên while là bắt buộc.

Sự khác biệt cốt lõi giữa toán tử // và / khi làm bài đếm chữ số là gì?

Toán tử // thực hiện phép chia lấy phần nguyên, vứt bỏ toàn bộ phần thập phân (ví dụ 15 // 10 = 1), giúp con số nhỏ dần về 0. Ngược lại, toán tử / là phép chia số thực (Float Division), trả về kết quả số thập phân chính xác (15 / 10 = 1.5), điều này vô tình phá vỡ toàn bộ cấu trúc biến nguyên và gây ra vòng lặp vô hạn.

Tại sao code đếm số bị lỗi TypeError khi nộp trên hệ thống tự động?

Lỗi này thường xảy ra khi hệ thống tự động truyền tham số trực tiếp vào hàm của bạn dưới dạng kiểu số (int), nhưng bạn lại áp dụng nhầm hàm len() thẳng lên tham số đó thay vì ép kiểu trước. Bạn chỉ cần sửa lỗi đơn giản bằng cách dùng biểu thức bọc str(tham_so) trước khi gọi hàm đo độ dài.


Kết luận

Việc đếm các chữ số của một số không phải là bài toán đánh đố, mà là cơ hội tuyệt vời để sinh viên làm quen với luồng tư duy xử lý dữ liệu. Nếu bạn ưu tiên tốc độ triển khai và muốn code “đậm chất” Python, hãy tự tin sử dụng hàm len() kết hợp ép kiểu. Nếu bạn cần trui rèn tư duy logic để sẵn sàng đối mặt với các thuật toán phức tạp hơn sau này, vòng lặp while sẽ là một người thầy nghiêm khắc nhưng xứng đáng để chinh phục.

Các khóa học liên quan: 

Một số sản phẩm từ Python:

Một số sách lập trình Python bạn hãy tham khảo

Để lại một bình luận

Email của bạn sẽ không được hiển thị công khai. Các trường bắt buộc được đánh dấu *