1.4.1. Representación de la información

Toda la información que almacena y lee un ordenador la maneja en código binario, esto es, como una sucesión de ceros y unos. Esto supone que el sistema binario es la base predominante en informática. Se tratará bajo este epígrafe:

  • Cómo representar números en distintos sistemas de numeración.

  • Cómo códificar caracteres alfanuméricos en código binario.

1.4.1.1. Sistemas de numeración

Un sistema de numeración es un conjunto de reglas y símbolos que permite representar todos los números válidos. Los modernos sistemas de numeración son posicionales, en los cuales el valor del símbolo dependen de la posición que ocupa. Por ejemplo, en el número decimal 11, el primero 1 representa 1 decena (o sea, su valor es 10 unidades), mientras que el segundo 1 tiene por valor 1 unidad.

Por base se entiende la cantidad de símbolos distintos usandos para representar los números. El sistema que habitualmente utilizamos es el sistema decimal o en base 10 en que los 10 símbolos son 0, 1, 2, 3, 4, 5, 6, 7, 8 y 9.

De nuestro interés son:

Nombre

Base

Símbolos

Razón de su interés

Binario

2

0 y 1

Es el que internamente usan los ordenadores para representar la información.

Octal

8

0-7

Es muy sencilla su conversión a binario y viceversa, y la representación es más compacta.

Decimal

10

0-9

Es el usado habitualmente por el ser humano.

Hexadecimal

16

0-9, A-F

Es muy sencilla su conversión a binario y viceversa, y la representación es más compacta.

En estos sistemas de numeración los números se representan de este modo.

Decimal

Binario

Octal

Hexadecimal

0

0

0

0

1

1

1

1

2

10

2

2

3

11

3

3

4

100

4

4

5

101

5

5

6

110

6

6

7

111

7

7

8

1000

10

8

9

1001

11

9

10

1010

12

A

11

1011

13

B

12

1100

14

C

13

1101

15

D

14

1110

16

E

15

1111

17

F

16

10000

20

10

17

10001

21

11

18

10010

22

12

19

10011

23

13

20

10100

24

14

Fundamentalmente, el interés sobre estos métodos radica en:

  • Saber cómo convertir números entre los sistemas binario y decimal.

  • Saber cómo convertir entre octal o hexadecimal y binario, ya que los dos primeros sistemas se suelen usar para escribir de una forma más compacta cifras binarias.

Nota

En textos sin formato en los que no pueden usarse subíndices para notar cuál es la base en la que está expresado un número (p.e. expresar un hexadecimal con la forma \(\mathit{C1A}_{16)}\)), es común usar esta notación:

  • Binario: Antecediendo el número con 0b: 0b11011.

  • Octal: Antecediendo el número con un cero: 0745.

  • Decimal: Se escribe de forma normal.

  • Hexadecimal: Antecediendo el número con 0x: 0xC1A.

1.4.1.1.1. Método general de conversión a decimal

1.4.1.1.2. Cuenta de la vieja (entre binario y decimal)

1.4.1.1.3. Conversión entre octal y binario

1.4.1.1.4. Conversión entre hexadecimal y binario

1.4.1.1.5. Ejercicios sobre sistemas de numeración

  1. Escriba los veinte números que suceden a:

    N

    101100012)

    17638)

    BFF216)

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

  2. Haga otro tanto con:

    N

    11111002)

    6658)

    6E516)

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

  3. Lleve a cabo la conversión entre los cuatro sistemas de numeración

    Binario

    Octal

    Decimal

    Hexadecimal

    11011101

    123

    F2

    333

    11111001

    564

    10F

    553

    671

    250

    D2

    101001110

1.4.1.2. Tipos de datos

Todos la información la almacena el ordenador en forma de ceros y unos. Sin embargo, los datos son de distinta naturaleza, esto es, de distinto tipo, y, en consecuencia, deben existir distintos mecanismos para transformar la información almacenada (exclusivamente) en forma binaria. Los datos, fundamentalmente, son:

  • Números enteros.

  • Números reales.

  • Caracteres.

También hemos de tener presente que, cuando pensamos representar un tipo de dato, debemos prefijar con cuántos bytes deseamos expresarlo. Por ejemplo, podríamos decidir que, para representar/almacenar números enteros, utilizaremos 2 bytes. Sin ser muy exhaustivos, esta podría ser una tabla resumen:

Tipos de datos

Tipo

Tamaño (bytes)

Carácter

1

Entero corto

2

Entero

4

Entero largo

8

Real (simple)

8

Real (doble)

16

