Имеет ли Unicode определенное максимальное количество кодовых точек?
Я прочитал много статей, чтобы узнать, какое максимальное количество кодовых точек Unicode, но я не нашел окончательного ответа.
Я понял, что кодовые точки Unicode были сведены к минимуму, чтобы все кодировки UTF-8 UTF-16 и UTF-32 могли обрабатывать одинаковое количество кодовых точек. Но что это за количество кодовых точек?
наиболее частый ответ, с которым я столкнулся, заключается в том, что кодовые точки Unicode находятся в диапазоне от 0x000000 до 0x10FFFF (1,114,112 кодовые точки), но я также читал в других местах, что это 1,112,114 кодовые точки. Итак, есть ли один номер, который нужно дать, или проблема сложнее?
3 ответов
максимальная допустимая кодовая точка в Юникоде-U+10FFFF, что делает его 21-разрядным набором кодов (но не все 21-разрядные целые числа являются допустимыми кодовыми точками Юникода; в частности, значения от 0x11000 до 0x1FFFF не являются допустимыми кодовыми точками Юникода).
вот откуда берется число 1,114,112: U+0000 .. U+10FFFF - 1,114,112 значения.
однако есть также набор кодовых точек, которые являются суррогатами для UTF-16. Они находятся в диапазоне U+D800 .. ОТ U+ДО DFFF. Это 2048 кодовые точки, зарезервированные для UTF-16.
1,114,112 - 2,048 = 1,112,064
есть также 66 не-символов. Они определены частично в исправление #9: 34 значения вида U+nFFFE и U+nFFFF (где 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. Среди прочего, в предисловии говорится:
стандарт Юникода, версия 7.0, содержит 112,956 символов
таким образом, было выделено только около 10% доступных кодовых точек.
Я не могу объясните, почему вы нашли 1,112,114 как количество кодовых точек.
кстати, верхний предел U+10FFFF выбран таким образом, что все значения в Unicode могут быть представлены в одной или двух 2-байтовых единицах кодирования в UTF-16, используя один высокий суррогат и один низкий суррогат для представления значений за пределами BMP или базовой многоязычной плоскости, которая является диапазоном U+0000 .. U+FFFF.
да, все кодовые точки, которые не могут быть представлены в UTF-16 (включая использование суррогатов), были объявлены недействительными.
U+10FFD кажется самой высокой кодовой точкой, но суррогаты, u+00FFFE и u+00FFFF не являются используемыми кодовыми точками, поэтому общее количество немного ниже.
Я сделал очень маленькую процедуру, которая печатает на экране очень длинную таблицу, от 0 до n значений, где начало var-это число, которое может быть настроено пользователем. Это фрагмент:
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. Вот что я получил:--7-->
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) функция неумолимо останавливается, поэтому я предполагаю, что она достигла своего максимально возможного значения: поэтому я интерпретирую это как максимально возможное значение таблицы символов Юникода. Конечно, как сказано в других ответах, не все коды char имеют эквивалентные символы, но часто они пусты, как показал пример. Также есть много символов, которые повторяются несколько раз в разных точках от 0 до 4294967294 коды символов
Edit: улучшения
(спасибо @duskwuff)
теперь также можно сравнить оба строку.fromCharCode и строку.fromCodePoint поведения. Обратите внимание, что первый оператор поступает в 4294967294, но вывод повторяется каждые 65536 (16 бит = 2^16). Последний перестает работать с кодом 1114111 (потому что список символов Юникода и символов начинается с 0 у нас есть всего 1,114,112 кодовых точек Unicode, но, как сказано в других ответах, не все из них действительны в том смысле, что они являются пустыми точками). Также помните, что для использования определенного символа Юникода вам нужен соответствующий шрифт, в котором определен соответствующий символ. Если нет, вы покажете пустой символ unicode или пустой квадратный символ.
обратите внимание:
Я заметил, что в некоторых системах Android с помощью браузера Chrome для Android js String.fromCodePoint
возвращает ошибку для всех элементов кода.