La serie “El computador mágico” está disponible también en forma de libro. |
Hemos dedicado los últimos capítulos de la serie a mostrar cómo representar números solamente con 1s y 0s. En este capítulo vamos a ver cómo representar otro tipo de información: el texto.
Pero antes de continuar, quiero dedicar una líneas a animarte. Es posible que estés un poco preocupado porque parece que nos estamos desviando del tema, dejando de lado el funcionamiento del ordenador, para centrarnos en aspectos demasiado formales, quizá demasiado técnicos… Si esa es tu impresión, no desistas, sigue adelante. Lo que hemos visto en los últimos capítulos es una base para que, cuando más adelante veamos cosas más complejas, podamos centrarnos en dichos detalles complejos y dar por sabidas estas cosas. Haz un pequeño acto de confianza en mí y piensa que toda esta aproximación es parte de un meticuloso plan para dominar el mun… para que entiendas cómo funciona el ordenador.
Además, esta entrada en concreto tiene muchas batallitas, mucha historia, así que será, eso espero, hasta divertida.
El caso es que ya sabemos cómo representar y operar con números, tanto enteros como de coma flotante.[1] Pero una parte no despreciable del trabajo que queremos hacer con un ordenador es procesar texto.
No debemos pensar solamente en un procesador de textos explícito, como pueden ser el Word de Microsoft o el Writer de LibreOffice, sino en el almacenaje, procesado y presentación de cualquier información textual: una página web como la que estás leyendo ahora, los nombres de los menúes en cualquier programa, las celdas con etiquetas en una hoja de cálculo, un email… Es obvio que el texto es importante. Pero como todo en los ordenadores, el texto no puede estar compuesto más que por 0s y 1s, de modo que tenemos que buscar la forma de representar texto en forma binaria.
Advierto de que no vamos a ver todos los sistemas posibles, y menos en profundidad. Solo vamos a ver cómo son conceptualmente y a nombrar los más importantes.
Todos los sistemas utilizados para representar texto se basan en una simple tabla de correspondencia. Por ejemplo, podríamos inventarnos un sistema como:
Letra |
Representación |
A |
0000 0000 |
B |
0000 0001 |
C |
0000 0010 |
D |
0000 0011 |
… |
… |
La tabla debe tener tantas entradas como letras queramos representar en nuestro método. Supongo que no te sorprende, a estas alturas de la serie, si te digo que para la representación binaria se suelen usar 8 bits, y a veces 16 bits, 24 bits, 32 bits,… dependiendo del estándar que sigamos.
Así, si lo que quiero es representar la palabra “BACA”,[2] en nuestro particular sistema inventado, pondríamos 0000 0001 0000 0000 0000 0010 0000 0000. Fácil, ¿verdad?
El más utilizado de los sistemas de representación binaria es el ASCII (American Standard Code for Information Interexchange, código estándar americano para el intercambio de información). A menudo se le llama “texto plano”, por ser el más extendido de todos, pero ojo: eso del “texto plano” es una arbitrariedad, no es una definición precisa. Simplemente, cuando decimos “texto plano” todo el mundo sobreentiende que nos referimos a ASCII. A menudo se le llama también US-ASCII (algo así como “el ASCII de United States”, “el ASCII de Estados Unidos”), luego veremos por qué. También se le llama a veces ASCII7 o ASCII-de-7-bits… de nuevo, luego veremos por qué.[3]
En ASCII cada carácter se representa con 7 bits, según la siguiente tabla:
Posición (decimal) | Binario | Carácter | Notas |
000 | 0000000 | NUL | (Null char.) |
001 | 0000001 | SOH | (Start of Header) |
002 | 0000010 | STX | (Start of Text) |
003 | 0000011 | ETX | (End of Text) |
004 | 0000100 | EOT | (End of Transmission) |
005 | 0000101 | ENQ | (Enquiry) |
006 | 0000110 | ACK | (Acknowledgment) |
007 | 0000111 | BEL | (Bell) |
008 | 0001000 | BS | (Backspace) |
009 | 0001001 | HT | (Horizontal Tab) |
010 | 0001010 | LF | (Line Feed) |
011 | 0001011 | VT | (Vertical Tab) |
012 | 0001100 | FF | (Form Feed) |
013 | 0001101 | CR | (Carriage Return) |
014 | 0001110 | SO | (Shift Out) |
015 | 0001111 | SI | (Shift In) |
016 | 0010000 | DLE | (Data Link Escape) |
017 | 0010001 | DC1 | (XON)(Device Control 1) |
018 | 0010010 | DC2 | (Device Control 2) |
019 | 0010011 | DC3 | (XOFF)(Device Control 3) |
020 | 0010100 | DC4 | (Device Control 4) |
021 | 0010101 | NAK | (Negative Acknowledgement) |
022 | 0010110 | SYN | (Synchronous Idle) |
023 | 0010111 | ETB | (End of Trans. Block) |
024 | 0011000 | CAN | (Cancel) |
025 | 0011001 | EM | (End of Medium) |
026 | 0011010 | SUB | (Substitute) |
027 | 0011011 | ESC | (Escape) |
028 | 0011100 | FS | (File Separator) |
029 | 0011101 | GS | (Group Separator) |
030 | 0011110 | RS | (Request to Send)(Record Separator) |
031 | 0011111 | US | (Unit Separator) |
032 | 0100000 | SP | (Space) |
033 | 0100001 | ! | (exclamation mark) |
034 | 0100010 | “ | (double quote) |
035 | 0100011 | # | (number sign) |
036 | 0100100 | $ | (dollar sign) |
037 | 0100101 | % | (percent) |
038 | 0100110 | & | (ampersand) |
039 | 0100111 | ‘ | (single quote) |
040 | 0101000 | ( | (left opening parenthesis) |
041 | 0101001 | ) | (right closing parenthesis) |
042 | 0101010 | * | (asterisk) |
043 | 0101011 | + | (plus) |
044 | 0101100 | , | (comma) |
045 | 0101101 | - | (minus or dash) |
046 | 0101110 | . | (dot) |
047 | 0101111 | / | (forward slash) |
048 | 0110000 | 0 | |
049 | 0110001 | 1 | |
050 | 0110010 | 2 | |
051 | 0110011 | 3 | |
052 | 0110100 | 4 | |
053 | 0110101 | 5 | |
054 | 0110110 | 6 | |
055 | 0110111 | 7 | |
056 | 0111000 | 8 | |
057 | 0111001 | 9 | |
058 | 0111010 | : | (colon) |
059 | 0111011 | ; | (semi-colon) |
060 | 0111100 | < | (less than sign) |
061 | 0111101 | = | (equal sign) |
062 | 0111110 | > | (greater than sign) |
063 | 0111111 | ? | (question mark) |
064 | 1000000 | @ | (AT symbol) |
065 | 1000001 | A | |
066 | 1000010 | B | |
067 | 1000011 | C | |
068 | 1000100 | D | |
069 | 1000101 | E | |
070 | 1000110 | F | |
071 | 1000111 | G | |
072 | 1001000 | H | |
073 | 1001001 | I | |
074 | 1001010 | J | |
075 | 1001011 | K | |
076 | 1001100 | L | |
077 | 1001101 | M | |
078 | 1001110 | N | |
079 | 1001111 | O | |
080 | 1010000 | P | |
081 | 1010001 | Q | |
082 | 1010010 | R | |
083 | 1010011 | S | |
084 | 1010100 | T | |
085 | 1010101 | U | |
086 | 1010110 | V | |
087 | 1010111 | W | |
088 | 1011000 | X | |
089 | 1011001 | Y | |
090 | 1011010 | Z | |
091 | 1011011 | [ | (left opening bracket) |
092 | 1011100 | \ | (back slash) |
093 | 1011101 | ] | (right closing bracket) |
094 | 1011110 | ^ | (caret cirumflex) |
095 | 1011111 | _ | (underscore) |
096 | 1100000 | ` | |
097 | 1100001 | a | |
098 | 1100010 | b | |
099 | 1100011 | c | |
100 | 1100100 | d | |
101 | 1100101 | e | |
102 | 1100110 | f | |
103 | 1100111 | g | |
104 | 1101000 | h | |
105 | 1101001 | i | |
106 | 1101010 | j | |
107 | 1101011 | k | |
108 | 1101100 | l | |
109 | 1101101 | m | |
110 | 1101110 | n | |
111 | 1101111 | o | |
112 | 1110000 | p | |
113 | 1110001 | q | |
114 | 1110010 | r | |
115 | 1110011 | s | |
116 | 1110100 | t | |
117 | 1110101 | u | |
118 | 1110110 | v | |
119 | 1110111 | w | |
120 | 1111000 | x | |
121 | 1111001 | y | |
122 | 1111010 | z | |
123 | 1111011 | { | (left opening brace) |
124 | 1111100 | | | (vertical bar) |
125 | 1111101 | } | (right closing brace) |
126 | 1111110 | ~ | (tilde) |
127 | 1111111 | DEL | (delete) |
Así, si lo que queremos es representar la frase “hola mundo”, lo que haríamos es poner:
1101000 1101111 1101100 1100001 0100000 1101101 1110101 1101110 1100100 1101111
Fíjate en que tiene códigos distintos para las letras mayúsculas que para las minúsculas, de modo que que una “A” no es lo mismo que una “a”. Fíjate también en que tiene representación en forma de carácter de los números. Es decir, el carácter 0110101 es el carácter “5″, pero eso no es lo mismo que el cinco representado en binario (que sería 0000101). Y también hay representación para los caracteres especiales más habituales, como el punto, la coma, el signo más, el guión, el ampersand, etc.
Debes darte cuenta de que hay algunos caracteres que no son realmente letras, sino lo que se llama caracteres de control. Esos caracteres están codificados en la tabla, aún cuando es poco probable que alguna vez se almacenen, por ejemplo en un fichero de Word. Piensa por ejemplo en el carácter número 8 (0001000), que significa BS (backspace, borrar). En un fichero de texto el usuario va añadiendo letras y escribe “hola muns”. Como se ha equivocado, pulsa la tecla “borrar” de su teclado, pero lo que se hace no es almacenar el BS, sino quitar la última letra del fichero y dejar “hola mun”. ¿Para qué sirve entonces el carácter 8, el BS? Por ejemplo, puede servir para el teclado: cuando el usuario pulse la tecla “borrar”, el teclado le manda al ordenador 0001000.[4]
Existen muchos otros caracteres de control, y la mayoría no tienen un significado tan claro como este. Unos representan el retorno de carro, como el 13; otros indican un tabulador, como el 9; otros incluso significan literalmente “nada”, como el 0. Y la gran mayoría en realidad ni siquiera tienen uso hoy en día: son recuerdos de secuencias de control que antaño se necesitaban para aparatos obsoletos, pero hoy ya no.
Es posible que te preguntes por qué se usan 7 bits, cuando decimos que 8 es un número más habitual. El motivo es doble: por un lado, quienes inventaron esto se dieron cuenta de que con 7 bits, con 127 combinaciones, no solo tenían suficiente, sino que incluso les sobraban huecos para meter caracteres de control. Y por otro, dado que los antediluvianos sistemas de transmisión de la época eran relativamente poco fiables, pensaron que podían utilizar ese bit que sobraba como bit de paridad (no vamos a ver esto; si sabes lo que es, enhorabuena, y si no, no vamos a interrumpir la explicación, porque no nos hace falta para el resto de la serie).
El caso es que este ASCII está tan extendido que no solo es la base para los demás sistemas que veremos, sino que incluso cuando más adelante hagamos bloques más complejos, diremos que codifican según ASCII y nos valdrá para el ejemplo.
Esto estaba bien, funcionaba… salvo que no hablaras inglés, claro. Si por ejemplo eras de Zaragoza y lo que querías escribir en tu fichero era “¿Cómo estás?”, tenías un problema. Porque la tabla ASCII podía representar fácilmente los caracteres “normales”, pero no podía representar caracteres con tilde, el símbolo de apertura de interrogación, la c-con-cedilla (Ç), ni muchos otros, como la Ñ, sin ir más lejos. Así que a alguien se le ocurrió que podía aprovechar que los sistemas de transmisión ya eran mucho mejores para prescindir del bit de paridad, y utilizar ese bit adicional para tener otros 128 caracteres adicionales que añadir a la tabla. Por ejemplo, a alguien se le ocurrió que, en adición a la tabla ASCII estándar podía poner la siguiente:
Posicion (decimal) | Binario | Carácter | Notas |
128 | 10000000 | Ç | C cedilla |
129 | 10000001 | ü | u diaeresis |
130 | 10000010 | é | e acute |
131 | 10000011 | â | a circumflex |
132 | 10000100 | ä | a diaeresis |
133 | 10000101 | à | a grave |
134 | 10000110 | å | a ring |
135 | 10000111 | ç | c cedilla |
136 | 10001000 | ê | e circumflex |
137 | 10001001 | ë | e diaeresis |
138 | 10001010 | è | e grave |
139 | 10001011 | ï | i diaeresis |
140 | 10001100 | î | i circumflex |
141 | 10001101 | ì | i grave |
142 | 10001110 | Ä | A diaeresis |
143 | 10001111 | Å | A ring |
144 | 10010000 | É | E acute |
145 | 10010001 | æ | ae diphthong |
146 | 10010010 | Æ | AE diphthong |
147 | 10010011 | ô | o circumflex |
148 | 10010100 | ö | o diaeresis |
149 | 10010101 | ò | o grave |
150 | 10010110 | û | u circumflex |
151 | 10010111 | ù | u grave |
152 | 10011000 | ÿ | y diaeresis |
153 | 10011001 | Ö | O diaeresis |
154 | 10011010 | Ü | U diaeresis |
155 | 10011011 | ø | o slash |
156 | 10011100 | £ | Pound sterling sign |
157 | 10011101 | Ø | O slash |
158 | 10011110 | × | Multiplication sign |
159 | 10011111 | ƒ | Florin sign |
160 | 10100000 | á | a acute |
161 | 10100001 | í | i acute |
162 | 10100010 | ó | o acute |
163 | 10100011 | ú | u acute |
164 | 10100100 | ñ | n tilde |
165 | 10100101 | Ñ | N tilde |
166 | 10100110 | ª | Feminine ordinal |
167 | 10100111 | º | Masculine ordinal |
168 | 10101000 | ¿ | Question mark inverted |
169 | 10101001 | ® | Registered trademark symbol |
170 | 10101010 | ¬ | Logical NOT / End of line symbol |
171 | 10101011 | ½ | One half |
172 | 10101100 | ¼ | One quarter |
173 | 10101101 | ¡ | Exclamation inverted |
174 | 10101110 | « | Left angle quotes |
175 | 10101111 | » | Right angle quotes |
176 | 10110000 | ░ | Fill character light |
177 | 10110001 | ▒ | Fill character medium |
178 | 10110010 | ▓ | Fill character heavy |
179 | 10110011 | │ | Center box bar vertical |
180 | 10110100 | ┤ | Right middle box side |
181 | 10110101 | Á | A acute |
182 | 10110110 | Â | A circumflex |
183 | 10110111 | À | A grave |
184 | 10111000 | © | Copyright symbol |
185 | 10111001 | ╣ | Right box side double |
186 | 10111010 | ║ | Center box vertical double |
187 | 10111011 | ╗ | Upper right box corner double |
188 | 10111100 | ╝ | Lower right box corner double |
189 | 10111101 | ¢ | Cent sign |
190 | 10111110 | ¥ | Yen sign |
191 | 10111111 | ┐ | Upper right box corner |
192 | 11000000 | └ | Lower right box corner |
193 | 11000001 | ┴ | Middle box bottom |
194 | 11000010 | ┬ | Middle box top |
195 | 11000011 | ├ | Left middle box side |
196 | 11000100 | ─ | Center box bar horizontal |
197 | 11000101 | ┼ | Box intersection |
198 | 11000110 | ã | a tilde |
199 | 11000111 | Ã | A tilde |
200 | 11001000 | ╚ | Lower left box corner double |
201 | 11001001 | ╔ | Upper left box corner double |
202 | 11001010 | ╩ | Middle box bottom double |
203 | 11001011 | ╦ | Middle box top double |
204 | 11001100 | ╠ | Left box side double |
205 | 11001101 | ═ | Center box bar horizontal double |
206 | 11001110 | ╬ | Box intersection double |
207 | 11001111 | ¤ | International currency symbol |
208 | 11010000 | ð | Icelandic eth |
209 | 11010001 | Ð | Icelandic Eth |
210 | 11010010 | Ê | E circumflex |
211 | 11010011 | Ë | E diaeresis |
212 | 11010100 | È | E grave |
213 | 11010101 | € | i dotless |
214 | 11010110 | Í | I acute |
215 | 11010111 | Î | I circumflex |
216 | 11011000 | Ï | I diaeresis |
217 | 11011001 | ┘ | Lower right box corner |
218 | 11011010 | ┌ | Upper left box corner |
219 | 11011011 | █ | Solid fill character |
220 | 11011100 | ▄ | Solid fill character bottom half |
221 | 11011101 | ¦ | Broken vertical bar |
222 | 11011110 | Ì | I grave |
223 | 11011111 | ▀ | Solid fill character upper half |
224 | 11100000 | Ó | O acute |
225 | 11100001 | ß | German sharp s |
226 | 11100010 | Ô | O circumflex |
227 | 11100011 | Ò | O grave |
228 | 11100100 | õ | o tilde |
229 | 11100101 | Õ | O tilde |
230 | 11100110 | µ | Greek mu |
231 | 11100111 | þ | Icelandic thorn |
232 | 11101000 | Þ | Icelandic Thorn |
233 | 11101001 | Ú | U acute |
234 | 11101010 | Û | U circumflex |
235 | 11101011 | Ù | U grave |
236 | 11101100 | ý | y acute |
237 | 11101101 | Ý | Y acute |
238 | 11101110 | ¯ | Macron (overbar) |
239 | 11101111 | ´ | Acute accent |
240 | 11110000 | | Soft hyphen |
241 | 11110001 | ± | Plus or minus sign |
242 | 11110010 | ‗ | Double underscore |
243 | 11110011 | ¾ | Three quarters |
244 | 11110100 | ¶ | Pilcrow sign |
245 | 11110101 | § | Paragraph sign |
246 | 11110110 | ÷ | Divide sign |
247 | 11110111 | ¸ | Cedilla |
248 | 11111000 | ° | Degree sign |
249 | 11111001 | ¨ | Diaeresis |
250 | 11111010 | · | Center dot |
251 | 11111011 | ¹ | Superscript 1 |
252 | 11111100 | ³ | Superscript 3 |
253 | 11111101 | ² | Superscript 2 |
254 | 11111110 | ■ | Solid square |
255 | 11111111 | Required Space |
No solo tenía ahora espacio suficiente para esos caracteres adicionales, sino que hasta le sobraba espacio para poner algunos caracteres más chulos, como los superíndices, las formas geométricas… en fin, una idea excelente.
Sí, excelente. Salvo que no hubo “alguien” que tuviera esa idea. La tuvo tooooodo el mundo. Cada fabricante propuso su tabla (la que hemos puesto arriba es la que se llama CP850, Code Page 850, propuesta por IBM y usada antaño por Microsoft en sus sistemas para Europa). Todas parecidas, todas con la misma idea… pero todas distintas. Y no solo pienses en distintos fabricantes, sino incluso en distintos países. Para un europeo, la e-con-tilde puede ser importantísima, pero para un japonés… pues no le sirve para mucho. Él necesita sus propios símbolos. Peor aún: incluso si tuviera su propia tabla, 256 caracteres son demasiado pocos para la mayoría de los idiomas asiáticos. E incluso en distintos modelos del mismo fabricante: dicho fabricante (sí, uno de tres letras, azules para más detalles, por ejemplo) usaba una tabla en sus sistemas grandes y otra distinta en sus sistemas microinformáticos. En fin, un caos de cuidado.
Finalmente la ISO estandarizó todo esto en sus normas ISO-8859-1, ISO-8859-2, ISO-8859-3… Seguía habiendo un montón de normas distintas para los distintos países, pero al menos todos los fabricantes usaban la misma. A estas cosas se las llamó ASCII extendido (o dependiendo del contexto, simplemente ASCII) y al ASCII original se le llamó ASCII-de-7-bits o US-ASCII o simplemente ASCII-original. Por si te lo encuentras por ahí, la ISO-8859-15 es la habitual en los países occidentales.
Aquello funcionó, más o menos, pero seguía echándose en falta un sistema que los unificara a todos, que permitiera representarlos todos ellos de forma uniforme. Entonces es cuando se inventó Unicode.
No vamos a ver Unicode en detalle, porque es complicadísimo. Simplificándolo, puedes pensar en Unicode como la tabla de ASCII, pero con miles de caracteres posibles, y que por lo tanto no se representa con solo 8 bits, sino con muchos más. Además, esas tablas tienen distintas formas de codificación, que llamamos UTF-8, UTF-16,… e incluso algunas de ellas tienen sub-formas. No vamos a verlas en detalle (y, además, lo que estamos contando es una simplificación muy burda), pero quédate con la idea de que es posible representar un carácter como un chorro determinado de bits, siempre que nos pongamos todos de acuerdo en cuál es el chorro de bits que corresponde con cada carácter.
No puedo terminar el capítulo sin nombrar uno de los mejores artículos que se ha escrito jamás sobre este tema: The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets (No Excuses!). Tras ese título tan largo se esconde “el mínimo absoluto que todo desarrollador de software definitiva e indudablemente debe conocer sobre Unicode y los códigos de caracteres (¡Sin excusas!)”. Fue escrito por Joel Spolsky hace casi diez años, pero sigue siendo válido. Si te defiendes con el inglés, léelo y te prometo que no te arrepentirás por haber perdido el tiempo.
En el próximo artículo terminaremos este interludio sobre representación con otras notaciones que no son binarias, pero que nos será muy útiles.
- Hemos dejado fuera intencionadamente los números imaginarios, porque no es habitual que los ordenadores los manejen explícitamente, sino que simplemente mantienen por separado la parte real y la parte imaginaria, y listo. [↩]
- Sí, Baca, con B. Es ese artefacto que se pone encima de la carrocería de los automóviles para llevar bultos. Baca. [↩]
- Hubo otros códigos similares, como por ejemplo el EBCDIC de IBM, pero que, a pesar del evidente empuje de sus promotores, no se impusieron. Bueno, no se impusieron en otros ordenadores que no fueran los mainframes de IBM: en ese ecosistema el 99% o más del texto sigue estando codificado en EBCDIC. [↩]
- Ojo: un teclado moderno real no funciona exactamente así. Solo es un ejemplo académico. [↩]
The Computador mágico XII – Representación binaria IV: texto by , unless otherwise expressly stated, is licensed under a Creative Commons Attribution-Noncommercial-No Derivative Works 2.5 Spain License.
{ 7 } Comentarios
Fantástico artículo, J. Además, me has tocado la fibra al hablar de ASCII y Unicode: soy un FANÁTICO de Unicode.
Y también, GRACIAS por el enlace al artículo de Joel Spolsky. Lo he disfrutado como un niño.
Me ha gustado mucho el artículo, muy bien redactado y, como Saul, me he leído entero también el enlace. Un tipo muy interesante el Joel este, y con más razón que un santo.
Joel Spolsky fue program manager de excel y luego, entre otras cosas, ha fundado StackOverflow (que, si te dedicas a programar, necesitas conocer sí o sí). Su blog Joel on Software es una de las referencias del mundillo. En fin, que no es un recién llegado.
No sabía que Joel Spolsky hubiese fundado StackOverflow, yo he conocido hace poco serverfault, su hermano para sysadmins y me encanta.
Joel tiene un wiki donde se van traduciendo sus artículos: http://local.joelonsoftware.com/wiki/El_M%C3%ADnimo_Minimorum_Que_Todo_Desarrollador_De_Software_Positiva_Y_Absolutamente_Debe_Saber_Acerca_De_Unicode_Y_Conjuntos_De_Caracteres._%28%C2%A1Sin_Excusas!%29
Si @J, lo segundo que hice tras leer su artículo fue ver su “Bio” y ya vi que era fundador de StackOverflow. Ahí me dí cuenta de su importancia.
Bastante claro y conciso!
Escribe un comentario