2012-01-07 93 views
7

¿Cómo restar números IEEE 754?Cómo restar números IEEE 754?

Por ejemplo: 0,546875 - 32.875 ...

-> 0,546875 es 0 01111110 10001100000000000000000 en el estándar IEEE-754

-> -32.875 es 1 10000111 01000101111000000000000 en el estándar IEEE-754

Entonces, ¿cómo hago la resta? Sé que tengo que hacer que ambos exponentes sean iguales, pero ¿qué hago después de eso? 2'Complemento de -32.875 mantisa y agregar con 0.546875 mantisa?

+0

posible duplicado de [Implementando la resta de coma flotante] (http://stackoverflow.com/questions/591046/implementing-floating-subtraction) –

+1

¿Por qué no simplemente resta? ¿Por qué molestarse en hacer la operación de complemento a 2 usted mismo? –

+0

@Carl Esa es la única forma en que sé cómo restar en binario -.- ' –

Respuesta

21

Realmente no es diferente de lo que haces con lápiz y papel. Está bien un poco diferente

123400 - 5432 = 1.234*10^5 - 5.432*10^3 

el número más grande domina, cambiar mantisa del número más pequeño fuera en el cubo poco hasta los exponentes coinciden

1.234*10^5 - 0.05432*10^5 

luego realizar la resta con las mantisas

1.234 - 0.05432 = 1.17968 
1.17968 * 10^5 

Luego normalizar (que en este caso es)

Eso estaba con base 10 números.

En IEEE de coma flotante, precisión simple

123400 = 0x1E208 = 0b11110001000001000 
11110001000001000.000... 

normalizar que tenemos que cambiar el decimal 16 lugares hacia la izquierda para

1.1110001000001000 * 2^16 

El exponente es empujado así que agregamos 127 a 16 y obtener 143 = 0x8F.Es un número positivo por lo que el bit de signo es un 0 empezamos a construir el número de coma flotante IEEE el 1 antes de que el decimal esté implícito y no se use en precisión simple, nos deshacemos de él y guardamos la fracción

bit de signo, exponente, mantisa

0 10001111 1110001000001000... 
0100011111110001000001000... 
0100 0111 1111 0001 0000 0100 0... 
0x47F10400 

y si se escribe un programa para ver lo que una cosas informáticos 123400 es que se consigue lo mismo:

0x47F10400 123400.000000 

por lo que sabemos el exponente y la mantisa por primera operando '

Ahora el segundo operando

5432 = 0x1538 = 0b0001010100111000 

Normalizar, SHIFT decimales 12 bits dejaron

1010100111000.000 
1.010100111000000 * 2^12 

El exponente está sesgada añadir 127 y obtener 139 = 0x8B = 0b10001011

poner todo junto

0 10001011 010100111000000 
010001011010100111000000 
0100 0101 1010 1001 1100 0000... 
0x45A9C00 

Y un programa de computadora/compilador da el mismo

0x45A9C000 5432.000000 

Ahora para responder a su pregunta. El uso de las partes componentes de los números de punto flotante, he restaurado la implícita 1 aquí porque lo necesitamos

0 10001111 111100010000010000000000 - 0 10001011 101010011100000000000000 

Tenemos que alinear nuestras cifras decimales al igual que en la escuela primaria antes de que podamos restar lo que en este contexto se tiene que cambiar el número más pequeño exponente de la derecha, lanzando bits de la mantisa fuera de la final hasta que los exponentes coinciden

0 10001111 111100010000010000000000 - 0 10001011 101010011100000000000000 
0 10001111 111100010000010000000000 - 0 10001100 010101001110000000000000 
0 10001111 111100010000010000000000 - 0 10001101 001010100111000000000000 
0 10001111 111100010000010000000000 - 0 10001110 000101010011100000000000 
0 10001111 111100010000010000000000 - 0 10001111 000010101001110000000000 

Ahora podemos restar las mantisas. Si los bits del signo coinciden, vamos a restar realmente si no coinciden, entonces agregamos. Ellos coinciden con esto será una resta.

ordenadores realizan una sustracción mediante el uso de la lógica Además, invirtiendo el segundo operador en el camino a la víbora y afirmando el acarreo en el bit, así:

      1 
    111100010000010000000000 
+ 111101010110001111111111 
========================== 

Y ahora igual que con papel y lápiz permite realizar el añadir

1111000100000111111111111 
    111100010000010000000000 
+ 111101010110001111111111 
========================== 
    111001100110100000000000 

o hacerlo con hexagonal en su calculadora

111100010000010000000000 = 1111 0001 0000 0100 0000 0000 = 0xF10400 
111101010110001111111111 = 1111 0101 0110 0011 1111 1111 = 0xF563FF 
0xF10400 + 0xF563FF + 1 = 0x1E66800 
1111001100110100000000000 =1 1110 0110 0110 1000 0000 0000 = 0x1E66800 

Un poco sobre cómo funciona el hardware, ya que esto fue realmente un sustraer usando el sumador, también invertimos el bit de ejecución (o en algunas computadoras lo dejan como está). Entonces, llevar a cabo un 1 es algo bueno, básicamente lo descartamos. Si hubiera sido un cero, habríamos necesitado más trabajo. No tenemos una ejecución así que nuestra respuesta es realmente 0xE66800.

deja muy rápidamente ver que de otra manera, en lugar de invertir y la adición de uno sólo permite utilizar una calculadora

111100010000010000000000 - 000010101001110000000000 = 
0xF10400 - 0x0A9C00 = 
0xE66800 

Al tratar de visualizarlo que tal vez fue peor. El resultado de resta de mantisa es 111001100110100000000000 (0xE66800), no hubo movimiento en el bit más significativo que terminamos con un número de 24 bits en este caso con el msbit de 1. Sin normalización. Para normalizar, debe desplazar la mantisa hacia la izquierda o hacia la derecha hasta que los 24 bits se alineen con el 1 más significativo en la posición más a la izquierda, ajustando el exponente para cada desplazamiento de bit.

Ahora pelar el 1. poco alejado de la respuesta ponemos las piezas juntas

0 10001111 11001100110100000000000 
01000111111001100110100000000000 
0100 0111 1110 0110 0110 1000 0000 0000 
0x47E66800 

Si usted ha estado siguiendo escribiendo un programa para hacer esto, lo hice también. Este programa infringe el estándar C al usar una unión de una manera incorrecta. Me salí con la mía con mi compilador en mi computadora, no espero que funcione todo el tiempo.

#include <stdio.h> 

union 
{ 
    float f; 
    unsigned int u; 
} myun; 


int main (void) 
{ 
    float a,b,c; 

    a=123400; 
    b= 5432; 

    c=a-b; 

    myun.f=a; printf("0x%08X %f\n",myun.u,myun.f); 
    myun.f=b; printf("0x%08X %f\n",myun.u,myun.f); 
    myun.f=c; printf("0x%08X %f\n",myun.u,myun.f); 

    return(0); 
} 

Y nuestro resultado coincide con la salida del programa anterior, tenemos un 0x47E66800 hacerlo a mano

0x47F10400 123400.000000 
0x45A9C000 5432.000000 
0x47E66800 117968.000000 

Si está escribiendo un programa para sintetizar los cálculos de punto flotante de su programa puede realizar la resta, no tienes que hacer la inversión y agregar más una cosa, más lo complica como vimos arriba. Si obtiene un resultado negativo aunque necesita jugar con el bit de signo, invierta su resultado, luego normalícelo.

Así:

1) Extraer las partes, signo, exponente, mantisa.

