Скільки символів можна зіставити за допомогою Unicode?


83

Я прошу підрахувати всі можливі допустимі комбінації в Unicode з поясненнями. Я знаю, що символ може бути закодований як 1,2,3 або 4 байти. Я також не розумію, чому в байтах продовження є обмеження, хоча початковий байт цього символу очищає, як довго він повинен бути.

Відповіді:


118

Я прошу підрахувати всі можливі допустимі комбінації в Unicode з поясненнями.

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

Зверніть увагу, що UTF-8 та UTF-32 теоретично можуть кодувати набагато більше 17 площин, але дальність дії обмежена на основі обмежень кодування UTF-16 .

В Unicode 12.1 насправді призначено 137 929 кодових точок .

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

Метою цього обмеження в UTF-8 є зробити кодування самосинхронізуючимся .

Для контрприкладу розглянемо китайське кодування GB 18030 . Там буква ßпредставлена ​​у вигляді послідовності байтів 81 30 89 38, яка містить кодування цифр 0та 8. Отже, якщо у вас є функція пошуку рядків, не розроблена для цієї специфічної кодування вигадки, тоді пошук цифри 8виявить помилковий позитивний результат у межах листа ß.

У UTF-8 цього не може статися, оскільки неперекриття між байтами ведучого та байтами сліду гарантує, що кодування коротшого символу ніколи не може відбутися в кодуванні довшого символу.


2
У статті про "самосинхронізацію", яку ви зв’язали, не пояснюється, що взагалі є
самосинхронізацією

1
як цікаве примітка, UTF8 потребує лише 4 байти, щоб зіставити всі символи Unicode, але UTF8 може підтримувати до 68 мільярдів символів, якщо це колись буде потрібно, займаючи до 7 байт на символ.
santiago arizti

10

Unicode дозволяє використовувати 17 літаків , кожен з 65 536 можливих символів (або „кодових точок“). Це дає в цілому 1114112 можливих символів. В даний час виділено лише близько 10% цього простору.

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


Згідно з цими "площинами", навіть останні три байти 4-байтового символу могли виразити 64 з них. Я помиляюся?
Ufuk Hacıoğulları

Так, це стосується синхронізації, див. Cl.cam.ac.uk/~mgk25/ucs/utf-8-history.txt
ninjalj

2
Я думаю, це застаріло. Він більше не використовує 6 байтів
Уфук Хаджогуллар,

3
@Andy: Це має сенс: оригінальні специфікації для UTF-8 працювали для більших номерів. Обмеження в 21 біт було для власників, які замикалися в 16-бітових символах, і таким чином UCS-2 породив гидоту, відому як UTF-16.
christ

1
@Simon: Є 34 нехарактерні кодові точки, все, що при розрядному додаванні з 0xFFFE == 0xFFFE, отже, дві такі кодові точки на площину. Також існує 31 не символьна кодова точка в діапазоні 0x00_FDD0 .. 0x00_FDEF. Плюс вам слід відняти із цього сурогати, які не є законними для відкритого обміну через недолік UTF-16, але їх слід підтримувати у вашій програмі.
christ

5

Юнікод підтримує 1114112 кодових точок. Існує 2048 сурогатних кодів, що дає 1112 064 скалярних значень. З них 66 символів, що призводить до 1111 998 можливих закодованих символів (якщо я не зробив помилку підрахунку).


Чи можете ви подивитися на мою відповідь? Чому існує 1112114 кодових точок?
Ufuk Hacıoğulları

3
Це число походить від кількості літаків, які можна адресувати за допомогою сурогатної системи UTF-16. У вас є 1024 низьких сурогатів і 1024 високих сурогатів, що дає 1024² кодових балів, не пов’язаних з BMP. Це плюс 65 536 кодових очок BMP дає рівно 1,114,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, де твіт максимальної довжини може кодувати дані на суму до 4 340 біт. (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": перший не обмежений.
christ

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 є невдалою справою. Помилково змушувати програмістів думати в формах кодування, а не в логічних символах.
christ


1

Згідно з Вікіпедією , Unicode 12.1 (випущений у травні 2019 року) містить 137 994 різних символів.


@Ufuk: Unicode не має символів. Він має кодові точки. Іноді для складання одного символу потрібно кілька кодових точок. Наприклад, символ "5̃" - це дві кодові точки, тоді як символ "ñ" може бути однією або двома кодовими точками (або більше!). Існує 2²¹ можливих кодових точок, але деякі з них зарезервовані як несимвольні або часткові символи.
christ

6
Unicode - стандарт кодування символів. Перша відповідь від unicode.org/faq/basic_q.html : "Unicode - це універсальне кодування символів", тому твердження, що "Unicode - це не кодування", є неправильним. (Я колись сам зробив цю помилку.)
Філіпп,

1
@tchrist: Стандарт Unicode визначає кілька термінів, серед них "абстрактний символ" і "закодований символ". Тож твердження про те, що Unicode не має символів, також не відповідає дійсності.
Філіпп
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.