martes, 23 de septiembre de 2008

Carácter, natural, bit. Unicode.

Un carácter es un signo de escritura o imprenta, como una letra, un número, una coma, una interrogación... El concepto de carácter es abstracto, por ejemplo la "a minúscula" puede visualizarse con apariencias variadas. La apariencia gráfica se determina por el tipo de letra (Arial, Times,...) y la fuente (normal, negrita, cursiva, etc, de tamaños diversos), pero el concepto de "letra a minúscula" es independiente de tal apariencia concreta.

Al llegar la era de la información los ordenadores deben manejar los caracteres normales, y además se empiezan a usar caracteres no visibles, pero que tienen su utilidad, como el retorno de carro y lo que en general se llaman caracteres de control, que informan a las máquinas de cómo comportarse: mueve esa cabezota de impresión al principio de la línea, avanza el rodillito hasta la siguiente línea, pita, etc.

Internamente los sistemas digitales solo entienden secuencias de bits. Un bit, un dígito binario, es o cero o uno, 0 o 1. Por razones históricas esas secuencias casi siempre se agrupan y manejan en grupos de 8 bits, lo que se denomina byte.

¿Como relacionar los caracteres con los bytes? Pues en dos pasos, que en muchos casos se dan a la vez . Empleando una denominación que no puede considerarse estándar, pero que uso consistentemente para diferenciarlos, esos dos pasos son:

Código (coded character set), del carácter al número. Se asocia a cada carácter abstracto un número natural. Como interesa manejar un repertorio de caracteres, podemos visualizar esta asociación como la colocación de cada carácter en una casilla de un casillero, siendo identificada cada casilla del casillero por un número natural, lo que llamaremos punto de código, o en inglés "code point".

Codificación (character encoding form), del número al bit. Regla por la que se asocia un número natural con una pauta concreta de bits. Con 8 bits hay 256 pautas distintas, que se asocian de forma "natural" a los números naturales del 0 al 255, según una regla que puede llamarse sistema binario, según la cual por ejemplo '10000011' corresponde a 131. En realidad este sistema binario se puede aplicar para relacionar cualquier secuencia de bits, tan grande como se quiera, con un número natural. Con 16 bits, 2 bytes, se pueden representar los números del 0 hasta el 65535. Con 4 bytes, los números naturales entre 0 y 4294967295. Pero no tiene que emplearse forzosamente ese sistema binario "natural", y puede haber pautas especiales de bits que no se asocien a un número.

Hace muchos años, cuando los norteamericanos eran casi los únicos en el mundo de la informática, cogieron un repertorio de sus caracteres favoritos, que no pasaban de 128. Les repartieron a su manera en un casillero de 128 casillas. Luego cada casilla la representaron con bits por la pauta "natural" empleando 7 de los 8 bits de un byte. El bit restante se usaba como comprobación contra errores. Lo que resultó es el código de caracteres ASCII (Código Estadounidense Estándar para el Intercambio de Información). Este código engloba tanto la asignación de cada carácter del repertorio a una casilla (código), como el byte correspondiente a esa casilla (codificación). En el ASCII inicial el byte obtenido para cada una de las 128 casillas no era siempre el resultante de aplicar la regla "natural" del sistema binario, por el uso especial del octavo bit.

Pronto se necesitó ampliar el repertorio de caracteres y usar un casillero mayor, de 256 casillas. Se amplió el ASCII rellenando el casillero agrandado, y cambiando la regla de codificación para usar, entonces sí, el sistema binario "natural" y abandonar el bit de paridad.

Pero como los americanos no estaban solos, y hay muchos alfabetos en el mundo, se hizo imprescindible definir más casilleros, cada uno con 256 casillas en las que en cada caso se colocaban distintos repertorios de caracteres, o incluso un mismo carácter se colocaba en distinta casilla. A cada casillero distinto se le suele denominar página de código, o code page, y se distinguen unos casilleros de otros por un número. La página de código 437 es la original del IBM PC, y en ese casillero la "a minúscula acentuada" ocupa la casilla 160. La página de código 1252 es la usada por Windows para el repertorio de caracteres latinos eurooccidentales, y en este casillero la "a minúscula acentuada" ocupa la casilla 225. Hay páginas de código con caracteres de repertorios correspondientes a lenguas de casi todo el mundo.

