¿Cuántos caracteres puede codificar UTF-8?

97

Si UTF-8 es de 8 bits, ¿no significa que solo puede haber un máximo de 256 caracteres diferentes?

Los primeros 128 puntos de código son los mismos que en ASCII. ¿Pero dice que UTF-8 puede admitir hasta un millón de caracteres?

¿Como funciona esto?

eMRe
fuente
2
si pudiera reevaluar esta pregunta porque todas las respuestas son incorrectas. Lea mi respuesta: stackoverflow.com/a/45042566/124486
Evan Carroll
En las codificaciones UTF-8, UTF-16, UTF-32 de Unicode, el número es el número de bits en sus unidades de código , uno o más de los cuales codifican un punto de código Unicode.
Tom Blodget
1
Respondí esta pregunta hace un tiempo en un intento de aclararlo: sería genial si lo sopesas con la respuesta elegida, que es literalmente solo una cita de wikipedia que no cuenta toda la historia (con suerte, mi actualización es mucho más claro)
Evan Carroll

Respuestas:

135

UTF-8 no usa un byte todo el tiempo, es de 1 a 4 bytes.

Los primeros 128 caracteres (US-ASCII) necesitan un byte.

Los siguientes 1.920 caracteres necesitan dos bytes para codificarse. Esto cubre el resto de casi todos los alfabetos latinos, y también los alfabetos griego, cirílico, copto, armenio, hebreo, árabe, siríaco y tana, así como la combinación de marcas diacríticas.

Se necesitan tres bytes para los caracteres del resto del plano multilingüe básico, que contiene prácticamente todos los caracteres de uso común [12], incluidos la mayoría de los caracteres chinos, japoneses y coreanos [CJK].

Se necesitan cuatro bytes para los caracteres en los otros planos de Unicode, que incluyen caracteres CJK menos comunes, varios guiones históricos, símbolos matemáticos y emoji (símbolos pictográficos).

fuente: Wikipedia

zwippie
fuente
hola @zwippie soy nuevo en esto. ¡Hay algo que no lo entiendo! BMP usa 2 bytes, ¿dices que son 3? ¿Me equivoco?
chiperortiz
1
@chiperortiz, BMP es de hecho de 16 bits, por lo que se puede codificar como UTF-16 con una longitud constante por carácter (UTF-16 también admite ir más allá de los 16 bits, pero es una práctica difícil y muchas implementaciones no lo admiten). Sin embargo, para UTF-8, también necesita codificar cuánto tiempo será, por lo que perderá algunos bits. Es por eso que necesita 3 bytes para codificar el BMP completo. Esto puede parecer un desperdicio, pero recuerde que UTF-16 siempre usa 2 bytes, pero UTF-8 usa un byte por carácter para la mayoría de los caracteres del lenguaje latino. Haciéndolo dos veces más compacto.
sanderd17
La idea central de la pregunta del OP está relacionada con por qué se llama UTF- 8 ; esto realmente no responde a eso.
jbyrd
39

UTF-8 usa 1-4 bytes por carácter: un byte para caracteres ascii (los primeros 128 valores unicode son los mismos que ascii). Pero eso solo requiere 7 bits. Si se establece el bit más alto ("signo"), esto indica el inicio de una secuencia multibyte; el número de bits altos consecutivos establecidos indica el número de bytes, luego un 0, y los bits restantes contribuyen al valor. Para los otros bytes, los dos bits más altos serán 1 y 0 y los 6 bits restantes son para el valor.

Entonces, una secuencia de cuatro bytes comenzaría con 11110 ... (y ... = tres bits para el valor) luego tres bytes con 6 bits cada uno para el valor, dando un valor de 21 bits. 2 ^ 21 excede el número de caracteres Unicode, por lo que todo Unicode puede expresarse en UTF8.

CódigoClown42
fuente
@NickL. No, me refiero a 3 bytes. En ese ejemplo, si el primer byte de una secuencia multibyte comienza 1111, el primer 1 indica que es el comienzo de una secuencia multibyte, entonces el número de unos consecutivos después de eso indica el número de bytes adicionales en la secuencia (por lo que un primer byte comenzará 110, 1110 o 11110).
CodeClown42
Encontré pruebas de sus palabras en RFC 3629. tools.ietf.org/html/rfc3629#section-3 . Sin embargo, no entiendo por qué debo colocar "10" al comienzo del segundo byte 110xxxxx 10xxxxxx. ¿Por qué no solo 110xxxxx xxxxxxxx?
kolobok
3
Respuesta encontrada en softwareengineering.stackexchange.com/questions/262227/… . Solo por razones de seguridad (en caso de que un solo byte en el medio de la transmisión esté dañado)
kolobok
@kolobok Ah. Sin seguridad, puede codificar un valor de 21 bits en 3 bytes (3 bits que indican la longitud, más 21 bits). : D Sin embargo, probablemente eso no sea tan significativo, al menos en los idiomas occidentales WRT.
CodeClown42
Supongo que NickL preguntó esto, pero ¿qué pasó con el resto de los bits en ese primer byte si ... representa bytes posteriores en lugar de bits?
c6754
26

