Sei sulla pagina 1di 6

Especificación IEEE-754, para representar valores

decimales en punto flotante de simple precisión.

Ing. Cosme Rafael Marcano Gamero, MSc, DEA.


cosmemarcano@gmail.com

En este escrito se explica la especificación utilizada por la mayoría de


los lenguajes de programación disponibles en el mercado para
representación los así llamados números reales, en los dispositivos de
almacenamiento, ya sea primario (RAM) o secundario (discos duros, etc.).

La especificación IEEE-754 establece que los 32 bits que ocupa un valor


decimal, en formato de simple precisión, es la siguiente:

Bit31: bit de signo: 1 = -, 0 = +


Bit30-23: 8 bits para el exponente, desplazado en 127.
Bit22-0: 23 bits para la mantisa normalizada.

EJEMPLO 1.

Tomemos como ejemplo a -1. En primer lugar, la parte entera (sin signo)
de -1.0 es 1. Como no hay que mover la coma decimal,
1 * 20  exp onente  127  0  127  01111111b

Por último, como -1 es negativo, el bit de signo, es decir, el bit 31,


será igual a 1.

Entonces:
B F 8 0 0 0 0 0
1 0 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
3 3 2 2 1 0
1 0 3 2

En vista de que los valores usualmente son almacenados terminando con el


byte más significativo (lo cual es referido a veces como bigendian),
entonces la representación de -1,0 en formato IEEE-754 sería igual a
BF800000, y se colocaría en memoria o en archivos binarios como:
000080BF, como se puede ver en la siguiente figura.

Cosme Rafael Marcano Gamero.


Figura 1. Representación en un archivo binario (20reales.bin),
de veintidós valores decimales en formato IEEE-754.

En la Figura 1 aparecen las representaciones de los siguientes valores


decimales en formato IEEE-754: -1, -0.875, -0.75, -0.625, -0.5, -0.375, -
0.25, -0.125, 0, 0.125, 0.25, 0.375, 0.5, 0.625, 0.75, 0.875, 1, 1.125,
1.25, 1.375, 1.7 y 123.45.

Nótese que cada valor ocupa cuatro bytes, es decir, 32 bits. Cada byte
aparece representado en forma de dos dígitos hexadecimales. Así, por
ejemplo, la representación de -1.0, o sea, 000080BF, corresponde a los
cuatro primeros bytes a partir del inicio del archivo (posición
00000000).

EJEMPLO 2.

Como otro ejemplo, hallemos la representación en formato IEEE-754 del


penúltimo valor almacenado en este archivo, es decir, 1.7.

En primer lugar, la parte entera de 1.7 es 1. Para normalizar este valor


no hay que mover la coma decimal, entonces:
1 * 20  exp onente  127  0  127  01111111b

La conversión de la parte decimal (0.7), viene a ser:

Bit x i acumulado
x * 2 i  1,2,3,...
1
1  1* 2 0.5000000
2
0  0*2 0.5000000
3
1  1* 2 0.625000000
4
1  1* 2 0.687500000
5
0  0*2 0.687500000

Cosme Rafael Marcano Gamero.


6
0  0*2 0.687500000
7
1  1* 2 0.695312500
8
1  1* 2 0.699218750
9
0  0*2 0.699218750
10
0  0*2 0.699218750
11
1  1* 2 0.699707031

 1* 2
12
1 0.699951172
13
0  0*2 0.699951172
14
0  0*2 0.699951172
15
1  1* 2 0.699981689
16
1  1* 2 0.699996948
17
0  0*2 0.699996948
18
0  0*2 0.699996948
19
1  1* 2 0.699998856
20
1  1* 2 0.699999809
21
0  0*2 0.699999809
22
1  1* 2 0.699999928
23
0  0*2 0.699999928

Parte decimal convertida: 0.699999928

Por último, como 1.7 es positivo, el bit de signo, es decir, el bit 31,
será igual a 0.

Entonces:

3 F D 9 9 9 9 A
0 0 1 1 1 1 1 1 1 1 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1 0 1 0
3 3 2 2 1 0
1 0 3 2

Y se almacenará en el archivo con la siguiente apariencia: 9A 99 D9 3F,


como se muestra en la Figura 1.

Nótese que en ambos ejemplos se omitió, de acuerdo a lo establecido en la


especificación IEEE-754, la representación del “1.”, después de haberse
normalizado la mantisa.

Recuerde que cada bit de la representación de la parte decimal del valor


que se desea convertir al formato IEEE-754, constituye un factor que
multiplica a potencias negativas de dos. Esto es, si los 23 bits de la
parte decimal de 1.7 (que, en este caso es exactamente igual a la
mantisa) son los siguientes:

Cosme Rafael Marcano Gamero.


1 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1 0 1 0

Entonces, el equivalente decimal de esa representación será:


1 2 3 4 22 23
1 * 2  0 * 2  1 * 2  1 * 2  ...  1 * 2  0*2  0.7

EJEMPLO 3.

Por último, como un ejemplo de conversión de un valor cuya parte entera


requiere más de un dígito binario, tomemos el 123.45, que es el último
valor almacenado en el archivo 20reales.bin (ver Figura 1).

En este caso, la parte entera es igual a 123 = 0111 1011b (7Bh).


Para obtener la representación de la parte decimal, observamos que:

