Có bao nhiêu ký tự có thể được ánh xạ với Unicode?


82

Tôi đang yêu cầu đếm tất cả các kết hợp hợp lệ có thể có trong Unicode với lời giải thích. Tôi biết một ký tự có thể được mã hóa thành 1,2,3 hoặc 4 byte. Tôi cũng không hiểu tại sao các byte tiếp tục có các hạn chế mặc dù byte bắt đầu của char đó rõ ràng là bao lâu.

Câu trả lời:


118

Tôi đang yêu cầu đếm tất cả các kết hợp hợp lệ có thể có trong Unicode kèm theo lời giải thích.

1.111.998 : 17 mặt phẳng × 65.536 ký tự trên mỗi mặt phẳng - 2048 ký tự thay thế - 66 ký tự không

Lưu ý rằng UTF-8 và UTF-32 về mặt lý thuyết có thể mã hóa hơn 17 mặt phẳng, nhưng phạm vi bị hạn chế dựa trên những hạn chế của mã hóa UTF-16 .

137.929 điểm mã thực sự được gán trong Unicode 12.1 .

Tôi cũng không hiểu tại sao các byte tiếp tục có các hạn chế mặc dù byte bắt đầu của char đó rõ ràng là bao lâu.

Mục đích của hạn chế này trong UTF-8 là làm cho mã hóa tự đồng bộ hóa .

Đối với một ví dụ ngược lại, hãy xem xét mã hóa GB 18030 của Trung Quốc . Ở đó, chữ cái ßđược biểu diễn dưới dạng chuỗi byte 81 30 89 38, chứa bảng mã của các chữ số 08. Vì vậy, nếu bạn có một chức năng tìm kiếm chuỗi không được thiết kế cho câu hỏi mã hóa cụ thể này, thì việc tìm kiếm chữ số 8sẽ tìm thấy một dương tính giả trong chữ cái ß.

Trong UTF-8, điều này không thể xảy ra, bởi vì sự không chồng chéo giữa các byte dẫn và byte phụ đảm bảo rằng mã hóa của một ký tự ngắn hơn có thể không bao giờ xảy ra trong mã hóa của một ký tự dài hơn.


2
Các "tự đồng bộ hóa" bài viết bạn liên kết không giải thích những gì tự đồng bộ ở tất cả là
Pacerier

Cũng giống như một lưu ý thú vị, UTF8 chỉ cần 4 byte để ánh xạ tất cả các ký tự Unicode, nhưng UTF8 có thể hỗ trợ tới 68 tỷ ký tự nếu nó được yêu cầu, chiếm tới 7 byte cho mỗi ký tự.
santiago arizti

10

Unicode cho phép tạo ra 17 mặt phẳng , mỗi mặt phẳng gồm 65.536 ký tự có thể có (hoặc 'điểm mã'). Điều này cung cấp tổng cộng 1.114.112 ký tự có thể. Hiện tại, chỉ khoảng 10% diện tích này đã được phân bổ.

Các chi tiết chính xác về cách các điểm mã này được mã hóa khác với mã hóa, nhưng câu hỏi của bạn khiến nó giống như bạn đang nghĩ đến UTF-8. Lý do hạn chế đối với các byte tiếp theo có lẽ là vì vậy dễ dàng tìm thấy phần đầu của ký tự tiếp theo (vì các ký tự tiếp theo luôn có dạng 10xxxxxx, nhưng byte bắt đầu không bao giờ có thể có dạng này).


Theo những "mặt phẳng" này, ngay cả ba byte cuối cùng của một ký tự 4 byte cũng có thể thể hiện 64 trong số chúng. Tôi có lầm không?
Ufuk Hacıoğulları

Có, đó là để đồng bộ hóa, hãy xem cl.cam.ac.uk/~mgk25/ucs/utf-8-history.txt
ninjalj

