¿Cuántos caracteres se pueden asignar con Unicode?

82

Estoy preguntando por el recuento de todas las posibles combinaciones válidas en Unicode con explicación. Sé que un char se puede codificar como 1,2,3 o 4 bytes. Tampoco entiendo por qué los bytes de continuación tienen restricciones a pesar de que el byte inicial de ese carácter borra cuánto tiempo debería ser.

Ufuk Hacıoğulları
fuente

Respuestas:

118

Estoy preguntando por el recuento de todas las posibles combinaciones válidas en Unicode con explicación.

1,111,998 : 17 planos × 65,536 caracteres por plano - 2048 sustitutos - 66 no personajes

Tenga en cuenta que, en teoría, UTF-8 y UTF-32 podrían codificar mucho más de 17 planos, pero el rango está restringido en función de las limitaciones de la codificación UTF-16 .

137,929 puntos de código están realmente asignados en Unicode 12.1 .

Tampoco entiendo por qué los bytes de continuación tienen restricciones a pesar de que el byte inicial de ese carácter borra cuánto tiempo debería ser.

El propósito de esta restricción en UTF-8 es hacer que la codificación se sincronice automáticamente .

Como contraejemplo, considere la codificación china GB 18030 . Allí, la letra ßse representa como la secuencia de bytes 81 30 89 38, que contiene la codificación de los dígitos 0y 8. Entonces, si tiene una función de búsqueda de cadenas no diseñada para esta peculiaridad específica de la codificación, una búsqueda del dígito 8encontrará un falso positivo dentro de la letra ß.

En UTF-8, esto no puede suceder, porque la no superposición entre los bytes iniciales y los bytes finales garantiza que la codificación de un carácter más corto nunca pueda ocurrir dentro de la codificación de un carácter más largo.

dan04
fuente
2
El artículo sobre "sincronización automática" que vinculó no explica en absoluto qué es la sincronización
automática
Como nota interesante, UTF8 solo necesita 4 bytes para mapear todos los caracteres Unicode, pero UTF8 puede admitir hasta 68 mil millones de caracteres si alguna vez es necesario, ocupando hasta 7 bytes por carácter.
santiago arizti
10

Unicode permite 17 planos , cada uno de los 65.536 caracteres posibles (o 'puntos de código'). Esto da un total de 1,114,112 caracteres posibles. En la actualidad, solo se ha asignado alrededor del 10% de este espacio.

Los detalles precisos de cómo se codifican estos puntos de código difieren con la codificación, pero su pregunta hace que parezca que está pensando en UTF-8. La razón de las restricciones en los bytes de continuación es presumiblemente que es fácil encontrar el comienzo del siguiente carácter (ya que los caracteres de continuación siempre tienen el formato 10xxxxxx, pero el byte de inicio nunca puede ser de este formato).

Simon Nickerson
fuente
Según estos "planos", incluso los últimos tres bytes de un carácter de 4 bytes podrían expresar 64 de ellos. ¿Me equivoco?
Ufuk Hacıoğulları
Sí, eso es para sincronización, consulte cl.cam.ac.uk/~mgk25/ucs/utf-8-history.txt
ninjalj
2
Eso es anticuado, creo. Ya no usa 6 bytes
Ufuk Hacıoğulları
3
@Andy: Eso tiene sentido: la especificación original para UTF-8 funcionó para números más grandes. El límite de 21 bits fue un alivio para las personas que se habían encerrado en caracteres de 16 bits y, por lo tanto, UCS-2 engendró la abominación conocida como UTF-16.
tchrist
1
@Simon: Hay 34 puntos de código que no son caracteres, cualquier cosa que cuando se agrega bit a bit con 0xFFFE == 0xFFFE, por lo que dos puntos de código de este tipo por plano. Además, hay 31 puntos de código que no son caracteres en el rango 0x00_FDD0 .. 0x00_FDEF. Además, debe restar de eso los sustitutos, que no son legales para el intercambio abierto debido a la falla UTF-16, pero deben ser admitidos dentro de su programa.
tchrist
5

Unicode admite 1,114,112 puntos de código. Hay 2048 puntos de código sustitutos, lo que da 1,112,064 valores escalares. De estos, hay 66 no caracteres, lo que lleva a 1,111,998 caracteres codificados posibles (a menos que haya cometido un error de cálculo).

Philipp
fuente
¿Puedes mirar mi respuesta? ¿Por qué hay 1,112,114 puntos de código?
Ufuk Hacıoğulları
3
Este número proviene del número de planos que se pueden direccionar utilizando el sistema sustituto UTF-16. Tiene 1024 sustitutos bajos y 1024 sustitutos altos, lo que da 1024² puntos de código que no son BMP. Esto más los 65,536 puntos de código BMP da exactamente 1,114,112.
Philipp
2
@Philipp, pero da '1_112_114' en su respuesta, pero explica '1_114_112' en su comentario. Quizás confundiste el 2 y el 4.
Shawn Kovac
1
Esta respuesta ha estado sentada con los errores de cálculo durante años, así que me tomé la libertad de limpiarla. Sí, el valor 1112114 en la respuesta fue un error tipográfico. El valor correcto es 1114112, que es el valor decimal de 0x110000.
Ray Toal
1

