Сколько символов можно сопоставить с помощью Unicode?

83

Я прошу подсчитать все возможные допустимые комбинации в Юникоде с объяснением. Я знаю, что char можно закодировать как 1,2,3 или 4 байта. Я также не понимаю, почему байты продолжения имеют ограничения, хотя начальный байт этого символа очищает, как долго он должен быть.

Уфук Хаджиогуллары
источник

Ответы:

118

Я прошу подсчитать все возможные допустимые комбинации в Юникоде с объяснением.

1111998 : 17 самолетов × 65 536 знаков на самолет - 2048 суррогатов - 66 несимволов

Обратите внимание, что UTF-8 и UTF-32 теоретически могут кодировать гораздо больше, чем 17 плоскостей, но диапазон ограничен из-за ограничений кодирования UTF-16 .

137 929 кодовых точек фактически присвоены в Unicode 12.1 .

Я также не понимаю, почему байты продолжения имеют ограничения, хотя начальный байт этого символа очищает, как долго он должен быть.

Цель этого ограничения в UTF-8 - сделать кодировку самосинхронизирующейся .

В качестве контрпримера рассмотрим китайскую кодировку GB 18030 . Там буква ßпредставлена ​​как последовательность байтов 81 30 89 38, которая содержит кодировку цифр 0и 8. Поэтому, если у вас есть функция поиска по строке, не предназначенная для этой специфической особенности кодирования, то поиск цифры 8приведет к ложному срабатыванию внутри буквы ß.

В UTF-8 этого не может произойти, потому что отсутствие перекрытия между ведущими байтами и конечными байтами гарантирует, что кодирование более короткого символа никогда не может произойти в кодировке более длинного символа.

dan04
источник
2
Статья о самосинхронизации, которую вы связали, вообще не объясняет, что такое самосинхронизация
Pacerier,
1
Интересно отметить, что UTF8 требует только 4 байта для отображения всех символов Unicode, но UTF8 может поддерживать до 68 миллиардов символов, если это когда-либо потребуется, занимая до 7 байтов на символ.
Сантьяго Аризти
10

Unicode допускает 17 плоскостей , каждый из 65 536 возможных символов (или «кодовых точек»). Это дает в общей сложности 1 114 112 возможных символов. В настоящее время выделено лишь около 10% этой площади.

Точные детали того, как эти кодовые точки кодируются, различаются в зависимости от кодировки, но ваш вопрос звучит так, как будто вы думаете о UTF-8. Причина ограничений на байты продолжения, по-видимому, заключается в том, чтобы легко найти начало следующего символа (поскольку символы продолжения всегда имеют форму 10xxxxxx, но начальный байт никогда не может иметь такую ​​форму).

Саймон Никерсон
источник
Согласно этим «плоскостям» даже последние три байта 4-байтового символа могут выражать 64 из них. Я ошибся?
Уфук Хаджиогуллары,
Да, это для синхронизации, см. Cl.cam.ac.uk/~mgk25/ucs/utf-8-history.txt
ninjalj
2
Думаю, это устарело. Он больше не использует 6 байтов
Уфук Хаджиогуллары,
3
@Andy: В этом есть смысл: исходная спецификация для UTF-8 работала для больших чисел. 21-битный предел был подачкой для людей, которые заперли себя в 16-битных символах, и поэтому UCS-2 породил мерзость, известную как UTF-16.
tchrist
1
@Simon: Есть 34 несимвольных кодовых точки, все, что при побитовом добавлении с 0xFFFE == 0xFFFE, поэтому две такие кодовые точки на плоскость. Кроме того, в диапазоне 0x00_FDD0 .. 0x00_FDEF имеется 31 кодовая точка, не являющаяся символом. Кроме того, вы должны вычесть из этого суррогаты, которые незаконны для открытого обмена из-за недостатка UTF-16, но должны поддерживаться внутри вашей программы.
tchrist
5

Unicode поддерживает 1114 112 кодовых точек. Существует 2048 суррогатных кодовых точек, дающих 1,112,064 скалярных значения. Из них 66 несимволов, что дает 1 1111 998 возможных закодированных символов (если я не сделал ошибку в расчетах).

Филипп
источник
Вы можете посмотреть мой ответ? Почему существует 1,112,114 кодовых точек?
Уфук Хаджиогуллары
3
Это число происходит от количества плоскостей, к которым можно обращаться с помощью суррогатной системы UTF-16. У вас есть 1024 младших суррогата и 1024 высоких суррогата, что дает 1024² кодовых точек, отличных от BMP. Это плюс 65 536 кодовых точек BMP дает ровно 1114 112.
Филипп
2
@Philipp, но вы даете «1_112_114» в своем ответе, но вы объясняете «1_114_112» в своем комментарии. Возможно, вы перепутали 2 и 4.
Шон Ковач
1
Этот ответ уже много лет сидит без ошибок с расчетами, поэтому я взял на себя смелость очистить его. Да, значение 1112114 в ответе было опечаткой. Правильное значение - 1114112, что является десятичным значением 0x110000.
Ray Toal
1