2
Tôi nghĩ đó là lỗi thời. Nó không sử dụng 6 byte nữa
Ufuk Hacıoğulları

3
@Andy: Điều đó có ý nghĩa: thông số ban đầu cho UTF-8 phù hợp với những con số lớn hơn. Giới hạn 21-bit là một sự ngụy biện đối với những người đã tự nhốt mình vào các ký tự 16-bit, và do đó, UCS-2 đã bỏ qua sự ghê tởm được gọi là UTF-16.
tchrist

1
@Simon: Có 34 điểm mã không ký tự, bất cứ thứ gì khi được cộng theo bit bằng 0xFFFE == 0xFFFE, vì vậy hai điểm mã như vậy trên mỗi mặt phẳng. Ngoài ra, có 31 điểm mã không ký tự trong phạm vi 0x00_FDD0 .. 0x00_FDEF. Thêm vào đó, bạn nên loại trừ việc thay thế, không hợp pháp cho trao đổi mở do lỗ hổng UTF-16, nhưng phải được hỗ trợ trong chương trình của bạn.
tchrist

5

Unicode hỗ trợ 1.114.112 điểm mã. Có 2048 điểm mã thay thế, cho 1.112.064 giá trị vô hướng. Trong số này, có 66 ký tự không phải ký tự, dẫn đến 1.111.998 ký tự có thể được mã hóa (trừ khi tôi mắc lỗi tính toán).


Bạn có thể nhìn vào câu trả lời của tôi? Tại sao lại có 1.112.114 điểm mã?
Ufuk Hacıoğulları

3
Con số này đến từ số lượng mặt phẳng có thể xác định được bằng cách sử dụng hệ thống thay thế UTF-16. Bạn có 1024 đại diện thay thế thấp và 1024 đại diện thay thế cao, cho 1024² điểm mã không phải BMP. Điều này cộng với 65.536 điểm mã BMP cho chính xác 1.114.112.
Philipp

2
@Philipp, nhưng bạn đưa ra '1_112_114' trong câu trả lời của mình, nhưng bạn giải thích '1_114_112' trong nhận xét của mình. Có lẽ bạn trộn lên 2 và 4.
Shawn Kovac

1
Câu trả lời này đã được đặt xung quanh các lỗi tính toán trong nhiều năm nay, vì vậy tôi đã tự do để làm sạch nó. Có, giá trị 1112114 trong câu trả lời là lỗi đánh máy. Giá trị đúng là 1114112, là giá trị thập phân của 0x110000.
Ray Toal

1

Để đưa ra một câu trả lời chính xác về mặt ẩn dụ all of them,.

Các byte tiếp tục trong mã hóa UTF-8 cho phép đồng bộ hóa lại luồng octet được mã hóa khi đối mặt với "nhiễu dòng". Bộ mã hóa, chỉ cần quét chuyển tiếp một byte không có giá trị từ 0x80 đến 0xBF để biết rằng byte tiếp theo là điểm bắt đầu của một điểm ký tự mới.

Về lý thuyết, các bảng mã được sử dụng ngày nay cho phép biểu thị các ký tự có số ký tự Unicode có độ dài lên đến 31 bit. Trên thực tế, mã hóa này thực sự được triển khai trên các dịch vụ như Twitter, nơi mà tweet có độ dài tối đa có thể mã hóa dữ liệu có giá trị lên tới 4.340 bit. (140 ký tự [hợp lệ và không hợp lệ], mỗi ký tự 31 bit.)


Thực tế, trên lý thuyết, nó không bị giới hạn ở 31 bit, bạn có thể mở rộng hơn trên máy 64 bit. perl -le 'print ord "\x{1FFF_FFFF_FFFF}"'in ra 35184372088831 trên máy 64 bit, nhưng gây tràn số nguyên trên máy 32 bit. Bạn có thể sử dụng ký tự lớn hơn như thế trong chương trình perl của bạn, nhưng nếu bạn cố gắng in chúng ra như là utf8, bạn nhận được một cảnh báo bắt buộc, trừ khi bạn vô hiệu hóa như: perl -le 'print "\x{1FFF_FFFF}"' Code point 0x1FFFFFFF is not Unicode, may not be portable at -e line 1. ######. Có sự khác biệt giữa "utf8 lỏng lẻo" và "UTF-8 nghiêm ngặt": cái trước không bị hạn chế.
tchrist