Bit x i acumulado
x * 2 i  1,2,3,...
1
0  0*2 0.000000000
2
1  1* 2 0.250000000
3
1  1* 2 0.375000000
4
1  1* 2 0.437500000
5
0  0*2 0.437500000
6
0  0*2 0.437500000
7
1  1* 2 0.445312500
8
1  1* 2 0.449218750
9
0  0*2 0.449218750
10
0  0*2 0.449218750
11
1  1* 2 0.449707031

 1* 2
12
1 0.449951172
13
0  0*2 0.449951172
14
0  0*2 0.449951172
15
1  1* 2 0.449981689
16
1  1* 2 0.449989319
17
0  0*2 0.449989319

Parte decimal convertida: 01110011001100110 = 0.449989319

Entonces: 123.45 = 111 1011.01110011001100110

Al normalizar, 111 1011 queda:


1.111011 * 2  exp onente  127  6  133  10000101b
6

Quitando el “1.”, y agregando la parte decimal, nos queda:

Cosme Rafael Marcano Gamero.


1110110111 0011 0011 0010

El bit de signo es 0, por ser 123.45 un valor positivo.

4 2 F 6 E 6 6 6
0 1 0 0 0 0 1 0 1 1 1 1 0 1 1 0 1 1 1 0 0 1 1 0 0 1 1 0 0 1 1 0

3 3 2 2 1 0
1 0 3 2

Finalmente, la representación de 123.45 en formato IEEE-754, que resultó


ser igual a 42 F6 E6 66, es almacenado como 66 E6 F6 42, de acuerdo a lo
mostrado en la Figura 1.

COMENTARIOS SOBRE EL PROGRAMA QUE GENERÓ EL ARCHIO BIMARIO 20reales.bin

Inclusión de la librería en donde se definen la clase de objeto

#include <fstream>

Definición de la estructura requerida para escribir y leer variables de


tipo real (float) en/desde un archivo binario en C++:

struct real {
float valor;
};

Declaración de un apuntador a la estructura requerida para escribir y


leer variables de tipo real (float) en/desde un archivo binario en C++:

real* preal = new real();

Declaración de una variable que contendrá el nombre del archivo binario


en donde se almacenarán los valores reales:

static const char *BINARIO = "20reales.bin";

Apertura del archivo de escritura. Nóyese que se abrirá con el nombre


“salida”. Con este nombre (manejador) se hará referencia al archivo
físico “20reales.bin” dentro del programa. Nótese también que se abre con
los atributos ios_base::out para indicar que es un archivo de salida
(sobre el cual se escribirán datos), ios_base::binary para indicar que
los datos deben ser almacenados en formato binario, y el atributo
ios_base::trunc, para indicar que los datos deben ser truncados (no
redondeados) a la longitud exacta en bytes que ocupen.

std::ofstream salida(BINARIO, ios_base::out | ios_base::binary |


ios_base::trunc);
if (salida==NULL){
cout << "Error: no pude abrir Archivo de salida." << endl;
return(-1);

Cosme Rafael Marcano Gamero.


}
Asignación del valor inicial de la variable real a ser escrita en el
archivo binario.

preal->valor=-1.0;
for (int contador=0; contador<20; contador++){
// escribir el contenido de la variable en el archivo
salida.write((const char*)preal, sizeof(real));
// mostrar en pantalla el mismo valor
printf("\n%10.7f", preal->valor);
// incrementar en 0.125 el valor de la variable. Esto quiere decir que
// el segundo valor a almacenar en el archivo será -0.875, luego, -
// -0.750, etc.
preal->valor+= 0.125;
}
preal->valor+= 0.2; // aquí alcanza el valor de 1.7
printf("\n%10.7f", preal->valor);
salida.write((const char*)preal, sizeof(real));

// ejemplo con parte entera de más de un dígito binario


preal->valor = 123.45;
printf("\n%10.7f", preal->valor);
salida.write((const char*)preal, sizeof(real));

// cerrar archive explícitamente (aunque C++ cierra automáticamente los


// archives que estén abiertos al finalizar la ejecución del programa).
salida.close();

La lectura de variables reales desde un archivo binario se realiza de


manera similar a la escritura y queda planteado como ejercicio.

MOTA:
Para poder utilizar printf("\n%10.7f", preal->valor), se debe incluir el
archivo de prototipos stdo.h el cual no es orioui de C++, sino de C
estándar. Esta función, sin embargo, permite controlar a voluntad del
programador (y las características del lenguaje de programación, por
supuesto) el número de posiciones decimales que se quiere mostrar en
pantalla. En este sentido, es más potente que la función std::cout de
C++. Para una comparación más detallada entre printf()y std::cout se
puede consultar el artículo “Comentarios sobre printf()y std::cout”m que
está disponible en cosmemarcano.wordpress.com.

COMENTARIO FINAL.

Afortunadamente, la conversión de los números con decimales (también


llamados números reales) es automática y transparente al programador en
lenguaje de de alto nivel, como Fortran, Pascal y C. No obstante, a la
hora de diseñar un prototipo de hardware que se desee conectar a una
computadora u otro circuito digital estándar, es necesario respetar el
formato utilizado para cada tipo de datos, de manera que se pueda
compartir información entre tales dispositivos.

Cosme Rafael Marcano Gamero.

Potrebbero piacerti anche