Según esta tabla, * UTF-8 debería admitir:

2 31 = 2,147,483,648 caracteres

Sin embargo, RFC 3629 restringió los valores posibles, por lo que ahora tenemos un límite de 4 bytes , lo que nos da

2 21 = 2,097,152 caracteres

Tenga en cuenta que una buena parte de esos caracteres están "reservados" para uso personalizado, lo que en realidad es bastante útil para las fuentes de iconos.

* Wikipedia muestra una tabla con 6 bytes; desde entonces han actualizado el artículo.

2017-07-11: corregido para contar dos veces el mismo punto de código codificado con varios bytes

mpen
fuente
Esta respuesta es contar dos veces el número de codificaciones posibles. Una vez que haya contado los 2 ^ 7, no podrá volver a contarlos en 2 ^ 11, 2 ^ 16, etc. El número correcto de codificaciones posibles es 2 ^ 21 (aunque no todas se están utilizando actualmente).
Jimmy
@Jimmy ¿Estás seguro de que estoy contando dos veces? 0xxxxxxxda 7 bits utilizables, 110xxxxx 10xxxxxxda 11 más, no hay superposición. El primer byte comienza con 0en el primer caso y 1en el segundo.
mpen
@mpen, entonces, ¿qué punto de código 00000001almacena y qué 11000000 100000001almacena?
Evan Carroll
1
@EvanCarroll Uhh .... punto tomado. No me di cuenta de que había varias formas de codificar el mismo punto de código.
mpen
1
Seguí adelante e intenté responder esto yo mismo, vea si cree que esta es una mejor explicación y respuesta a la pregunta: stackoverflow.com/a/45042566/124486
Evan Carroll
21

Unicode frente a UTF-8

Unicode resuelve los puntos de código en caracteres. UTF-8 es un mecanismo de almacenamiento para Unicode. Unicode tiene una especificación. UTF-8 tiene una especificación. Ambos tienen límites diferentes. UTF-8 tiene un límite ascendente diferente.

Unicode

Unicode se designa con "planos". Cada avión lleva 2 16 puntos de código. Hay 17 aviones en Unicode. Para un total de 17 * 2^16puntos de código. El primer plano, el plano 0 o el BMP , es especial por el peso de lo que lleva.

En lugar de explicar todos los matices, permítanme citar el artículo anterior sobre aviones.

Los 17 planos pueden acomodar 1,114,112 puntos de código. De estos, 2.048 son sustitutos, 66 no son personajes y 137.468 están reservados para uso privado, dejando 974.530 para asignación pública.

UTF-8

Ahora volvamos al artículo vinculado anteriormente,

El esquema de codificación utilizado por UTF-8 fue diseñado con un límite mucho mayor de 2 31 puntos de código (32 768 planos), y puede codificar 2 21 puntos de código (32 planos) incluso si está limitado a 4 bytes. [3] Dado que Unicode limita los puntos de código a los 17 planos que pueden ser codificados por UTF-16, los puntos de código por encima de 0x10FFFF no son válidos en UTF-8 y UTF-32.

Entonces puede ver que puede poner cosas en UTF-8 que no son Unicode válido. ¿Por qué? Porque UTF-8 admite puntos de código que Unicode ni siquiera admite.

UTF-8, incluso con una limitación de cuatro bytes, admite 2 21 puntos de código, que es mucho más que17 * 2^16

Evan Carroll
fuente
18

Se pueden codificar potencialmente 2,164,864 “caracteres” mediante UTF-8.

Este número es 2 ^ 7 + 2 ^ 11 + 2 ^ 16 + 2 ^ 21 que proviene de la forma en que funciona la codificación:

  • Los caracteres de 1 byte tienen 7 bits para la codificación 0xxxxxxx(0x00-0x7F)

  • Los caracteres de 2 bytes tienen 11 bits para la codificación 110xxxxx 10xxxxxx(0xC0-0xDF para el primer byte; 0x80-0xBF para el segundo)

  • Los caracteres de 3 bytes tienen 16 bits para la codificación 1110xxxx 10xxxxxx 10xxxxxx(0xE0-0xEF para el primer byte; 0x80-0xBF para los bytes de continuación)

  • Los caracteres de 4 bytes tienen 21 bits para la codificación 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx(0xF0-0xF7 para el primer byte; 0x80-0xBF para los bytes de continuación)

Como puede ver, esto es significativamente más grande que el Unicode actual (1,112,064 caracteres).

ACTUALIZAR

Mi cálculo inicial es incorrecto porque no considera reglas adicionales. Consulte los comentarios a esta respuesta para obtener más detalles.

Ruben Reyes
fuente
2
Sus matemáticas no respetan la regla UTF-8 de que solo la secuencia de unidad de código más corta puede codificar un punto de código. Entonces, 00000001 es válido para U + 0001 pero 11110000 10000000 10000000 10000001 no lo es. Ref: Tabla 3-7. Secuencias de bytes UTF-8 bien formadas . Además, la pregunta es respondida directamente por la tabla: simplemente sume los rangos. (No están unidos para excluir sustitutos de UTF-16).
Tom Blodget
Tom, gracias por tu comentario. No conocía esas restricciones. Vi la tabla 3-7 y ejecuté los números y parece que hay 1,083,392 posibles secuencias válidas.
Ruben Reyes
6