Для того, чтобы дать точный ответ метафорически, all of them.

Байты продолжения в кодировке UTF-8 позволяют повторно синхронизировать закодированный поток октетов перед лицом "линейного шума". Кодировщику просто нужно сканировать вперед для байта, который не имеет значения между 0x80 и 0xBF, чтобы знать, что следующий байт является началом новой точки символа.

Теоретически используемые сегодня кодировки позволяют выражать символы, длина которых в Unicode составляет до 31 бита. На практике это кодирование фактически реализовано в таких сервисах, как Twitter, где твит максимальной длины может кодировать до 4340 бит данных. (140 символов [действительный и недействительный], умноженный на 31 бит каждый.)

Энди Финкенштадт
источник
Фактически, теоретически он не ограничивается 31 битом, вы можете увеличить его на 64-битной машине. perl -le 'print ord "\x{1FFF_FFFF_FFFF}"'выводит 35184372088831 на 64-битной машине, но дает целочисленное переполнение на 32-битной машине. Вы можете использовать больше символов , как , что внутри PERL программы, но если вы пытаетесь напечатать их как utf8, вы получите обязательное предупреждение , если вы отключите такие: perl -le 'print "\x{1FFF_FFFF}"' Code point 0x1FFFFFFF is not Unicode, may not be portable at -e line 1. ######. Есть разница между «свободным utf8» и «строгим UTF-8»: первый не ограничен.
tchrist
1
Кодировки, используемые сегодня, не позволяют использовать 31-битные скалярные значения. UTF-32 допускает 32-битные значения, UTF-8 - еще больше, но UTF-16 (используемый внутри Windows, OS X, Java, .NET, Python и, следовательно, самая популярная схема кодирования) позволяет чуть более один миллион (которого все равно должно хватить).
Филипп
1
«Все они» не совсем точны; в устаревших кодировках есть символы, которых нет в Unicode. Например, логотип Apple в MacRoman и пара графических символов в ATASCII. OTOH, есть область частного использования, поэтому эти символы можно сопоставить с помощью Unicode; они просто не являются частью стандарта.
dan04
1
@tchrist: Python 3 действительно использует UTF-16; например, в моей системе я могу сказать len(chr(0x10000)), что дает 2 (единицы кода). Ядро OS X использует UTF-8, правильно, но высокоуровневые API (какао и т. Д.) Используют UTF-16.
Филипп
1
@Philip: Я использую только Python 2, поддержка Unicode которого оставляет желать лучшего. Я специалист по системам, поэтому я не использую хромирование для конечных пользователей: все системные вызовы, которые я использую в OS X, принимают UTF-8, который ядро ​​конвертирует для вас в NFC. Мой опыт работы с UTF-16 на Java был плохим: попробуйте сопоставить класс символов в квадратных скобках регулярного выражения с буквальными некоторыми кодовыми точками, отличными от BMP, в их, вроде бы [𝒜-𝒵], и вы поймете, почему я считаю раскрытие UTF-16 провалом. Ошибочно заставлять программистов мыслить в формах кодирования, а не в логических символах.
Христос
1

Юникод имеет шестнадцатеричное число 110000, что составляет 1114112

Дмитрий Плешков
источник
1

Согласно Википедии , Unicode 12.1 (выпущенный в мае 2019 года) содержит 137 994 различных символа.

orlp
источник
@Ufuk: Unicode не имеет символов. Он имеет кодовые точки. Иногда для создания одного символа требуется несколько кодовых точек. Например, символ «5̃» - это две кодовые точки, тогда как символ «ñ» может быть одной или двумя кодовыми точками (или более!). Существует 2 ¹ возможных кодовых точек, но некоторые из них зарезервированы как несимвольные или неполные символы.
tchrist
6
Юникод - это стандарт кодировки символов. Первый ответ unicode.org/faq/basic_q.html : «Юникод - это универсальная кодировка символов», поэтому утверждение, что «Юникод - это не кодировка», неверно. (Однажды я сам совершил эту ошибку.)
Филипп
1
@tchrist: стандарт Unicode определяет несколько терминов, среди которых «абстрактный символ» и «закодированный символ». Так что утверждение, что Unicode не имеет символов, также неверно.
Филипп