Unicode是否具有已定义的最大代码点数?

时间:2014-12-11 05:26:35

标签: unicode utf-8 utf-16 codepoint utf-32

我已阅读了很多文章,以了解Unicode代码点的最大数量,但我没有找到最终答案。

据我所知,Unicode代码点被最小化,使得所有UTF-8 UTF-16和UTF-32编码都能够处理相同数量的代码点。但是这个代码点的数量是多少?

我遇到的最常见的答案是Unicode代码点在0x000000到0x10FFFF(1,114,112代码点)的范围内,但我还在其他地方读过它是1,112,114个代码点。那么要给出一个数字还是比这更复杂的问题?

3 个答案:

答案 0 :(得分:22)

Unicode中的最大有效代码点是U + 10FFFF,这使它成为一个21位代码集(但并非所有21位整数都是有效的Unicode代码点;特别是0x110000到0x1FFFFF的值不是有效的Unicode代码点)。

这是数字1,114,112来自:U + 0000 .. U + 10FFFF是1,114,112个值。

但是,还有一组代码点是UTF-16的代理。它们在U + D800 .. U + DFFF范围内。这是为UTF-16保留的2048个代码点。

1,114,112 - 2,048 = 1,112,064

还有66个非角色。这些部分在Corrigendum #9中定义:形式为U + nFFFE和U + nFFFF的34个值(其中 n 是值0x00000,0x10000,... 0xF0000,0x100000)和32个值U + FDD0 - U + FDEF。减去这些也会产生1,111,998个可分配字符。有三个范围保留用于'私人使用':U + E000 .. U + F8FF,U + F0000 .. U + FFFFD,以及U + 100000 .. U + 10FFFD。实际分配的值的数量取决于您正在查看的Unicode版本。您可以在Unicode Consortium找到有关最新版本的信息。除此之外,那里的介绍说:

  

Unicode标准版本7.0包含112,956个字符

因此,只分配了大约10%的可用代码点。

我无法解释您为什么找到1,112,114作为代码点的数量。

顺便提一下,选择上限U + 10FFFF,以便Unicode中的所有值都可以用UTF-16中的一个或两个2字节编码单位表示,使用一个高代理项和一个低代理项来表示BMP或基本多语言平面,范围为U + 0000 .. U + FFFF。

答案 1 :(得分:2)

是的,所有无法用UTF-16表示的代码点(包括使用代理)都被宣布无效。

U + 10FFD似乎是最高的代码点,但代理,u + 00FFFE和u + 00FFFF不是可用的代码点,所以总计数稍低。

答案 2 :(得分:-5)

我制作了一个非常小的例程,在屏幕上打印一个非常长的表,从0到n值,其中var start是一个可由用户自定义的数字。这是片段:

function getVal()
			{
				var start = parseInt(document.getElementById('start').value);
				var range = parseInt(document.getElementById('range').value);
				var end = start + range;
				return [start, range, end];
			}

		
			function next()
			{
				var values = getVal();
				document.getElementById('start').value = values[2];
				document.getElementById('ok').click();
			}
			
			function prev()
			{
				var values = getVal();
				document.getElementById('start').value = values[0] - values[1];
				document.getElementById('ok').click();
			}
			
			function renderCharCodeTable()
			{
				var values = getVal();
				var start = values[0];
				var end = values[2];

				const MINSTART = 0; // Allowed range
				const MAXEND = 4294967294; // Allowed range
				
				start = start < MINSTART ? MINSTART : start;
				end = end < MINSTART ? (MINSTART + 1) : end;

				start = start > MAXEND ? (MAXEND - 1) : start;
				end = end >= MAXEND ? (MAXEND + 1) : end;
				
				var tr = [];
				
				var unicodeCharSet = document.getElementById('unicodeCharSet');

				var cCode;
				var cPoint;
				for (var c = start; c < end; c++)
				{
					try
					{
						cCode = String.fromCharCode(c);
					}
					catch (e)
					{
						cCode = 'fromCharCode max val exceeded';
					}
					
					try
					{
						cPoint = String.fromCodePoint(c);
					}
					catch (e)
					{
						cPoint = 'fromCodePoint max val exceeded';
					}
					
					tr[c] = '<tr><td>' + c + '</td><td>' + cCode + '</td><td>' + cPoint + '</td></tr>'
				}
				unicodeCharSet.innerHTML = tr.join('');
			}
			
			function startRender()
			{
				setTimeout(renderCharCodeTable, 100);
				console.time('renderCharCodeTable');
			}
			unicodeCharSet.addEventListener("load",startRender());