UTF-8 es una codificación de longitud variable con un mínimo de 8 bits por carácter.
Los caracteres con puntos de código más altos ocuparán hasta 32 bits.

deceze
fuente
2
Esto es engañoso. El punto de código más largo que puede tener es 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx, por lo que solo se pueden usar 21 bits para codificar el carácter real.
Boris
5
Dije que los puntos de código pueden tardar hasta 32 bits en codificarse, nunca dije que (por inducción) se pueden codificar 2 ^ 32 caracteres en UTF-8 de 32 bits. Pero eso es bastante discutible, ya que puede codificar todos los caracteres Unicode existentes en UTF-8, y puede codificar aún más si extiende UTF-8 a 48 bits (que existe pero está obsoleto), así que no estoy seguro de cuál es el el punto engañoso es.
diciembre
2

Consulte el estándar Unicode y la información relacionada, como su entrada de preguntas frecuentes, UTF-8 UTF-16, UTF-32 y BOM . No es tan fácil, pero es información autorizada, y mucho de lo que podría leer sobre UTF-8 en otros lugares es cuestionable.

El "8" en "UTF-8" se refiere a la longitud de las unidades de código en bits. Las unidades de código son entidades que se utilizan para codificar caracteres, no necesariamente como una simple asignación uno a uno. UTF-8 usa un número variable de unidades de código para codificar un carácter.

La colección de caracteres que se pueden codificar en UTF-8 es exactamente la misma que para UTF-16 o UTF-32, es decir, todos los caracteres Unicode. Todos codifican todo el espacio de codificación Unicode, que incluso incluye no caracteres y puntos de código no asignados.

Jukka K. Korpela
fuente
1

Si bien estoy de acuerdo con mpen en los códigos UTF-8 máximos actuales (2,164,864) (que se enumeran a continuación, no pude comentar sobre el suyo), está fuera de 2 niveles si elimina las 2 restricciones principales de UTF-8: solo 4 bytes límite y los códigos 254 y 255 no se pueden usar (solo eliminó el límite de 4 bytes).

El código de inicio 254 sigue la disposición básica de los bits de inicio (bandera de varios bits establecida en 1, un recuento de 6 1 y terminal 0, sin bits de repuesto), lo que le brinda 6 bytes adicionales para trabajar (6 grupos 10xxxxxx, 2 ^ adicionales 36 códigos).

El código de inicio 255 no sigue exactamente la configuración básica, no hay terminal 0 pero se usan todos los bits, lo que le da 7 bytes adicionales (marca de múltiples bits establecida en 1, una cuenta de 7 1 y sin terminal 0 porque se usan todos los bits ; 7 grupos 10xxxxxx, 2 ^ 42 códigos adicionales).

Al agregarlos, se obtiene un conjunto de caracteres presentable máximo final de 4.468.982.745.216. Esto es más que todos los caracteres en uso actual, idiomas antiguos o muertos, y cualquier idioma perdido que se cree. ¿Alguien quiere un guión angelical o celestial?

También hay códigos de un solo byte que se pasan por alto / ignoran en el estándar UTF-8 además de 254 y 255: 128-191, y algunos otros. Algunos son usados ​​localmente por el teclado, el código de ejemplo 128 suele ser un retroceso de eliminación. Los otros códigos de inicio (y rangos asociados) no son válidos por una o más razones ( https://en.wikipedia.org/wiki/UTF-8#Invalid_byte_sequences ).

James V. Fields
fuente
0

Unicode está firmemente casado con UTF-8. Unicode admite específicamente 2 ^ 21 puntos de código (2,097,152 caracteres) que es exactamente la misma cantidad de puntos de código admitidos por UTF-8. Ambos sistemas reservan el mismo espacio 'muerto' y zonas restringidas para puntos de código, etc. ... a junio de 2018, la versión más reciente, Unicode 11.0, contiene un repertorio de 137,439 caracteres

Del estándar Unicode. Preguntas frecuentes sobre Unicode

El estándar Unicode codifica caracteres en el rango U + 0000..U + 10FFFF, lo que equivale a un espacio de código de 21 bits.

De la página de Wikipedia de UTF-8. Descripción UTF-8

Desde la restricción del espacio de código Unicode a valores de 21 bits en 2003, UTF-8 se define para codificar puntos de código en uno a cuatro bytes, ...

Nombre para mostrar
fuente
21 bits se redondean. Unicode admite 1,114,112 puntos de código (U + 0000 a U + 10FFFF) como dice. (A veces descrito como 17 aviones de 65536)
Tom Blodget
@TomBlodget, tienes razón. La conclusión más relevante de esta discusión es que UTF-8 puede codificar todos los puntos definidos actualmente en el estándar Unicode y probablemente podrá hacerlo durante bastante tiempo.
Nombre