Unicode可以映射多少个字符?


82

我要求解释所有Unicode中所有可能有效组合的数量。我知道一个char可以编码为1,2,3或4个字节。即使该char的起始字节清除了应该多长时间,我也不明白为什么连续字节有限制。

Answers:


118

我要求解释所有Unicode中所有可能有效组合的数量。

1,111,998:17个平面×每个平面65,536个字符-2048个替代-66个非字符

请注意,理论上UTF-8和UTF-32可以编码的平面远远超过17个,但是范围受UTF-16编码限制

实际上,在Unicode 12.1中分配了137,929个代码点。

即使该char的起始字节清除了应该多长时间,我也不明白为什么连续字节有限制。

UTF-8中此限制的目的是使编码自同步

作为反例,请考虑中文GB 18030编码。在那里,字母ß表示为字节序列81 30 89 38,其中包含数字0和的编码8。因此,如果您的字符串搜索功能不是为此特定于编码的怪癖设计的,则搜索数字8将在字母中找到误报ß

在UTF-8中,这不会发生,因为前导字节和尾部字节之间的非重叠保证了较短字符的编码永远不会在较长字符的编码内发生。


2
您链接的“自我同步”文章根本没有解释什么是自我同步
Pacerier,2012年

有趣的是,UTF8只需要4个字节即可映射所有Unicode字符,但如果需要,UTF8最多可以支持680亿个字符,每个字符最多需要7个字节。
圣地亚哥亚利桑那州

10

Unicode允许17个平面,每个平面包含65,536个可能的字符(或“代码点”)。这总共提供了1,114,112个可能的字符。目前,仅分配了大约10%的空间。

这些代码点的编码方式的确切细节随编码方式的不同而不同,但是您的问题听起来似乎像是在考虑UTF-8。限制连续字节的原因大概是这样,因此很容易找到下一个字符的开头(因为连续字符始终采用10xxxxxx的形式,但是起始字节永远不能采用这种形式)。


根据这些“平面”,即使是4字节char的最后三个字节也可以表示其中的64个。我错了吗?
UfukHacıoğulları2011年

是的,那是为了同步,请参见cl.cam.ac.uk/~mgk25/ucs/utf-8-history.txt
ninjalj 2011年

2
我认为那已经过时了。它不再使用6个字节了
UfukHacıoğulları2011年

3
@Andy:这很有意义:UTF-8的原始规范适用于更大的数字。21位的限制对于将自己锁定为16位字符的人们来说是一个遗憾,因此UCS-2确实获得了被称为UTF-16的可憎性。
tchrist 2011年

1
@Simon:有34个非字符代码点,任何与0xFFFE == 0xFFFE按位相加的东西,因此每个平面有两个这样的代码点。另外,在0x00_FDD0 .. 0x00_FDEF范围内有31个非字符代码点。另外,您应该从中减去替代项,由于UTF-16缺陷,这些替代项对于开放式交换不是合法的,但必须在程序内部得到支持。
tchrist 2011年

5

Unicode支持1,114,112个代码点。有2048个代理代码点,给出1,112,064个标量值。其中有66个非字符,导致1,111,998个可能的编码字符(除非我计算错误)。


你能看我的回答吗?为什么会有1,112,114个代码点?
UfukHacıoğulları2011年

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之类的服务上实现的,其中推文的最大长度可以编码多达4340位的数据。(140个字符[有效和无效],每个乘以31位。)


实际上,理论上它不限于31位,您可以在64位计算机上更大。perl -le 'print ord "\x{1FFF_FFFF_FFFF}"'在64位计算机上打印35184372088831,但在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 2011年

1
今天使用的编码不允许使用31位标量值。UTF-32将允许使用32位值,而UTF-8则允许更多,但UTF-16(由Windows,OS X,Java,.NET,Python内部使用,因此是最受欢迎的编码方案)允许仅使用32位值。一百万(应该仍然足够)。
菲利普

1
“所有人”都不是很准确。遗留编码中的字符不是Unicode。例如,MacRoman中的Apple徽标和ATASCII中的几个图形字符。OTOH,有一个私人使用区,因此这些字符可以用Unicode映射。它们只是不属于标准的一部分。
dan04 2011年

1
@tchrist:Python 3确实使用了UTF-16;例如,在我的系统上,我可以说len(chr(0x10000)),给出2(代码单位)。OS X的内核使用正确的UTF-8,但是高级API(可可等)使用UTF-16。
菲利普

1
@Philip:我只使用Python 2,它对Unicode的支持还有很多不足之处。我是系统人员,所以我不进行最终用户镀铬:我在OS X上使用的所有syscall都使用UTF-8,内核会为您将其转换为NFC。我在Java中使用UTF-16的经历很糟糕:尝试在正则表达式括起来的charclass匹配中使用字面上的一些非BMP代码点,例如[𝒜-𝒵],您会明白为什么我发现将UTF-16暴露为缺陷。使程序员思考编码形式而不是逻辑字符是错误的。
tchrist 2011年


1

根据Wikipedia的说法,Unicode 12.1(于2019年5月发布)包含137,994个不同的字符。


@Ufuk:Unicode没有字符。它具有代码点。有时,需要多个代码点组成一个字符。例如,字符“ 5̃”是两个代码点,而字符“ñ”可以是一个或两个代码点(或更多!)。有2²¹可能的代码点,但其中一些保留为非字符或部分字符。
tchrist 2011年

6
Unicode是字符编码标准。unicode.org/faq/basic_q.html的第一个答案是:“ Unicode是通用字符编码”,因此说“ Unicode不是编码”是错误的。(我曾经自己犯过这个错误。)
菲利普(Philipp

1
@tchrist:Unicode标准定义了多个术语,其中包括“抽象字符”和“编码字符”。因此说Unicode没有字符也是不正确的。
菲利普
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.