Ile znaków można odwzorować za pomocą Unicode?

83

Proszę o policzenie wszystkich możliwych prawidłowych kombinacji w Unicode z wyjaśnieniem. Wiem, że znak można zakodować jako 1, 2, 3 lub 4 bajty. Nie rozumiem też, dlaczego bajty kontynuacji mają ograniczenia, mimo że początkowy bajt tego znaku określa, jak długo powinien być.

Ufuk Hacıoğulları
źródło

Odpowiedzi:

118

Proszę o policzenie wszystkich możliwych prawidłowych kombinacji w Unicode z wyjaśnieniem.

1 111 998 : 17 płaszczyzn × 65 536 znaków na płaszczyznę - 2048 surogatów - 66 nie-znaków

Zauważ, że UTF-8 i UTF-32 teoretycznie mogą zakodować znacznie więcej niż 17 płaszczyzn, ale zasięg jest ograniczony ze względu na ograniczenia kodowania UTF-16 .

137 929 punktów kodowych jest faktycznie przypisanych w Unicode 12.1 .

Nie rozumiem też, dlaczego bajty kontynuacji mają ograniczenia, mimo że początkowy bajt tego znaku określa, jak długo powinien być.

Celem tego ograniczenia w UTF-8 jest uczynienie kodowania samosynchronizującymi .

Dla kontrprzykładu rozważmy chińskie kodowanie GB 18030 . Tam litera ßjest reprezentowana jako sekwencja bajtów 81 30 89 38, która zawiera kodowanie cyfr 0i 8. Więc jeśli masz funkcję wyszukiwania ciągów znaków, która nie została zaprojektowana dla tego specyficznego dla kodowania dziwactwa, to wyszukiwanie cyfry 8znajdzie fałszywie dodatni wynik w literze ß.

W UTF-8 nie może się to zdarzyć, ponieważ brak nakładania się między bajtami wiodącymi i bajtami śladu gwarantuje, że kodowanie krótszego znaku nigdy nie może nastąpić w ramach kodowania dłuższego znaku.

dan04
źródło
2
Podlinkowany artykuł „
samosynchronizujący się
1
co ciekawe, UTF8 potrzebuje tylko 4 bajtów, aby zmapować wszystkie znaki Unicode, ale UTF8 może obsługiwać do 68 miliardów znaków, jeśli jest to kiedykolwiek wymagane, zajmując do 7 bajtów na znak.
santiago arizti
10

Unicode pozwala na 17 płaszczyzn , każdy z 65 536 możliwych znaków (lub „punktów kodowych”). Daje to łącznie 1114 112 możliwych znaków. Obecnie tylko około 10% tej powierzchni zostało przydzielone.

Dokładne szczegóły kodowania tych punktów kodowych różnią się w zależności od kodowania, ale twoje pytanie sprawia, że ​​brzmi to tak, jakbyś myślał o UTF-8. Przyczyną ograniczeń dotyczących bajtów kontynuacji jest przypuszczalnie, że łatwo jest znaleźć początek następnego znaku (ponieważ znaki kontynuacji mają zawsze postać 10xxxxxx, ale bajt początkowy nigdy nie może mieć tej postaci).

Simon Nickerson
źródło
Według tych "płaszczyzn" nawet ostatnie trzy bajty 4-bajtowego znaku mogą wyrazić 64 z nich. Czy się mylę?
Ufuk Hacıoğulları
Tak, to jest do synchronizacji, patrz cl.cam.ac.uk/~mgk25/ucs/utf-8-history.txt
ninjalj
2
Myślę, że to przestarzałe. Nie używa już 6 bajtów
Ufuk Hacıoğulları
3
@Andy: To ma sens: oryginalna specyfikacja UTF-8 działała dla większych liczb. Limit 21-bitowy był sopem dla ludzi, którzy zamknęli się w postaci 16-bitowych, a tym samym UCS-2 zrodził obrzydliwość znaną jako UTF-16.
tchrist
1
@Simon: Istnieją 34 nie-znakowe punkty kodowe, wszystko, co po dodaniu bitowym za pomocą 0xFFFE == 0xFFFE, więc dwa takie punkty kodowe na płaszczyznę. Ponadto w zakresie 0x00_FDD0 .. 0x00_FDEF znajduje się 31 niebazowych punktów kodowych. Dodatkowo powinieneś odjąć od tego surogaty, które nie są legalne dla otwartej wymiany ze względu na wadę UTF-16, ale muszą być obsługiwane w twoim programie.
tchrist
5

Unicode obsługuje 1114 112 punktów kodowych. Istnieje 2048 zastępczych punktów kodowych, co daje 1112 064 wartości skalarne. Spośród nich jest 66 nie-znaków, co prowadzi do 1111 998 możliwych zakodowanych znaków (chyba że popełniłem błąd w obliczeniach).

Philipp
źródło
Możesz spojrzeć na moją odpowiedź? Dlaczego istnieje 1112 114 punktów kodowych?
Ufuk Hacıoğulları
3
Liczba ta pochodzi od liczby płaszczyzn, które można adresować za pomocą systemu zastępczego UTF-16. Masz 1024 niskie surogaty i 1024 wysokie surogaty, co daje 1024² punktów kodowych innych niż BMP. To plus 65 536 punktów kodowych BMP daje dokładnie 1 114 112.
Filip
2
@Philipp, ale w swojej odpowiedzi podajesz „1_112_114”, ale w swoim komentarzu wyjaśniasz „1_114_112”. Być może pomieszałeś 2 i 4.
Shawn Kovac,
1
Ta odpowiedź od lat tkwi w błędach obliczeniowych, więc pozwoliłem sobie ją wyczyścić. Tak, wartość 1112114 w odpowiedzi była literówką. Prawidłowa wartość to 1114112, co jest wartością dziesiętną 0x110000.
Ray Toal,
1

