- Trong ASCII,
Z được đặt ở 90 còn a ở 97; nhờ 6 ký tự nằm giữa chúng mà chênh lệch mã giữa chữ hoa và chữ thường khớp đúng 32
- 32 là
2^5, nên các cặp chữ hoa/chữ thường tương ứng như A 65 và a 97 luôn chỉ khác nhau đúng một bit 00100000
- Nhờ cách sắp xếp này, có thể chuyển thành chữ hoa bằng cách AND với giá trị đảo bit của
32, chuyển thành chữ thường bằng OR với 32, và đảo hoa/thường bằng XOR với 32
- Thứ tự chữ cái có thể lấy bằng cách AND mã ký tự với
31 để chỉ giữ lại 5 bit thấp; khi đó A/a là 1 và Z/z là 26
- ASCII là một bộ mã ký tự đời đầu chỉ biểu diễn được 128 code point bằng 7 bit; 128 code point đầu tiên của Unicode hiện nay trùng với ASCII
Cách sắp xếp ASCII và khoảng chênh 32
- Trong bảng ASCII, giá trị mã của chữ hoa
Z là 90, còn chữ thường a không nằm ngay sau đó mà được đặt ở 97
- Ở giữa có 6 ký tự:
[ \ ] ^ _ `
- Bảng chữ cái tiếng Anh có 26 chữ; cộng thêm 6 ký tự này thì
26 + 6 = 32
32 là giá trị tương ứng với 2^5, nên quan hệ tương ứng giữa chữ hoa và chữ thường được căn chỉnh thành khác nhau ở đúng một bit cụ thể
- Ví dụ,
A là 65 đồng thời là 01000001, còn a là 97 đồng thời là 01100001; chênh lệch giữa hai giá trị là 32
Quan hệ giữa ASCII và Unicode
- ASCII là một trong những cách mã hóa ký tự đời đầu, chỉ dùng 7 bit để biểu diễn
2^7 = 128 code point
- 128 code point là không đủ để chứa mọi ký tự con người sử dụng, đặc biệt là với các ngôn ngữ có hàng chục nghìn ký tự như tiếng Trung
- Ngày nay, Unicode được dùng làm bộ ký tự tiêu chuẩn, với nhiều kiểu mã hóa như UTF-8 và UTF-16
- 128 code point đầu tiên của Unicode trùng với ASCII
Bit thứ 5 phân biệt chữ hoa và chữ thường
- Khi so sánh ở dạng nhị phân, chữ thường và chữ hoa tương ứng luôn chỉ thay đổi ở bit ứng với
32
65 = 01000001 = A
97 = 01100001 = a
66 = 01000010 = B
98 = 01100010 = b
67 = 01000011 = C
99 = 01100011 = c
32 trong hệ nhị phân là 00100000, và chính bit này tạo ra sự khác biệt giữa chữ hoa và chữ thường
- Cách sắp xếp bảng chữ cái trong ASCII giúp việc chuyển đổi hoa/thường bằng phép toán bit trở nên dễ dàng
Xử lý chữ hoa và chữ thường bằng phép toán bit
-
Chuyển sang chữ hoa
- Để biến một ký tự thành chữ hoa, thực hiện phép AND bit với giá trị đảo bit của
32
0 1 1 0 0 0 0 1 (97 = 'a')
& 1 1 0 1 1 1 1 1 (mask)
-------------------
0 1 0 0 0 0 0 1 (65 = 'A')
- Áp dụng cho
a thì 97 đổi thành 65, tức A
- Nếu áp dụng cùng phép toán đó cho
A vốn đã là chữ hoa thì vẫn giữ nguyên A
-
Chuyển sang chữ thường
- Để biến một ký tự thành chữ thường, thực hiện phép OR bit với
32
0 1 0 0 0 0 0 1 (65 = 'A')
| 0 0 1 0 0 0 0 0 (32)
-------------------
0 1 1 0 0 0 0 1 (97 = 'a')
- Áp dụng cho
A thì 65 đổi thành 97, tức a
- Nếu áp dụng cùng phép toán đó cho
a vốn đã là chữ thường thì vẫn giữ nguyên a
-
Đảo hoa/thường
- Để đảo chữ hoa/thường, thực hiện phép XOR bit với
32
0 1 1 0 0 0 0 1 (97 = 'a')
^ 0 0 1 0 0 0 0 0 (32)
-------------------
0 1 0 0 0 0 0 1 (65 = 'A')
0 1 0 0 0 0 0 1 (65 = 'A')
^ 0 0 1 0 0 0 0 0 (32)
-------------------
0 1 1 0 0 0 0 1 (97 = 'a')
a sẽ thành A, còn A sẽ thành a
Lấy thứ tự chữ cái bằng 5 bit thấp
- Có thể lấy thứ tự chữ cái bằng cách thực hiện phép AND bit giữa mã ký tự và
31
0 1 0 0 0 0 0 1 (65 = 'A')
& 0 0 0 1 1 1 1 1 (31)
-------------------
0 0 0 0 0 0 0 1 (1)
0 1 1 1 1 0 1 0 (122 = 'z')
& 0 0 0 1 1 1 1 1 (31)
-------------------
0 0 0 1 1 0 1 0 (26)
31 trong hệ nhị phân là 00011111, nên nó xóa các bit phía trước và chỉ giữ lại 5 bit thấp
- Trong ASCII, 5 bit thấp của các chữ cái khớp đúng với vị trí của chúng trong bảng chữ cái
A/a kết thúc bằng 00001 nên cho ra 1, B/b kết thúc bằng 00010 nên cho ra 2, còn Z/z kết thúc bằng 11010 nên cho ra 26
- Trong mã ký tự ASCII,
c & 31 tương đương với c % 32
- Vì
32 là lũy thừa của 2, nên việc mask bằng 31 sẽ loại bỏ các nhóm theo đơn vị 32 và chỉ giữ lại phần còn dư
'A' = 65 → 65 % 32 = 1
'B' = 66 → 66 % 32 = 2
...
'Z' = 90 → 90 % 32 = 26
'a' = 97 → 97 % 32 = 1
'b' = 98 → 98 % 32 = 2
...
'z' = 122 → 122 % 32 = 26
1 bình luận
Ý kiến trên Lobste.rs
Giải thích cũng ổn, nhưng tôi cảm thấy bên https://garbagecollected.org/2017/01/31/four-column-ascii/ giải thích hay hơn.
Không chỉ riêng Shift mà Ctrl cũng liên quan. Ví dụ, Tab là Ctrl-I, vì I là
1001001và Ctrl che bit đầu tiên để còn lại0001001của TabNếu dùng logic cơ điện thay vì logic điện tử như các hãng sản xuất trong thập niên 1960, thì bit paired keyboard sẽ dễ triển khai hơn nhiều.
Phím Shift chỉ cần bật/tắt một bit trong ký tự ASCII. Ngày nay mọi bàn phím đều có CPU đa dụng và phần logic gần như miễn phí, nhưng vào thời máy tính đa dụng còn to bằng cả một căn phòng thì những cách giải như vậy đắt đỏ hơn rất nhiều
Bài viết đưa ra động cơ của cách sắp xếp ASCII là có thể triển khai chuyển đổi chữ hoa/chữ thường một cách hiệu quả bằng phép toán bit, nhưng giá trị đó có thể có ý nghĩa về mặt lịch sử chứ với hiện đại thì khá mỏng.
Chuyển đổi
a→Achỉ đúng với văn bản đơn giản, và dù ISO-8859-1 hay Unicode có mở rộng phần nào cách bố trí này cho các ký tự nhưü,ç, thì việc đổi hoa/thường vẫn phụ thuộc vào địa phương, ngữ cảnh và thời điểm. Cặp hoa/thường đúng củaßhayïbị chi phối bởi ngôn ngữ, cơ quan quản lý, vùng sử dụng và thời đại.Unicode cung cấp các bảng ánh xạ và gập chữ hoa/thường như https://www.unicode.org/charts/case/ để đưa ra câu trả lời khá gần trong các trường hợp phổ biến, nhưng đây là vấn đề có sự can thiệp của chính sách con người nên độ phức tạp trên thực tế gần như vô hạn, và để làm đúng có thể cần phần mềm tùy biến.
Ngày nay, nếu không thể bảo đảm dữ liệu bị giới hạn trong 2⁷ code point đầu của Unicode, thì offset
0b0010_0000rất dễ thất bại, và chắc chắn phải đi qua đường mã đắt hơn một phép toán trên một bit. Ngay cả trong CPython,''.uppercũng đi qua đường nhanh ASCII củaunicode_upper{,_impl}, nhưng trên thực tế vẫn phải qua nhánh, hàm inline, truy cập struct, nhiều hàm và hàm, macro, rồi thực hiện tra cứu bảng.Triển khai
''.uppertrong các ngôn ngữ hiện đại nhìn chung sẽ có độ phức tạp tương tự, và dù compiler có tối ưu thì cách tiếp cận hiện đại dường như vẫn không thể rẻ bằng một phép toán trên một bit. Lợi ích của thiết kế này có lẽ chỉ nổi bật trong phần mềm tùy biến kiểu làm phép toán số học trênnumpy.ndarrayvớidtype=uint8chứa dữ liệu nhị phân thô hoặc dữ liệu Unicode chỉ gồm các code point dưới 2⁷.Điều tôi thắc mắc là thế này: nếu giả sử động cơ duy nhất của lựa chọn thiết kế này đúng như bài viết nói, thì ngay cả khi đó cũng đã có phương án thay thế là bảng tra cứu 128 byte; vậy trong lịch sử điện toán, giai đoạn nào phép toán trên một bit lại hiệu quả hơn hoặc khả thi hơn tra cứu bảng 128 byte?
Một lựa chọn thiết kế ở một thời điểm nào đó cố định hình dạng của thứ gì đó dựa trên những giả định sau này sẽ vỡ, khiến việc mở rộng về sau trở nên khó hoặc bất khả thi. Những bài viết gần đây về IPv6 cũng cho thấy các lựa chọn từng đúng đắn với IPv4 và IPv6 vào thời điểm đó nay đã trở thành gánh nặng khổng lồ.
Nhìn theo hướng thiện chí, những lựa chọn như vậy hẳn đã được đưa ra sau khi cân nhắc rủi ro và lợi ích. Kiểu như: “nếu đổi một ký tự sang chữ hoa chỉ cần một phép toán trên một bit thì sẽ nhanh hơn nhiều, vậy đáng để chấp nhận rủi ro rằng một ngày nào đó nó sẽ hỏng khi xuất hiện người dùng tiếng Nhật”.
Từ góc nhìn hiện đại, lựa chọn của năm 1976 làm cuộc sống năm 2026 khó khăn hơn, nhưng nếu bạn chưa từng có máy tính vào năm 1976 thì bạn không nhận được lợi ích nào mà chỉ còn lại nhược điểm. Tạm gác sự ích kỷ đó sang một bên, tôi tự hỏi làm sao có thể dự đoán tốt hơn tính bền vững của những lựa chọn kiểu này khi viết phần mềm mà mình mong vẫn còn phổ biến sau 20 năm nữa.
tolowernhanh ở mức bit vẫn còn hữu ích. https://dotat.at/@/2022-06-27-tolower-swar.htmlÍt nhất thì trong ASCII, các chữ cái vẫn nằm liên tiếp nhau. EBCDIC có khoảng cách là
0x40(64), và nếu so với ASCII thì nó giống hai hàng 9 ký tự và một hàng 8 ký tự xếp chồng lên nhau theo chiều dọc.https://en.wikipedia.org/wiki/EBCDIC
Còn về mã 5 bit http://www.quadibloc.com/crypto/images/tele38.gif và, nếu tôi nhớ không nhầm, một số thiết bị ngoại vi CDC dùng mã 6 bit chứa đầy ký tự điều khiển chuyển trang, thì tốt hơn là đừng nói đến.
Điều này làm tôi nhớ đến việc nickname IRC không phân biệt hoa thường theo ASCII, nên
foo{giống vớifoo[vàbar|giống vớibar\.Tôi cũng sẽ không ngạc nhiên nếu một số client đến giờ vẫn còn bị chuyện này làm rối