Unicode ile kaç karakter eşleştirilebilir?


83

Unicode'daki olası tüm geçerli kombinasyonların sayımını açıklamayla birlikte istiyorum. Bir karakterin 1,2,3 veya 4 bayt olarak kodlanabileceğini biliyorum. Ayrıca, o karakterin başlangıç ​​baytı ne kadar uzun olması gerektiğini temizlese de, devam baytlarının neden kısıtlamaları olduğunu anlamıyorum.

Yanıtlar:


118

Unicode'daki olası tüm geçerli kombinasyonların sayımını açıklamayla birlikte istiyorum.

1.111.998 : 17 uçak × uçak başına 65.536 karakter - 2048 vekil - 66 karakter olmayan

UTF-8 ve UTF-32'nin teorik olarak 17 düzlemden çok daha fazlasını kodlayabildiğini, ancak aralığın UTF-16 kodlamasının sınırlamalarına göre kısıtlandığını unutmayın .

137.929 kod noktası aslında Unicode 12.1'de atanmıştır .

Ayrıca, o karakterin başlangıç ​​baytı ne kadar uzun olması gerektiğini temizlese de, devam baytlarının neden kısıtlamaları olduğunu anlamıyorum.

UTF-8'deki bu kısıtlamanın amacı, kodlamanın kendi kendini senkronize etmesini sağlamaktır .

Bir karşı örnek olarak, Çin GB 18030 kodlamasını düşünün . Orada, harf ß, 81 30 89 38rakamların kodlamasını içeren bayt dizisi olarak temsil edilir 0ve 8. Bu nedenle, bu kodlamaya özgü tuhaflık için tasarlanmamış bir dizge arama işleviniz varsa, rakam için yapılan bir arama 8harf içinde yanlış bir pozitif bulacaktır ß.

UTF-8'de, bu olamaz, çünkü baştaki baytlar ile iz baytları arasındaki örtüşmeme, daha kısa bir karakterin kodlamasının daha uzun bir karakterin kodlaması içinde asla gerçekleşemeyeceğini garanti eder.



1
ilginç bir not olarak, UTF8 tüm Unicode karakterlerini eşlemek için yalnızca 4 bayta ihtiyaç duyar, ancak UTF8 gerekirse 68 milyar karakteri destekleyebilir ve karakter başına 7 bayta kadar yer kaplar.
santiago arizti

10

Unicode , her biri 65,536 olası karakter (veya 'kod noktası') olan 17 düzlem için izin verir . Bu, toplam 1.114.112 olası karakter verir. Şu anda, bu alanın yalnızca yaklaşık% 10'u tahsis edilmiştir.

Bu kod noktalarının nasıl kodlandığına dair kesin ayrıntılar kodlamaya göre farklılık gösterir, ancak sorunuz UTF-8'i düşündüğünüz gibi görünmesini sağlar. Devam baytları üzerindeki kısıtlamaların nedeni muhtemelen bir sonraki karakterin başlangıcını bulmak kolaydır (çünkü devam karakterleri her zaman 10xxxxxx biçimindedir, ancak başlangıç ​​baytı asla bu biçimde olamaz).


Bu "düzlemlere" göre 4 baytlık bir karakterin son üç baytı bile 64 tanesini ifade edebilir. Yanlış mıyım?
Ufuk Hacıoğulları

Evet, bu senkronizasyon içindir, bkz. Cl.cam.ac.uk/~mgk25/ucs/utf-8-history.txt
ninjalj

2
Sanırım bu modası geçmiş. Artık 6 bayt kullanmıyor
Ufuk Hacıoğulları

3
@Andy: Bu mantıklı: UTF-8'in orijinal özelliği daha büyük sayılar için çalıştı. 21 bitlik sınır, kendilerini 16 bitlik karakterlere kilitleyen insanlar için bir sop idi ve bu nedenle UCS-2, UTF-16 olarak bilinen iğrençliği yarattı.
tchrist

1
@Simon: 0xFFFE == 0xFFFE ile bitsel olarak eklendiğinde, düzlem başına bu tür iki kod noktası olan 34 karakter olmayan kod noktası vardır. Ayrıca, 0x00_FDD0 .. 0x00_FDEF aralığında 31 karakter olmayan kod noktası vardır. Ayrıca, UTF-16 kusuru nedeniyle açık değişim için yasal olmayan ancak programınızda desteklenmeleri gereken vekilleri çıkarmanız gerekir.
tchrist

5

Unicode, 1.114.112 kod noktasını destekler. 1.112.064 skaler değer veren 2048 vekil kod noktası vardır. Bunlardan 66 karakter olmayan karakter vardır, bu da 1.111.998 olası kodlanmış karaktere yol açar (bir hesaplama hatası yapmadıysam).


Cevabıma bakar mısın Neden 1.112.114 kod noktası var?
Ufuk Hacıoğulları

3
Bu sayı, UTF-16 vekil sistemi kullanılarak adreslenebilen uçak sayısından gelir. 1024² BMP olmayan kod puanı veren 1024 düşük vekiliniz ve 1024 yüksek vekiliniz var. Bu artı 65.536 BMP kod noktası tam olarak 1.114.112 verir.
Philipp