Obviamente, cuanto mayor sea el tamaño que dediquemos a codificar el dato, mayor será el rango de números (o caracteres) que podamos almacenar.

Nota

La tabla admite muchísimas puntualizaciones. Ya veremos, por ejemplo, que la estrategia moderna de codificar caracteres es usar un tamaño varible.

1.4.1.2.1. Representación de números enteros

Si no existieran los número negativos, sería sumamente simple: bastaría con escribir la expresión binaria del número tal como la hemos estudiando anteriormente y ya está. Por ejemplo, si ocupásemos un byte para codificar el número 123, se almacenaría como 01111011. Sin embargo, existen los negativos, por lo que hay que decidir estrategias para representarlos. Las principales son cuatro, aunque modernamente se usa la tercera:

Bit para el signo

Es la más sencilla de entender. Simplemente, se reserva un bit para representar el signo: 0 para el positivo y 1 para el negativo, lo cual nos dejaría 7 bits (supuestos los 8 que hemos decidido que usaremos para codificar) para representar la magnitud, que la representamos simplemente haciendo las conversiones antes vistas. De este modo:

Número

Representacion

123

01111011

-123

11111011

El problema de esta representación es que las operaciones de suma y resta no pueden tratarse del mismo modo y que, además, hay dos maneras de representar el 0.

Complemento a uno

Consiste en reservar el primer bit que será siempre 0 para números positivos y representar la magnitud con los restantes del modo ya visto al tratar las conversiones entre bases. Por tanto, la representación de números naturales es exactamente la vista para el caso anterior. Los números negativos son el complementario de su correspondiente positivo, esto es, el que se obtiene cambiando bit a bit 0 por 1 y 1 por 0:

Número

Representacion

123

01111011

-123

10000100

Esta estrategia presenta la ventaja de que sumas y restas pueden reducirse a una misma operación: \(50-8\) puede reducirse a la suma \(50+(-8)\). También el 0 tiene dos representaciones (00000000 y 11111111).

Nota

En realidad, hay que tener una pequeña prevención al restar. La operación anterior (50-8) es la suma binaria \(00110010 + 11110111\) que es 100101001, número que ocupa 9 cifras. Eso es, en realidad, un acarreo, porque representamos los números con 8 cifras. El 1 del acarreo hay que sumarlo a las 8 cifras para obtener el resultado: \(00101001 + 1 = 00101010\), que es justamente 42.

Complemento a dos

Semejante al complemento a uno con la diferencia de que los números negativos se obtienen de sumar 1 a la representanción del número negativo en complemento a uno. Por tanto:

Número

Representacion

123

01111011

-123

10000101

Con esta representación no es necesario reintroducir el acarreo para restar y, además, no hay más que una forma de representar el 0.

Exceso a X

Consiste en representar todo como números positivos y establecer el 0 no en 00000000, sino en la cifra binaria intermedia que deje un intervalo simétrico de números positivos y negativos. Así, si representamos con 8 bits los números binarios van del 00000000 al 11111111, lo que en principio sería del 0 al 255. Pero no, decidimos que vamos de -127 a 128 con lo que 00000000 representa el -127 y 11111111, el 128. En este caso, usamos el exceso a 127 y el 0 estaría representado por el binario 01111111 (\(127 - 127 = 0\)).

1.4.1.2.2. Representación de números reales

Los números con decimales estamos acostumbrados a representarlos con una parte entera y una parte decimal (llamada mantisa) separadas ambas por una coma (o un punto). Por ello, escribimos 1.234, 45.678 o -56783.3456. Del mismo modo que creamos números con decimales en base 10, podríamos crear números binaros con decimales. Por ejemplo, \(1101.101_2\) representa el número decimal \(1*2^3+1*2^2+0*2^1+1*2^0+1*2^{-1}+0*2^{-2}+1*2^{-3} = 13.625\).

Sin embargo, esta representación habitual es poco apropiada porque, dado que deberemos escoger un tamaño para almacenar los números (por ejemplo, 32 bits), si queremos poder representar números muy grandes (la parte entera será grande), entonces tendremos que acortar la precisión que proporciona la mantisa; y viceversa. Por este motivo, en informática se utiliza la notación de coma flotante.