1
Các mã hóa được sử dụng ngày nay không cho phép các giá trị vô hướng 31 bit. UTF-32 sẽ cho phép các giá trị 32 bit, UTF-8 cho nhiều hơn nữa, nhưng UTF-16 (được sử dụng nội bộ bởi Windows, OS X, Java, .NET, Python và do đó là lược đồ mã hóa phổ biến nhất) chỉ cho phép hơn một triệu (vẫn đủ).
Philipp

1
"Tất cả chúng" không hoàn toàn chính xác; có các ký tự trong bảng mã kế thừa không có trong Unicode. Ví dụ: logo Apple trong MacRoman và một vài ký tự đồ họa trong ATASCII. OTOH, có một Khu vực Sử dụng Riêng, vì vậy những ký tự này có thể được ánh xạ bằng Unicode; chúng không phải là một phần của tiêu chuẩn.
dan04

1
@tchrist: Python 3 sử dụng UTF-16; ví dụ, trên hệ thống của tôi, tôi có thể nói len(chr(0x10000)), đưa ra 2 (đơn vị mã). Nhân của OS X sử dụng UTF-8, đúng - nhưng các API cấp cao (Cacao, v.v.) sử dụng UTF-16.
Philipp

1
@Philip: Tôi chỉ sử dụng Python 2, có hỗ trợ Unicode để lại rất nhiều điều mong muốn. Tôi là một người thích hệ thống, vì vậy tôi không thực hiện chrome-platting của người dùng cuối: tất cả các cuộc gọi hệ thống mà tôi sử dụng trên OS X đều lấy UTF-8, hạt nhân chuyển đổi thành NFC cho bạn. Trải nghiệm UTF-16 của tôi trong Java rất tệ: hãy thử đối sánh lớp biểu đồ có dấu ngoặc vuông regex với một số mã điểm không phải BMP theo nghĩa đen trong chúng, chẳng hạn như [𝒜-𝒵], và bạn sẽ thấy tại sao tôi thấy UTF-16 là một botch. Thật sai lầm khi khiến các lập trình viên phải suy nghĩ trong các biểu mẫu mã hóa thay vì các ký tự logic.
tchrist


1

Theo Wikipedia , Unicode 12.1 (phát hành vào tháng 5 năm 2019) chứa 137.994 ký tự riêng biệt.


@Ufuk: Unicode không có ký tự. Nó có điểm mã. Đôi khi nó yêu cầu nhiều điểm mã để tạo nên một ký tự. Ví dụ, ký tự "5̃" là hai điểm mã, trong khi ký tự "ñ" có thể là một hoặc hai điểm mã (hoặc nhiều hơn!). Có thể có 2²¹ điểm mã, nhưng một số trong số đó được dành riêng dưới dạng ký tự không phải ký tự hoặc ký tự một phần.
tchrist

6
Unicode là một tiêu chuẩn mã hóa ký tự. Câu trả lời đầu tiên từ unicode.org/faq/basic_q.html : “Unicode là bảng mã ký tự chung”, vì vậy nói rằng “Unicode không phải là một bảng mã” là sai. (Tôi đã từng tự mình mắc sai lầm đó.)
Philipp

1
@tchrist: Tiêu chuẩn Unicode xác định nhiều thuật ngữ, trong số đó có “ký tự trừu tượng” và “ký tự được mã hóa”. Vì vậy, nói rằng Unicode không có ký tự cũng không đúng.
Philipp
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.