2) Alinear sus cifras decimales mediante el sacrificio de bits de la mantisa del número con el exponente más pequeño, cambio que mantisa hacia la derecha hasta que los exponentes coinciden

3) es una operación de resta, si los bits de signo son los mismos a continuación, usted realiza un resta, si los bits del signo son diferentes, realiza un agregado de las mantisas.

4) si el resultado es un cero, entonces su respuesta es un cero, codificar el valor IEEE para el cero como el resultado, de lo contrario:

5) normalizar el número, cambio la respuesta a la derecha o izquierda (La respuesta puede ser de 25 bits a partir de una suma/resta de 24 bits, agregar/restar puede tener un cambio dramático para normalizar, ya sea uno a la derecha o muchos bits a la izquierda hasta que tenga un número de 24 bits con el más significativo justificado a la izquierda. 24 bits es para flotador de precisión simple. La forma más correcta de definir la normalización es desplazarse hacia la izquierda o hacia la derecha hasta que el número se parezca a 1.algo. si tuvieras 0.001 cambiarías a la izquierda 3, si tuvieras 11.10 cambiarías a la derecha 1. un desplazamiento a la izquierda aumenta tu exponente, un desplazamiento a la derecha lo disminuye. No es diferente a cuando convertimos de un número entero a flotar arriba.

6) para la precisión simple, quite el 1. principal de la mantisa, si el exponente se ha desbordado, entonces se entra en la construcción de una señalización nan. Si los bits del signo fueron diferentes y realizó un agregado, entonces tiene que lidiar con calcular el bit del signo de resultado. Si como todo arriba está bien, simplemente coloque el signo de bit, exponente y mantisa en el resultado

Multiplicar y dividir es diferente, ha preguntado acerca de subract, por lo que es todo lo que cubrí.

+0

Esta respuesta entra en muchos aspectos, pero omite los efectos del redondeo. Incluso sin redondeo, el paso 2) está simplificado. La resta puede cancelar el bit de avance de manera que el MSBit desplazado no se sacrifica, sino que se retiene. Ejemplo de 4 bits: Piense en 1,000 - 0.1111 -> 0.0001, no 0.001 – chux

Cuestiones relacionadas