Mục lục bài viết

Mã hóa thông tin bằng ASCII là cách máy tính đổi mỗi ký tự thành dãy bit. Bài này lấy chuỗi “HELLO” làm ví dụ: đổi từng ký tự sang nhị phân, hexa và tính xem chuỗi chiếm bao nhiêu byte. Nếu chưa vững hệ đếm, bạn nên xem lại bài chuyển đổi giữa các hệ đếm cơ bản trước nhé.

Mục tiêu bài học:

  • Giải thích được vì sao máy tính phải mã hóa ký tự.
  • Đổi được ký tự sang nhị phân và hexa theo bảng ASCII.
  • Tính được dung lượng chuỗi khi lưu bằng ASCII và UTF-16.

1. Mã hóa thông tin bằng ASCII là gì?

Máy tính chỉ hiểu hai trạng thái 0 và 1. Muốn lưu chữ “A”, trước hết cần quy ước “A” ứng với một con số. Con số đó được đổi sang nhị phân rồi mới ghi vào bộ nhớ.

ASCII (American Standard Code for Information Interchange) là bảng quy ước như vậy. Bảng dùng 7 bit, biểu diễn được 128 ký tự. Trong đó có chữ cái tiếng Anh, chữ số, dấu câu và ký tự điều khiển. Khi lưu vào máy, mỗi ký tự chiếm 1 byte (8 bit) và bit đầu tiên luôn là 0.

Máy tính lưu trữ chữ cái, chữ số như thế nào? Mã hóa thông tin bằng ASCII và Unicode
Mã hóa thông tin bằng ASCII cho ký tự H
Nhóm ký tựMã thập phânMã hexa
Chữ số 0–948–5730–39
Chữ hoa A–Z65–9041–5A
Chữ thường a–z97–12261–7A

Mẹo: Chữ thường lớn hơn chữ hoa đúng 32 đơn vị (A = 65, a = 97). Nhớ mẹo này, bạn đổi chữ hoa sang chữ thường (và ngược lại) cực nhanh.

Muốn xem đủ 128 ký tự, bạn tra bảng mã ASCII đầy đủ trên Wikipedia (có cả mã nhị phân, thập phân, hexa). Hoặc tự chạy thử chương trình C++ in ra bảng mã ASCII ngay trên máy của bạn.

2. Unicode và UTF-16

ASCII chỉ có 128 ký tự, không có chữ “ệ” hay “ơ” của tiếng Việt. Unicode ra đời để gán mã cho mọi ký tự trên thế giới. Chữ “H” trong Unicode là U+0048, trùng với mã ASCII (48 hexa = 72 thập phân). Unicode giữ nguyên 128 mã đầu tiên của ASCII.

Unicode chỉ là bảng mã. Còn cách ghi các mã đó thành byte được gọi là kiểu mã hóa (encoding), phổ biến nhất là UTF-8 và UTF-16.

Kiểu mã hóaKý tự ASCIITiếng Việt có dấuEmoji
UTF-81 byte2–3 byte4 byte
UTF-162 byte2 byte4 byte

Lưu ý: UTF-16 không phải lúc nào cũng 2 byte mỗi ký tự. Các ký tự nằm ngoài vùng U+0000 đến U+FFFF (ví dụ emoji) sẽ tốn 4 byte.

3. Bài tập mã hóa thông tin bằng ASCII: chuỗi “HELLO”

Đề bài: Cho chuỗi ký tự “HELLO”.

  1. Chuyển từng ký tự sang mã nhị phân và hexa theo bảng mã ASCII.
  2. Tính tổng dung lượng lưu trữ của chuỗi nếu lưu bằng ASCII (8 bit/ký tự).
  3. Nếu lưu bằng Unicode UTF-16 thì cần bao nhiêu byte?

a) Mã hóa thông tin bằng ASCII: nhị phân và hexa

Đầu tiên, tra bảng ASCII để lấy mã thập phân, sau đó đổi sang hệ 2 và hệ 16. Lấy chữ “H” = 72 làm mẫu:

  • Nhị phân: 72 = 64 + 8 = 26 + 23 → 1001000. Thêm 1 số 0 vào đầu cho đủ 8 bit → 01001000.
  • Hexa: tách 8 bit thành 2 nhóm 4 bit: 0100 | 1000 → 4 | 8 → 48.

Làm tương tự với các ký tự còn lại:

Ký tựThập phânNhị phânHexa
H720100100048
E690100010145
L76010011004C
L76010011004C
O79010011114F

Viết gọn, chuỗi “HELLO” ở dạng hexa là 48 45 4C 4C 4F. Hai chữ “L” giống nhau nên mã cũng y chang.

Mẹo: Luôn viết đủ 8 bit. Viết 1001000 thay vì 01001000 là lỗi mất điểm hay gặp nhất.

b) Dung lượng khi lưu bằng ASCII

Mỗi ký tự chiếm 8 bit, chuỗi có 5 ký tự:

5 × 8 = 40 bit. Đổi sang byte: 40 : 8 = 5 byte.

c) Dung lượng khi lưu bằng UTF-16

UTF-16 dùng 2 byte (16 bit) cho mỗi ký tự trong “HELLO”. Ví dụ chữ “H” được lưu thành 00 48.

5 × 2 = 10 byte (80 bit), gấp đôi khi lưu bằng ASCII.

Lưu ý: Khi lưu file UTF-16 hoặc chạy code, bạn có thể thấy kết quả là 12 byte. Hai byte dư là BOM (Byte Order Mark – dấu thứ tự byte) đặt ở đầu file. Đề bài chỉ hỏi chuỗi ký tự nên đáp án là 10 byte.

Kiểm tra lại bằng Python

s = "HELLO"

for c in s:
    # ord() trả về mã của ký tự
    print(c, ord(c), format(ord(c), "08b"), format(ord(c), "02X"))

print("ASCII:", len(s.encode("ascii")), "byte")
print("UTF-16 không BOM:", len(s.encode("utf-16-le")), "byte")
print("UTF-16 có BOM:", len(s.encode("utf-16")), "byte")

Kết quả chạy:

H 72 01001000 48
E 69 01000101 45
L 76 01001100 4C
L 76 01001100 4C
O 79 01001111 4F
ASCII: 5 byte
UTF-16 không BOM: 10 byte
UTF-16 có BOM: 12 byte

Định dạng "08b" đổi sang nhị phân đủ 8 chữ số, còn "02X" đổi sang hexa viết hoa.

4. Bài tập tự luyện

  1. Đổi chuỗi “GocHocIT” sang nhị phân, hexa và tính dung lượng khi lưu bằng ASCII.
  2. Chuỗi “GócHọcIT” tốn bao nhiêu byte khi lưu bằng UTF-8 và UTF-16? Vì sao không lưu được bằng ASCII?
  3. Tin nhắn 160 ký tự không dấu tốn bao nhiêu byte nếu lưu bằng ASCII? Bằng UTF-16?

Tóm lại: ASCII tốn 1 byte mỗi ký tự, UTF-16 tốn 2 byte cho ký tự thông thường. Muốn ôn lại bit, byte, KB, bạn xem bài đơn vị đo thông tin trong máy tính.

Tác giả

HV Lee

500+ bài viết về lập trình, phần cứng, mạng máy tính và công nghệ. Chia sẻ kiến thức từ những gì đã học, đã dạy và đã trải nghiệm — để người học CNTT hiểu sâu hơn và làm được nhiều hơn.

Gợi ý tiếp theo

Thuật toán sắp xếp đổi chổ trực tiếp (Interchange Sort)

Học tiếp