Para dar una respuesta precisa metafóricamente, all of them.

Los bytes de continuación en las codificaciones UTF-8 permiten la resincronización del flujo de octetos codificados frente al "ruido de línea". El codificador, simplemente necesita escanear hacia adelante en busca de un byte que no tenga un valor entre 0x80 y 0xBF para saber que el siguiente byte es el comienzo de un nuevo punto de carácter.

En teoría, las codificaciones que se utilizan hoy en día permiten la expresión de caracteres cuyo número de caracteres Unicode es de hasta 31 bits de longitud. En la práctica, esta codificación se implementa en servicios como Twitter, donde el tweet de longitud máxima puede codificar hasta 4.340 bits de datos. (140 caracteres [válidos y no válidos], multiplicados por 31 bits cada uno).

Andy Finkenstadt
fuente
En realidad, en teoría no está limitado a 31 bits, puede ir más grande en una máquina de 64 bits. perl -le 'print ord "\x{1FFF_FFFF_FFFF}"'imprime 35184372088831 en una máquina de 64 bits, pero da un desbordamiento de enteros en una máquina de 32 bits. Puede utilizar caracteres más grandes, como que dentro de su programa de Perl, pero si se intenta imprimir en papel como UTF-8, se obtiene una advertencia obligatoria a menos que tales desactivar: perl -le 'print "\x{1FFF_FFFF}"' Code point 0x1FFFFFFF is not Unicode, may not be portable at -e line 1. ######. Hay una diferencia entre "UTF8 suelto" y "UTF-8 estricto": el primero no está restringido.
tchrist
1
Las codificaciones que se utilizan hoy en día no permiten valores escalares de 31 bits. UTF-32 permitiría valores de 32 bits, UTF-8 para incluso más, pero UTF-16 (utilizado internamente por Windows, OS X, Java, .NET, Python y, por lo tanto, el esquema de codificación más popular) permite un poco más de un millón (que debería ser suficiente).
Philipp
1
"Todos ellos" no es del todo exacto; hay caracteres en codificaciones heredadas que no están en Unicode. Por ejemplo, el logotipo de Apple en MacRoman y un par de caracteres gráficos en ATASCII. OTOH, hay un área de uso privado, por lo que estos caracteres se pueden mapear con Unicode; simplemente no son parte del estándar.
dan04
1
@tchrist: Python 3 usa UTF-16; por ejemplo, en mi sistema puedo decir len(chr(0x10000)), dando 2 (unidades de código). El kernel de OS X usa UTF-8, correcto, pero las API de alto nivel (Cocoa, etc.) usan UTF-16.
Philipp
1
@Philip: Solo uso Python 2, cuya compatibilidad con Unicode deja mucho que desear. Soy un tipo de sistemas, así que no hago cromadas para el usuario final: todas las llamadas al sistema que uso en OS X toman UTF-8, que el kernel convierte en NFC por ti. Mis experiencias con UTF-16 en Java han sido malas: intente una coincidencia de clase de char entre corchetes de expresiones regulares con algunos puntos de código que no sean BMP en su, como [𝒜-𝒵], y verá por qué encuentro que exponer UTF-16 es un fracaso. Es un error hacer que los programadores piensen en formas de codificación en lugar de en caracteres lógicos.
tchrist
1

Unicode tiene la cantidad hexadecimal de 110000, que es 1114112

Dmitry Pleshkov
fuente
1

Según Wikipedia , Unicode 12.1 (lanzado en mayo de 2019) contiene 137.994 caracteres distintos.

orlp
fuente
@Ufuk: Unicode no tiene caracteres. Tiene puntos de código. A veces, se requieren varios puntos de código para formar un carácter. Por ejemplo, el carácter "5̃" son dos puntos de código, mientras que el carácter "ñ" puede ser uno o dos puntos de código (¡o más!). Hay 2²¹ puntos de código posibles, pero algunos de ellos están reservados como no caracteres o como caracteres parciales.
tchrist
6
Unicode es un estándar de codificación de caracteres. Primera respuesta de unicode.org/faq/basic_q.html : "Unicode es la codificación de caracteres universal", por lo que decir que "Unicode no es una codificación" es incorrecto. (Una vez cometí ese error)
Philipp
1
@tchrist: el estándar Unicode define varios términos, entre ellos "carácter abstracto" y "carácter codificado". Entonces, decir que Unicode no tiene caracteres tampoco es cierto.
Philipp