Unicode等价性

Unicode等价性（Unicode equivalence）是为和许多现存的标准能够相容，Unicode（统一码）包含了许多特殊字符。在这些字符中，有些在功能上会和其它字符或字符序列等价。因此，Unicode将一些码位序列定义成相等的。Unicode提供了两种等价概念：标准等价和相容等价。前者是后者的一个子集。例如，字符n后接着组合字符~标准等价和相容等价于Unicode字符ñ。而合字ﬀ则只有相容等价于两个f字符。

Unicode正规化（Unicode normalization）是文字正规化的一种形式，是指将彼此等价的序列转成同一列序。此序列在Unicode标准中称作正规形式。对于每种等价概念，Unicode又定义两种形式，一种是完全合成的，一种是完全分解的。因此，最后会有四种形式，其缩写分别为：NFC、NFD、NFKC、NFKD。对于Unicode的文字处理程式而言，正规化是很重要的。因为它影响了比较、搜寻和排序的意义。

## 等价概念

### 标准等价

统一码中标准等价的基础概念为字符的组成和分解的交互使用。合成指的是将简单的字符合并成较少的预组字符的过程，如字符n和组合字符~可以组成统一码ñ。分解则是反向过程，即将预组字符变回部件。

标准等价是指保持视觉上和功能上的等价。例如，含附加符号字母被视为和分解后的字母及其附加符号是标准等价。换句话说，预组字符“ü”（U+00FC）和由“u”（U+0075）及“ ̈”（U+0308）所组成的序列“ü”（U+0075U+0308）是标准等价。相似地，统一码统合了一些希腊附加符号和外观与附加符号类似的标点符号。

### 相容等价

相容等价的范围较标准等价来得广。如果序列是标准等价的话就会是相容等价，反之则未必成立。相容等价更关注在于纯文字的等价，并把一些语义上的不同形式归结在一起。

例如，上标数字和其所使用的数字是相容等价，但非标准等价。其理由为下标和上标形式虽然在某些时侯属于不同意义，但若应用程序将他们视为一样也是合理的（虽然视觉上可区分）。如此，在统一码富文件中，上标和下标就可以以比较不累赘地方式出现（见下一节）。

全形和半形的片假名也是一种相容等价但不是标准等价。如同合字和其部件序列。其只有视觉上但没有语义上的区别。换句话说，作者通常没有特别宣称使用合字是一种意思，而不使用是另一种意思。相对地，这仅限于印刷上的选择。

## 正规化

文书处理软件在实作统一码字串的搜寻和排序时，须考虑到等价性的存在。如果没有此特性的话，使用者在搜寻时将无法找到在视觉上无法区分的字形。

统一码提供了一个标准的正规化算法，可将所有相同的序列产生一个唯一的序列。

其等价准绳可以为标准的（NF）或相容的（NFK）。

既然可以任意选择等价类中的元素，对每一个等价标准有多个标准形式也是有可能的。

统一码为每一种等价准绳分别提供两种正规形式：合成用的NFC和NFKC以及分解用的NFD和NFKD。

而不论是组合的或分解的形式，都会使用标准顺序，以此限制正规形式只有唯一形式。

为了比较或搜寻统一码字串，软件可以使用合成或分解形式其中之一。

只要被比较或搜寻的字串使用的形式是相同的，哪种选择都没关系。

另一方面，等价概念的选择则会影响到搜寻结果。

譬如，有些合字如ﬃ（U+FB03）、罗马数字如Ⅸ（U+2168），甚至是上标数字如⁵（U+2075）有其个别统一码码位。

标准正规形式并不会影响这些结果。

但相容正规形式会分解ﬃ成f、f、i。所以搜寻U+0066（f）时，在NFKC中会成功，但在NFC则会失败。

同样地有在预组罗马数字Ⅸ 中搜寻拉丁字母I（U+0049）。类似地，“⁵”会转成“5”。

对于丰富文件格式的浏覧器，将上标转换成到基底线未必是好的，因为上标的资讯会因而消失。为了允许这种不同，统一码字符数据库句含了相容格式标签，其提供了相容转换的细节。在合字的情况下，这个标签只是`<compat>`，而在上标的情况下则为`<super>`。丰富文件格式如超文件标示语言则会使用相容标签。例如，HTML使用自订标签来将“5”放到上标位置。

### 正规形式

统一码定义了四种正规形式。这些形式或其（转换）算法表列如下。所有的形式都会使用到标准顺序，好让结果序列能保证是等价类中的唯一形式。这些算法都是幂等转换，但因为singletons和标准顺序的关系，都不是单射。

此外，也没有一个形式在字串串接下会是封闭的，意味着在同一个正规形式下的两个字串串接，并不保证产生的是正规形式。

这会发生在当一个字串并不是以基础字符为开头或以其它中间或结尾字符为开头的字串附加到另一个字串时。

NFDNormalization Form Canonical Decomposition｜以标准等价方式来分解

NFCNormalization Form Canonical Composition｜以标准等价方式来分解，然后以标准等价重组之。若是singleton的话，重组结果有可能和分解前不同。

NFKDNormalization Form Compatibility Decomposition｜以相容等价方式来分解

NFKCNormalization Form Compatibility Composition｜以相容等价方式来分解，然后以标准等价重组之。

有些码点经过正规转换后，是无法转换成之前的形式。换个方式说则是，singleton都不会是正规形式。譬如，埃格斯特朗符号U+212B（Å），在NFC中总是被代换成在视觉上相同的U+00C5（Å –在上方带环的A）。在NFD中，则会换成由U+0041（A）和U+030A（° – combining ring above）这两个字符所组成的序列。因此，没有一个正规函数是单射的。

在统一码字符数据库中，singletons是指那些和其它单一字符有相同分解的字符。

### 标准顺序

标准顺序主要关注在结合符序列的顺序。这里将以附加符号做例子。不过，一般而言，附加符号不是结合字符且结合字符不是附加符号。

统一码假设每个字符是一个结合类别，并赋予一个数字。非结合字符的类别值为0，而结合字符则会是一个正值。要得到标准顺序，每个有非零值结合符的子串序要以稳定排序算法排序过。稳定排序是必要的，因为结合字符被假设会影响到排版，所以两个顺序不被视为相等。

例如，越南语字母中的字符ế（U+1EBF）同时具有尖音符和抑扬符。它的标准分解是序列U+0065（e）、U+0302（抑扬符）、U+0301（尖音符）。这两个重音的结合类别都是230，所以U+1EBF不等同于U+0065 U+0301 U+0302。

并非所有结合序列都有预组（在前一例的最后一个可以化简成U+00E9 U+0302），即使NFC会被结合字符所影响。

相容正规化（NFKC和NFKD）会移除某些格式区别，Unicode联盟因此提醒不应对任意文本不加区分地使用；具体形式应依应用场景选择。

## 因正规化不同而导致的错误

当两个应用程序分享统一码资料，但却使用不同正规形式时，就有可能导致错误。

例如，Mac OS X有许多物件是只能使用分解字符（因此，以UTF-8为编码又限定分解形式的统一码又被称为"UTF8-MAC"）。

在一特例中，OS X错误处理用途而产生的组合字符和Samba档案和打印分享软件（在复制档案时，会将分解过的字母替换成组合过的字母）混合使用时，会导致混淆和损坏资料。应用程序若要避免此类问题，可以保留输入码点，然后只在程式内部使用自己的正规化形式。

## 另见

- Unicode
- 合字
- 附加符号
- 预组字符（Precomposed character）
- Unicode相容字符
- 复杂文字编排（Complex text layout）

## 参考

- Unicode Standard Annex #15: Unicode Normalization Forms