2
@Philipp, ama cevabınızda '1_112_114' veriyorsunuz, ancak yorumunuzda '1_114_112'yi açıklıyorsunuz. Belki 2 ile 4'ü karıştırdınız.
Shawn Kovac 18'16

1
Bu cevap yıllardır hesaplama hatalarıyla ortalıkta dolaşıyor, ben de onu temizlemek için özgürdüm. Evet, yanıttaki 1112114 değeri bir yazım hatasıydı. Doğru değer, 0x110000'ün ondalık değeri olan 1114112'dir.
Ray Toal

1

Mecazi olarak doğru bir cevap vermek all of them,.

UTF-8 kodlamalarındaki devam baytları, kodlanmış sekizli akışının "satır gürültüsü" karşısında yeniden senkronizasyonuna izin verir. Kodlayıcının, sonraki baytın yeni bir karakter noktasının başlangıcı olduğunu bilmesi için, yalnızca 0x80 ile 0xBF arasında bir değere sahip olmayan bir baytı taraması gerekir.

Teorik olarak, bugün kullanılan kodlamalar, Unicode karakter sayısı 31 bit uzunluğa kadar olan karakterlerin ifadesine izin verir. Uygulamada, bu kodlama aslında maksimum uzunluktaki tweet'in 4.340 bitlik veriyi kodlayabildiği Twitter gibi hizmetlerde uygulanmaktadır. (140 karakter [geçerli ve geçersiz] çarpı 31 bit her biri.)


Aslında teorik olarak 31 bit ile sınırlı değil, 64 bitlik bir makinede daha da büyüyebilirsiniz. perl -le 'print ord "\x{1FFF_FFFF_FFFF}"'64 bitlik bir makinede 35184372088831 yazdırır, ancak 32 bitlik bir makinede tamsayı taşması verir. Eğer Perl programı içinde böyle büyük karakter kullanabilirsiniz, ancak utf8 olarak yazdırmak denerseniz, bir zorunlu uyarı olsun size devreden böyle olmadıkça: perl -le 'print "\x{1FFF_FFFF}"' Code point 0x1FFFFFFF is not Unicode, may not be portable at -e line 1. ######. "Gevşek utf8" ve "katı UTF-8" arasında bir fark vardır: eski kısıtlı değildir.
tchrist

1
Bugün kullanılan kodlamalar 31 bitlik skaler değerlere izin vermiyor. UTF-32, 32 bit değerlere, daha fazlası için UTF-8'e izin verir, ancak UTF-16 (Windows, OS X, Java, .NET, Python tarafından dahili olarak kullanılır ve bu nedenle en popüler kodlama şeması) bir milyon (ki bu yine de yeterli olmalıdır).
Philipp

1
"Hepsi" tam olarak doğru değil; eski kodlamalarda Unicode'da olmayan karakterler var. Örneğin, MacRoman'daki Apple logosu ve ATASCII'deki birkaç grafik karakteri. Bu karakterler böylece OTOH, bir Özel Kullanım Alanı var olabilir Unicode ile eşlenmesi; onlar standardın parçası değiller.
dan04

1
@tchrist: Python 3 UTF-16 kullanıyor; örneğin, benim sistemimde len(chr(0x10000))2 (kod birimi) vererek diyebilirim . OS X'in çekirdeği UTF-8 kullanıyor, doğru - ancak yüksek seviyeli API'ler (Cocoa vb.) UTF-16 kullanıyor.
Philipp

1
@Philip: Ben sadece Unicode desteği arzulanan çok şey bırakan Python 2 kullanıyorum. Ben bir sistem adamıyım, bu yüzden son kullanıcı krom kaplama yapmıyorum: OS X'de kullandığım tüm sistem çağrıları, çekirdeğin sizin için NFC'ye dönüştürdüğü UTF-8'i alıyor. Java'daki UTF-16 deneyimlerim kötüydü: gibi [𝒜-𝒵], içinde BMP olmayan bazı kod noktalarıyla regex parantezli bir charclass eşleşmesi deneyin ve UTF-16'yı neden bir beceriksiz olarak gördüğümü göreceksiniz. Programcıların mantıksal karakterler yerine kodlama formlarını düşünmelerini sağlamak yanlıştır.
tchrist


1

Wikipedia'ya göre Unicode 12.1 (Mayıs 2019'da piyasaya sürüldü) 137.994 farklı karakter içeriyor.


@Ufuk: Unicode'da karakterler yok. Kod noktaları vardır. Bazen bir karakter oluşturmak için birden fazla kod noktası gerektirir. Örneğin, "5̃" karakteri iki kod noktasıdır, oysa "ñ" karakteri bir veya iki kod noktası (veya daha fazla!) Olabilir. 2²¹ olası kod noktası vardır, ancak bunlardan bazıları karakter olmayan veya kısmi karakterler olarak ayrılmıştır.
tchrist

6
Unicode bir karakter kodlama standardıdır. Unicode.org/faq/basic_q.html'den ilk cevap : "Unicode evrensel karakter kodlamasıdır", dolayısıyla "Unicode bir kodlama değildir" demek yanlıştır. (Bir keresinde bu hatayı kendim yaptım.)
Philipp

1
@tchrist: Unicode standardı, aralarında "soyut karakter" ve "kodlanmış karakter" olmak üzere birden çok terimi tanımlar. Yani Unicode'un karakter içermediğini söylemek de doğru değil.
Philipp
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.