2012-01-07 37 views
7

Come sottrarre i numeri IEEE 754?Come sottrarre i numeri IEEE 754?

Ad esempio: 0,546875 - 32,875 ...

-> 0,546875 è 0 01111110 10001100000000000000000 in IEEE-754

-> -32,875 è 1 10.000.111 01000101111000000000000 in IEEE-754

Quindi come si fa la sottrazione? So che devo rendere uguali entrambi gli esponenti, ma cosa faccio dopo? 2 'Complemento di -32.875 mantissa e aggiungi con 0.546875 mantissa?

+0

possibile duplicato di [Implementazione della sottrazione in virgola mobile] (http://stackoverflow.com/questions/591046/implementing-floating-point-subtraction) –

+1

Perché non devi semplicemente sottrarre? Perché preoccuparsi di eseguire l'operazione di complemento a 2? –

+0

@Carl Questo è l'unico modo in cui so sottrarre in binario -.- ' –

risposta

21

In realtà non è diverso da quello che fai con carta e penna. Va bene un po 'diverso

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

il numero maggiore domina, spostare mantissa del numero minore fuori nel secchio bit fino esponenti corrispondono

1.234*10^5 - 0.05432*10^5 

quindi eseguire la sottrazione delle mantisse

1.234 - 0.05432 = 1.17968 
1.17968 * 10^5 

Quindi normalizzare (che in questo caso è)

Che era con numeri di base 10.

In float IEEE, precisione singola

123400 = 0x1E208 = 0b11110001000001000 
11110001000001000.000... 

normalizzare che dobbiamo spostare il decimale 16 posti alla cosiddetta sinistra

1.1110001000001000 * 2^16 

L'esponente è polarizzato in modo da aggiungere 127 a 16 e ottieni 143 = 0x8F.È un numero positivo, quindi il bit del segno è uno 0 iniziamo a costruire il numero in virgola mobile IEEE il numero iniziale 1 prima del decimale è implicito e non utilizzato in una precisione singola, ci sbarazziamo di esso e manteniamo la frazione

bit di segno, esponente mantissa

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

e se si scrive un programma per vedere che cosa un computer cose 123400 è che si ottiene la stessa cosa:

0x47F10400 123400.000000 

Così sappiamo l'esponente e mantissa per la prima operando '

Ora la seconda operando

5432 = 0x1538 = 0b0001010100111000 

Normalizzazione, spostamento decimali 12 bit del

1010100111000.000 
1.010100111000000 * 2^12 

L'esponente è polarizzato aggiungi 127 e ricevere 139 = 0x8B = 0b10001011

mettere tutto insieme

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

E un programma/compilatore di computer fornisce lo stesso

0x45A9C000 5432.000000 

Ora per rispondere alla tua domanda. Utilizzando i componenti dei numeri in virgola mobile, ho restaurato l'implicita 1 qui perché ne abbiamo bisogno

0 10001111 111100010000010000000000 - 0 10001011 101010011100000000000000 

Dobbiamo allineare le nostre cifre decimali, proprio come in grado di scuola prima di poter sottrarre così in questo contesto che si dover spostare il piccolo numero esponente destra, lanciando bit mantissa fuori dall'estremità fino esponenti corrispondono

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 

Ora possiamo sottrarre mantisse. Se i bit del segno corrispondono, in realtà dovremo sottrarre se non corrispondono, quindi aggiungiamo. Corrispondono a questa sarà una sottrazione.

computer eseguono una sottrazione utilizzando la logica Inoltre, invertendo il secondo operatore sulla strada verso la vipera e affermando il riporto nel bit, in questo modo:

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

Ed ora, proprio come con carta e penna permette di eseguire il componente aggiuntivo

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

o farlo con esadecimale sulla calcolatrice

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 po 'di come funziona l'hardware, dato che questo è stato davvero un sottrarre usando il sommatore, invertiamo anche il bit di esecuzione (o su alcuni computer lo lasciano così com'è). Quindi portare a termine 1 è una buona cosa, praticamente la scartiamo. Se fosse stato uno zero, avremmo avuto bisogno di più lavoro. Non abbiamo un risultato così la nostra risposta è davvero 0xE66800.

lascia molto rapidamente vedere che un altro modo, invece di invertire e l'aggiunta di uno lascia solo usare una calcolatrice

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

Cercando di visualizzarla ho forse fatto peggio. Il risultato della sottrazione mantissa è 111.001.100.110,1 mille miliardi (0xE66800), non c'era movimento nel bit più significativo si finisce con un numero a 24 bit in questo caso con l'msbit di un 1. No normalizzazione. Per normalizzare è necessario spostare la mantissa sinistra o destra fino a 24 bit allinea con i più significativi 1 in quella più a sinistra posizione, regolando l'esponente per ogni turno bit.

Ora stripping 1. po 'fuori la risposta che abbiamo messo insieme le parti

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

Se avete seguito insieme scrivendo un programma per fare questo, ho fatto pure. Questo programma viola lo standard C utilizzando un'unione in modo improprio. Sono riuscito a farla franca con il mio compilatore sul mio computer, non mi aspetto che funzioni sempre.

#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); 
} 

E il nostro risultato corrisponde l'uscita del programma di cui sopra, abbiamo ottenuto un 0x47E66800 farlo a mano

0x47F10400 123400.000000 
0x45A9C000 5432.000000 
0x47E66800 117968.000000 

Se si sta scrivendo un programma per sintetizzare la matematica in virgola mobile il programma può eseguire la sottrarre, non dovete fare l'invertito e aggiungere più una cosa, sopra complica come abbiamo visto sopra. Se ottieni un risultato negativo anche se devi giocare con il bit del segno, inverti il ​​risultato, quindi normalizza.

Quindi:

1) estrarre il parti, segno, esponente, mantissa.