Y aquí tenemos la babel desatada. Porque casi se podía acertar en suponer que la codificación (encoding) de un byte era la "natural" del sistema binario, y de los bytes obtener el número natural correcto indicativo de la casilla. Pero la casilla ¿de qué casillero? Había que saber la página de código correcta. Y en aplicaciones multilingües podían ser necesarias muchas.

Contra la babel desatada, organización. UNICODE. La solución en esencia es olvidar la multitud de casilleros de reducidas dimensiones. Usar un único casillero que pueda albergar cualquiera de los caracteres que ha habido en la historia humana o que pueda idearse en el futuro: un casillero con 1,114,112 casillas. En vez de imaginar las casillas en línea, para distinguir las partes del casillero este se divide en 17 planos (del 0 al 16), cada plano con 65536 casillas. Cada casilla se distingue del resto por su punto de código (code point), un número natural entre 0 y 1,114,111 aunque lo más común no es usar el sistema decimal, sino el hexadecimal. Todos los caracteres de todos los idiomas conocidos, más todo tipo de símbolos, se reparten por el casillero de una forma convenida que se conoce como Conjunto de Caracteres Universal. A veces se habla de "caracteres Unicode".

Resuelto el problema del código, se agrava un tanto el de la codificación. Para cubrir ese rango numérico hacen falta como mínimo 21 bits, que implica usar 3 bytes. Ademas a los sistemas binarios no les gustan los impares, a veces manejan "palabras" de 2 o de 4 bytes, pero no de 3. Para abordar este tema de la codificación de los puntos de código, se ofrecen varias tipos de codificación. El más simple se denomina UTF-32, y usa 4 bytes para representar cada casilla. Ventaja: uniformidad y rapidez en codificar y descodificar. Desventaja: Salvaje despilfarro de espacio, pues la inmensa mayoría de caracteres realmente utilizados están en casillas de números bajos, que pueden representarse con sólo un byte, o con dos bytes. Por eso se plantean los sistemas de codificación de longitud variable, aquellos que emplean diferente número de bytes según la casilla de que se trate. UTF-16 emplean como mínimo dos bytes (16 bits). El más económico es UTF-8, que como mínimo puede emplear un sólo byte (8 bits). Estas tres formas de codificación son parte del estándar Unicode. Hay otras variantes que no son estándar y es mejor olvidar.

UTF-8 tiene la ventaja de ahorro en espacio, y de compatibilidad con el veterano y muy extendido código ASCII. El lado negativo está en la mayor complejidad en la codificación y descodificación, pero como eso lo hacen las máquinas... Es de esperar que en un futuro sólo se use Unicode (el casillero Conjunto de Caracteres Universal), y como codificación UTF-8 y UTF-16.

Todo esto que parece tan sencillo tiene muchos detalles técnicos que dan para leer largo y tendido. Parte de la codificación UTF-8 consiste en distinguir cuando se usa sólo un byte o cuando se usan más. De los bytes empleados solo algunos bits se emplean para obtener, usando el sistema binario, el punto de código. Hay una pauta de bits reservada para identificar el orden de bytes usados en cada sistema informático (pues usando palabras de 2 bytes, el byte con los bits más significativos puede ir o el primero o el segundo, y habiendo dos posibilidades ...).

Para que la felicidad sea completa, y reconozcamos gráficamente los caracteres, solo falta tener una fuente que represente (casi) todos los definidos en Unicode. En Windows se puede visualizar cualquier carácter Unicode con la fuente Arial Unicode MS.

En todo este ámbito, en que las tecnologías de la información se relacionan con los sistemas de escritura y los lenguajes humanos, puede apreciarse lo fructífero (y arduo) que resulta la cooperación, el entendimiento, la unificación de criterios, y el empleo del discurrir de muchos para el beneficio de todos. Bien por Unicode.