body
		{
			margin-bottom: 50%;
		}
		
		form
		{
			position: fixed;
		}
		
		table *
		{
			border: 1px solid black;
			font-size: 1em;
			text-align: center;
		}
		
		table
		{
			margin: auto;
			border-collapse: collapse;
		}
		
		td:hover
		{
			padding-bottom: 1.5em;
			padding-top: 1.5em;
		}
		
		tbody > tr:hover
		{
			font-size: 5em;
		}
	
	<form>
		Start Unicode: <input type="number" id="start" value="0" onchange="renderCharCodeTable()" min="0" max="4294967300" title="Set a number from 0 to 4294967294" >
		<p></p>
		Show <input type="number" id="range" value="30" onchange="renderCharCodeTable()" min="1" max="1000" title="Range to show. Insert a value from 10 to 1000" > symbols at once.
		<p></p>
		<input type="button" id="pr" value="◄◄" onclick="prev()" title="Mostra precedenti" >
		<input type="button" id="nx" value="►►" onclick="next()" title="Mostra successivi" >
		<input type="button" id="ok" value="OK" onclick="startRender()" title="Ok" >
		<input type="reset" id="rst" value="X" onclick="startRender()" title="Reset" >
		
	</form>
	<table>
		<thead>
			<tr>
				<th>CODE</th>
				<th>Symbol fromCharCode</th>
				<th>Symbol fromCodePoint</th>
			</tr>
		</thead>
		<tbody id="unicodeCharSet">
			<tr><td colspan="2">Rendering...</td></tr>
		</tbody>
	</table>

第一次运行它,然后打开代码并将start变量的值设置为一个非常高的数字,只比MAXEND常数值略低一点。以下是我获得的内容:

    code        equivalent symbol
{~~~ first execution output example ~~~~~}

0   
1   
2   
3   
4   
5   
6   
7   
8   
9   
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  !
34  "
35  #
36  $
37  %
38  &
39  '
40  (
41  )
42  *
43  +
44  ,
45  -
46  .
47  /
48  0
49  1
50  2
51  3
52  4
53  5
54  6
55  7
56  8
57  9
{~~~ second execution output example ~~~~~}
4294967275  →
4294967276  ↓
4294967277  ■
4294967278  ○
4294967279  ￯
4294967280  ￰
4294967281  ￱
4294967282  ￲
4294967283  ￳
4294967284  ￴
4294967285  ￵
4294967286  ￶
4294967287  ￷
4294967288  ￸
4294967289  
4294967290  
4294967291  
4294967292  
4294967293  �
4294967294  

当然输出被截断(在第一次和第二次执行之间),因为它太长了。

在4294967294(= 2 ^ 32)之后,函数不可避免地停止,因此我认为它已达到其最大可能值:所以我将其解释为unicode char代码表的最大可能值。当然,正如其他答案所说的那样,并非所有的char代码都具有等效符号,但通常它们是空的,如示例所示。还有很多符号在0到4294967294个字符代码之间的不同点重复多次

编辑:改进

(谢谢@duskwuff)

现在也可以比较 String.fromCharCode String.fromCodePoint 行为。请注意,第一个语句到达4294967294,但输出每65536(16位= 2 ^ 16)重复。最后一个停止在代码1114111处工作(导致unicode字符列表和符号从0开始,我们总共有1,114,112个Unicode代码点,但正如在其他答案中所说的那样,并非它们都是有效的,因为它们是空点) 。还要记住,要使用某个unicode char,你需要有一个合适的字体,其中定义了相应的char。如果不是,您将显示一个空的unicode char或一个空的方形字符。

enter image description here

注意:

我注意到在某些使用适用于Android的Chrome浏览器的Android系统中,js String.fromCodePoint会为所有代码点返回错误。