La notación de coma flotante consiste en adjuntar a la expresión del número una potencia de diez que exprese su magnitud. Por ejemplo, -56783.3456 podríamos expresarlo como \(-56.783456*10^3\). Si, además, indicamos la potencia de diez de suerte que la parte entera sólo tenga una cifra, entonces la notación esta normalizada. De este modo los ejemplos anteriores en esta notación normalizada se expresarían como \(1.234*10^0\), \(4.5678*10^1\) y \(-5.67833456*10^4\). Como todas las cantidades están expresadas en base decimal, la base del exponente siempre será diez, por lo que estas cantidades tienes tres variables:

  • El signo. Como hay dos posibilidades, podemos notar al «+» con 0 y al «-» con 1.

  • El significado, esto es, el número significativo. La coma siempre está en la misma posición, así que podríamos prescindir de usarla.

  • El exponente.

Por tanto, un numero real lo podemos expresar como la combinación de tres reales: signo, mantisa y exponente:

Coma flotante (base decimal)

Número

Signo

Exponente

Significado

1.234

0

0

1234

45.678

0

1

45678

-56783.3456

1

4

567833456

Esta es, conceptualmente, la explicación de la notación de coma flotante. Sin embargo, los ordenadores sólo utilizan el sistema binario para representanción, así que debemos repensar todo esto en ese sistema. Partamos de nuestro ejemplo 13.625, cuya representación binaria es \(1101.101_2\). o, lo que es lo mismo, \(1.101101*2^3\). Pero, ¿qué hacen ese 2 y ese 3 en esa representación binaria? Del 2 directamente podemos prescindir como prescindimos cuando pensábamos en decimal del 10. El 3 forzosamente sí habrá que pasarlo a binario (\(11_2\)). Por tanto:

Coma flotante (base binaria)

Número

Signo

Exponente

Significado

1101.101

0

11

1101101

Esto es una primera aproximación, pero los ordenadores no pueden crear tablitas como nosotros para representar un número: simplemente reservan una cantidad de bits y escriben en ellos ceros o unos. Lo que se hace, para evitar problemas es reservar una cantidad fija de bits para cada componente. La cantidad para el signo es evidente: 1 y para los otros dos componentes de la notación depende de la cantidad de bits que usemos:

Tipo

Signo

Exponente

Mantisa

Total

Coma flotante simple

1

8

23

32

Coma flotante de doble precisión

1

11

52

64

Nota

La columna para expresar el tamaño del «significado» se ha nombrado como «mantisa» (o sea, sólo la parte decimal). Más adelante veremos por qué.

Por tanto, si usamos el tipo simple, una mejor aproximación a cómo notan estos números los ordenadores es:

Coma flotante

Número

Signo

Exponente

Significado

1101.101

0

00000011

11011010000000000000000

Obsérvese que hemos añadido al significado los ceros a la derecha y no a la izquierda como comúnmente se hace. Esto se debe a que el punto decimal siempre estará entre el primer bit y el segundo, por lo que los ceros a la derecha, en realidad. son ceros de relleno. Por otro lado, la notación siempre está normalizada, por lo que el primer dígito de la mantisa si usamos binario siempre será 1. Por tanto, ¿para qué escribirlo y perder un bit? En consecuencia, se prescinde del 1 que tiene la parte entera y sólo se escribe la parte decimal, esto es, la mantisa. La representación quedaría finalmente así:

Coma flotante

Número

Signo

Exponente

Mantisa

1101.101

0

00000011

10110100000000000000000

Yuxtaponiendo las tres partes para constituir el dato de 32 bits, tenemos la representación que hace del número el ordenador: 00000001110110100000000000000000. Hemos soslayado una cuestión para hacer más simples las explicaciones: ¿qué ocurre cuando el exponente es negativo (p.e. el número 0.0011011)? No hay bit para el signo del exponente: se usa el complemento a dos.

Por último, deben tenerse presente algunas particularidades:

  • El exponente define la magnitud del número (cuanto mayor, más grande).

  • La mantisa define la precisión del numero (cuanto mayor, más preciso).

  • La regla general es que la notación siempre es normalizada y, además, sólo se expresa la mantisa. Esto, sin embargo, haría imposible representar el 0, ya que la parte entera siempre se sobrentiende 1. Por ese motivo, hay dos excepciones:

    • Cuando el exponente tiene todos sus bits a 0, no se sobrentiende parte entera y la mantisa representa en realidad al significado. Por tanto, todos los bits a 0 de signo, exponente y mantisa significan \(+0\) y lo mismo pero con el bit del signo a 1, \(-0\).

    • Cuando el exponente tiene todos sus bits a 1:

      • y la mantisa es 0, se entiende \(+\infty\) o \(-\infty\) dependiendo del bit de signo.

      • y la mantisa no es 0, se entiende NaN.

1.4.1.2.3. Representación de caracteres