Dać przenośni dokładną odpowiedź all of them.

Bajty kontynuacyjne w kodowaniu UTF-8 pozwalają na ponowną synchronizację zakodowanego strumienia oktetów w obliczu „szumu liniowego”. Koder, wystarczy przeszukać bajt, który nie ma wartości między 0x80 i 0xBF, aby wiedzieć, że następny bajt jest początkiem nowego punktu znaku.

Teoretycznie stosowane obecnie kodowania pozwalają na wyrażanie znaków, których liczba znaków Unicode ma długość do 31 bitów. W praktyce to kodowanie jest faktycznie wdrażane w usługach takich jak Twitter, gdzie tweet o maksymalnej długości może zakodować dane o wartości do 4340 bitów. (140 znaków [prawidłowe i nieprawidłowe], razy po 31 bitów).

Andy Finkenstadt
źródło
Faktycznie, teoretycznie nie jest to ograniczone do 31 bitów, możesz zwiększyć rozmiar na komputerze 64-bitowym. perl -le 'print ord "\x{1FFF_FFFF_FFFF}"'wypisuje 35184372088831 na maszynie 64-bitowej, ale daje przepełnienie całkowitoliczbowe na maszynie 32-bitowej. Można użyć większych znaków takich jak Perl, że wewnątrz programu, ale jeśli spróbujesz wydrukować je jako utf8, masz obowiązek ostrzeżenia, chyba że wyłączenie takie: perl -le 'print "\x{1FFF_FFFF}"' Code point 0x1FFFFFFF is not Unicode, may not be portable at -e line 1. ######. Istnieje różnica między „luźnym utf8” a „ścisłym UTF-8”: to pierwsze nie jest ograniczone.
tchrist
1
Obecnie stosowane kodowanie nie zezwala na 31-bitowe wartości skalarne. UTF-32 pozwoliłby na 32-bitowe wartości, UTF-8 na jeszcze więcej, ale UTF-16 (używany wewnętrznie przez Windows, OS X, Java, .NET, Python, a zatem najpopularniejszy schemat kodowania) pozwala na nieco ponad milion (co nadal powinno wystarczyć).
Filip
1
„Wszystkie” nie jest całkiem dokładne; istnieją znaki w starszych kodowaniach, które nie są w standardzie Unicode. Na przykład logo Apple w MacRoman i kilka znaków graficznych w ATASCII. OTOH, istnieje obszar użytku prywatnego, więc te znaki można odwzorować za pomocą Unicode; po prostu nie są częścią standardu.
dan04
1
@tchrist: Python 3 używa UTF-16; na przykład w moim systemie mogę powiedzieć len(chr(0x10000)), podając 2 (jednostki kodu). Jądro OS X używa UTF-8, poprawne - ale API wysokiego poziomu (Cocoa itp.) Używają UTF-16.
Filip
1
@Philip: Używam tylko Pythona 2, którego obsługa Unicode pozostawia wiele do życzenia. Jestem facetem od systemów, więc nie wykonuję chrome-plattingu użytkownika końcowego: wszystkie wywołania systemowe, których używam w OS X, pobierają UTF-8, który jądro konwertuje dla ciebie na NFC. Moje doświadczenia z UTF-16 w Javie były złe: spróbuj dopasować klasę znaków w nawiasach regularnych z dosłownymi punktami kodowymi nie-BMP w ich polubieniach [𝒜-𝒵], a zobaczysz, dlaczego ujawnianie UTF-16 jest nieudolnym. Błędem jest zmuszanie programistów do myślenia w formach kodowania zamiast w logicznych znakach.
tchrist
1

Unicode ma liczbę szesnastkową 110000, czyli 1114112

Dmitry Pleshkov
źródło
1

Według Wikipedii Unicode 12.1 (wydany w maju 2019 r.) Zawiera 137994 różnych znaków.

orlp
źródło
@Ufuk: Unicode nie ma znaków. Posiada punkty kodowe. Czasami potrzeba wielu punktów kodowych, aby utworzyć jeden znak. Na przykład znak „5̃” to dwa punkty kodowe, podczas gdy znak „ñ” może oznaczać jeden lub dwa punkty kodowe (lub więcej!). Istnieje 2²¹ możliwych punktów kodowych, ale niektóre z nich są zarezerwowane jako znaki niebędące znakami lub częściowe.
tchrist
6
Unicode to standard kodowania znaków. Pierwsza odpowiedź z unicode.org/faq/basic_q.html : „Unicode to uniwersalne kodowanie znaków”, więc twierdzenie, że „Unicode to nie kodowanie” jest błędne. (Kiedyś sam popełniłem ten błąd.)
Filip
1
@tchrist: Standard Unicode definiuje wiele terminów, między innymi „abstrakcyjny znak” i „zakodowany znak”. Więc powiedzenie, że Unicode nie ma znaków, również nie jest prawdą.
Filip