2) Allineare le vostre cifre decimali sacrificando bit mantissa dal numero con il più piccolo esponente, spostamento che mantissa verso destra fino a quando gli esponenti corrispondono

3) essendo un'operazione di sottrazione se i bit del segno sono gli stessi allora si esegue una sottrazione, se i bit del segno sono diversi si esegue un'aggiunta delle mantisse.

4) se il risultato è zero, allora la risposta è uno zero, codificare il valore IEEE per lo zero come risultato, in caso contrario:

5) normalizzare il numero, SHIFT la risposta a destra oa sinistra (la risposta può essere 25 bit da un 24 bit aggiungere/togliere, aggiungere/sottrarre può avere un cambiamento drammatico per normalizzare, sia quella giusta o più bit a sinistra) fino a quando si dispone di un numero di 24 bit con quello più significativo giustificato a sinistra. 24 bit è per il galleggiante a precisione singola. Il modo più corretto per definire la normalizzazione è lo spostamento verso sinistra o verso destra finché il numero non assomiglia a 1.qualcosa. se tu avessi 0.001 si sposterebbe a sinistra 3, se aveste 11.10 ci si sposterà aumenta sinistra a destra 1. una spostare la vostra esponente, uno spostamento a destra diminuisce esso. Non diverso da quando abbiamo convertito da numero intero a float sopra.

6) per la singola precisione rimuovere il principale 1. dalla mantissa, se l'esponente è traboccato, allora si ottiene nella costruzione di una segnalazione nan. Se i bit del segno erano diversi e hai eseguito un add, allora devi occuparti di capire il bit del segno risultato. Se come sopra tutto va bene, basta inserire il segno bit, esponente e mantissa nel risultato

Moltiplicare e dividere è diverso, hai chiesto informazioni subract, quindi è tutto quello che ho coperto.

+0

Questa risposta ha molti aspetti, ma salta gli effetti dell'arrotondamento. Anche senza arrotondamento, la Fase 2) è finita semplificata. La sottrazione può annullare il bit iniziale in modo che il bitbit spostato non venga sacrificato, ma mantenuto. Esempio di 4 bit: pensate a 1.000 - 0.1111 -> 0.0001, no 0.001 – chux

Problemi correlati