Además de la representación numérica, en los ordenadores es necesario también representar caracteres alfanuméricos, esto es, letras, números, símbolos de puntuación o símbolos de control (p.e. un cambio de línea). Como la información siempre debe tratarse en binario, para llevarlo a cabo se definen tablas de codificación que relacionan cada símbolo con el código binario que lo representa.

Un sistema de codificación es un sistema normalizado que permite codificar en formato binario un determinado conjunto de caracteres. Hay distintos sistemas de codificación:

De ancho fijo

Son sistemas de codificación en los que los códigos binarios tienen todos la misma longitud, esto es, el mismo número de cifras binarias.

ASCII

Es una sistema de codificación de ancho de 7 bits capaz de representar caracteres de control (los 32 primeros códigos y el último), de puntuación y letras del alfabeto inglés. Su importancia radica en que la mayoría de los sistemas de codificación son compatibles con él.

Ver también

Consulte la tabla de codificación ASCII

Como la información suele agruparse en grupos de 8 bits (1 byte), hay toda una serie de sistemas de codificación de ancho fijo de 8 bits, cuyos primeros 128 caracteres coinciden con la codificación ASCII. A estos sistemas de codificación suele denominárseles ASCII extendido.

ASCII extendido

Forma genérica de denominar a un conjunto dispar de sistemas de codificación de 8 bits cuyos primeros 128 códigos coinciden con el ASCII estándar y, por tanto, son compatibles con el ASCII original de 7 bits. Los más comunes son:

CP 437

Sistema de codificación de 8 bits que extiende ASCII y cuyos 128 códigos superiores se dedican a caracteres para el diseño de tablas, símbolos matemáticos, algunas letras griegas (usadas en matemáticas y física) y algunas vocales acentuadas que existen en las lenguas de Europa occidental, pero insuficientes para escribir correctamente en estas lenguas. Era el usado en las primeros version de inglesas de MS-DOS.

CP 850

Semejante al anterior, pero sustituye algunos caracteres para el dibujo de tablas y letras griegas por los caracteres que faltan para lograr escribir completamente en las lenguas de Europa occidental. Se usaba en las versiones europeas de MS-DOS.

Sistemas ISO/IEX 8859

Conjunto de 15 sistemas de ASCII extendido cada uno de los cuales orientado a escribir un conjunto distinto de lenguas. El ISO-8859-1 es el encargado de codificar los caracteres necesarios para escribir en las lenguas europeas occidentales; y el ISO-8859-15 es una modificación de este para codificar el símbolo del euro y algunas pocas letras acentuadas.

CP 1252 Windows-1252

SIstema de codificación de ASCII extendido usado en sistemas Windows hasta época más o menos reciente, muy semejante a ISO-8859-1, del cual difería en unos pocos caracteres de control.

UTF-32

Sistema de códificación de ancho fijo de 32 bits que es capaz de codificar los símbolos necesarios para escribir en todas las lenguas más algunos otros símbolos matemáticos, musicales, etc. Pese a esa ventaja, presenta dos desventajas:

  • Como cualquier carácter se representa con 4 bytes, aumenta considerablemente el tamaño para almacenar cualquier fichero de caracteres, aunque este sólo incluya caracteres muy simples.

  • Es incompatible con ASCII.

De ancho variable

Al contrario de los anteriores, todos sus códigos binarios no tienen la misma longitud. Los dos sistemas de codificación de ancho variables más usados son:

UTF-16

Sistema de codificación de ancho variable que usa 2 ó 4 bytes para codificar todos los caracteres existentes. Para optimizar el tamaño, los caracteres que usan códigos de 2 bytes son los que permiten escribir en las lenguas de mayor uso. Tiene el inconveniente de que es incompatible con ASCII.

UTF-8

Sistema de codificación de ancho variable que usa códigos de 1, 2, 3 ó 4 bytes para representar todos los caracteres existentes:

  • Codifica con 1 bytes los carácteres ASCII usando los mismos códigos, con lo que logra compatibilidad con este sistema de codificación.

  • Codifica con 2 bytes caracteres para escribir en las lenguas europeas, el árabe o el hebreo.

  • Códifica con 3 bytes caracteres no linguísticos de uso común y lenguas como el chino o el japonés.

  • Códifica con 4 bytes en resto de caracteres unicode.

Dado que optimiza el tamaño, es compatible con ASCII y permite codificar cualquier carácter unicode es el sistema de codificación que usan los sistemas operativos modernos. Como contrapartida, ofrece el peor rendimiento al ser computado.