ChatGPT解决这个技术问题 Extra ChatGPT

Unicode 可以映射多少个字符?

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


B
Boris Verkhovskiy

我要求计算 Unicode 中所有可能的有效组合并附上解释。

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

请注意,UTF-8 和 UTF-32 理论上可以编码超过 17 个平面,但范围基于 limitations of the UTF-16 encoding 受到限制。

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

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

UTF-8 中此限制的目的是使编码为 self-synchronizing

举个反例,考虑中文的GB 18030 encoding。在那里,字母 ß 表示为字节序列 81 30 89 38,其中包含数字 08 的编码。因此,如果您的字符串搜索功能不是针对这种特定于编码的怪癖而设计的,那么对数字 8 的搜索将在字母 ß 中发现误报。

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


您链接的“自同步”文章根本没有解释什么是自同步
有趣的是,UTF8 只需要 4 个字节即可映射所有 Unicode 字符,但如果需要,UTF8 最多可以支持 680 亿个字符,每个字符最多占用 7 个字节。
S
Simon Nickerson

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

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


根据这些“平面”,即使是 4 字节字符的最后三个字节也可以表示其中的 64 个。我错了吗?
是的,这是为了同步,请参阅 cl.cam.ac.uk/~mgk25/ucs/utf-8-history.txt
我认为这已经过时了。它不再使用 6 个字节
@Andy:这是有道理的:UTF-8 的原始规范适用于更大的数字。 21 位限制对那些将自己锁定在 16 位字符中的人来说是一个安慰,因此 UCS-2 产生了被称为 UTF-16 的可憎之物。
@Simon:有34个非字符代码点,当按位添加0xFFFE == 0xFFFE时,每个平面有两个这样的代码点。此外,在 0x00_FDD0 .. 0x00_FDEF 范围内有 31 个非字符代码点。另外,您应该从中减去代理项,由于 UTF-16 缺陷,这些代理项对于开放交换是不合法的,但必须在您的程序内部得到支持。
R
Ray Toal

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


你能看看我的回答吗?为什么有 1,112,114 个代码点?
此数字来自使用 UTF-16 代理系统可寻址的平面数。您有 1024 个低代理和 1024 个高代理,提供 1024² 个非 BMP 代码点。这加上 65,536 个 BMP 代码点正好得到 1,114,112。
@Philipp,但是您在回答中给出了“1_112_114”,但您在评论中解释了“1_114_112”。也许你把 2 和 4 弄混了。
这个答案多年来一直存在计算错误,所以我冒昧地清理它。是的,答案中的值 1112114 是一个错字。正确的值为 1114112,即 0x110000 的十进制值。
A
Andy Finkenstadt

为了给出一个隐喻准确的答案,all of them

UTF-8 编码中的连续字节允许在面对“线路噪声”时重新同步编码的八位字节流。编码器只需要向前扫描一个在 0x80 和 0xBF 之间没有值的字节,就知道下一个字节是新字符点的开始。

从理论上讲,今天使用的编码允许表达 Unicode 字符数最多为 31 位的字符。实际上,这种编码实际上是在 Twitter 等服务上实现的,其中最大长度的推文可以编码多达 4,340 位的数据。 (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”是有区别的:前者不受限制。
今天使用的编码不允许 31 位标量值。 UTF-32 将允许 32 位值,UTF-8 甚至更多,但 UTF-16(由 Windows、OS X、Java、.NET、Python 内部使用,因此是最流行的编码方案)允许超过一百万(这应该足够了)。
“所有这些”不是很准确;传统编码中的某些字符不在 Unicode 中。例如,MacRoman 中的 Apple 标志,以及 ATASCII 中的几个图形字符。 OTOH,有一个私人使用区,所以这些字符可以用 Unicode 映射;它们只是不是标准的一部分。
@tchrist:Python 3 确实使用 UTF-16;例如,在我的系统上,我可以说 len(chr(0x10000)),给出 2(代码单元)。 OS X 的内核使用 UTF-8,没错,但高级 API(Cocoa 等)使用 UTF-16。
@Philip:我只使用 Python 2,它的 Unicode 支持还有很多不足之处。我是系统专家,所以我不做最终用户镀铬:我在 OS X 上使用的所有系统调用都采用 UTF-8,内核会为你转换成 NFC。我在 Java 中的 UTF-16 体验一直很糟糕:尝试使用正则表达式括号字符类匹配其中的一些非 BMP 代码点,例如 [𝒜-𝒵],您就会明白为什么我发现暴露 UTF-16 是一个烂问题。让程序员思考编码形式而不是逻辑字符是错误的。
D
Dmitry Pleshkov

Unicode 的十六进制数是 110000,即 1114112


B
Boris Verkhovskiy

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


@Ufuk:Unicode 没有字符。它有代码点。有时它需要多个代码点来组成一个字符。例如,字符“5̃”是两个代码点,而字符“ñ”可能是一个或两个代码点(或更多!)。有 2²¹ 个可能的代码点,但其中一些被保留为非字符或部分字符。
Unicode 是一种字符编码标准。 unicode.org/faq/basic_q.html 的第一个答案:“Unicode 是通用字符编码”,因此说“Unicode 不是编码”是错误的。 (我自己曾经犯过这个错误。)
@tchrist:Unicode 标准定义了多个术语,其中包括“抽象字符”和“编码字符”。所以说Unicode没有字符也是不正确的。