(-1)1 • (1 + 0.010101)
(-1)1 • (1 + 0.010101)
(-1)1 • (1 + 0.010101)
Create successful ePaper yourself
Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.
Somma di numeri floating point<br />
Algoritmi di moltiplicazione e divisione per<br />
numeri interi<br />
Standard IEEE754<br />
" Standard IEEE754: Singola precisione (32 bit)<br />
si riescono a rappresentare numeri 2.0 10 <strong>•</strong> 2 -38 ÷ 2.0 10 <strong>•</strong> 2 38<br />
" Standard IEEE754: Doppia precisione (64 bit)<br />
si riescono a rappresentare numeri 2.0 10 <strong>•</strong> 2 -308 ÷ 2.0 10 <strong>•</strong> 2 308
Lo standard IEEE754 sceglie di:<br />
Standard IEEE754<br />
" rendere d 0 = 1 implicito, mettendo un circuito che somma<br />
automaticamente 1 alla cifra espressa dalla mantissa.<br />
" usare la notazione polarizzata per rappresentare l’esponente:<br />
essa consente di ordinare e confrontare gli esponenti in modo<br />
facile<br />
- Singola precisione: polarizzazione pari a 127 = 01111111 2<br />
- Doppia precisione: polarizzazione pari a 1023 = 01111111111 2<br />
" riservare l’esponente 00...0 per rappresentare lo zero<br />
" riservare l’esponente 11...1 per casi particolari<br />
(fuori dall’insieme dei valori rappresentabili)<br />
Standard IEEE754<br />
Per leggere un numero in notazione polarizzata si usa la regola:<br />
(-1) S<strong>•</strong>(1+m)<strong>•</strong>2 (e - polazizzazione)<br />
Esempio: Quale numero decimale rappresenta la seguente sequenza di bit,<br />
letta secondo lo standard IEEE754?<br />
esponente: 10001101 2 = 128+8+4+1=141 10<br />
mantissa: 1+0.10011 2 = 1+0.59375 = 1.59375 10<br />
Quindi il numero è: 1.59375 10 <strong>•</strong> 2 (141 - 127) = 1.59375 10 <strong>•</strong> 2 14
Standard IEEE754<br />
Per scrivere un numero in notazione polarizzata bisogna ricordarsi di:<br />
" non rappresentare la parte intera della mantissa<br />
(il bit 1 prima della virgola)<br />
" aggiungere all’esponente la polarizzazione<br />
Esempio: scrivere - 10. 625 10 in notazione floating point, usando lo<br />
standard IEEE754<br />
- 10. 625 10 = - (10 + 0.5 +0.125) = - (10 + 1/2 + 1/8) =<br />
= - 1010. 101 2 = - 1. 010101 <strong>•</strong> 2 3 =<br />
= (-1) 1 <strong>•</strong> (1 + <strong>0.010101</strong>) <strong>•</strong> 2 (3+127)<br />
= (-1) 1 <strong>•</strong> (1 + <strong>0.010101</strong>) <strong>•</strong> 2 (130)<br />
Somma di numeri razionali in virgola mobile<br />
Algoritmo che esegue la somma<br />
di due numeri razionali :<br />
Esempio: eseguire 5 10 + 3.625 10<br />
assumendo una precisione di 4 bit<br />
5 = 101 = 1.01 <strong>•</strong> 2 10 2 2<br />
3.625 = 11.101 <strong>•</strong> 2 10 2 0 = 1.1101<strong>•</strong> 21 = 0.11101<strong>•</strong> 22 Allora: 1.01000 +<br />
0.11101 =<br />
----------------<br />
10.00101 <strong>•</strong> 22 Normalizzazione: 1.000101 <strong>•</strong> 2 3<br />
Arrotondamento: 1.0001 <strong>•</strong> 2 3
Somma di numeri razionali in virgola mobile<br />
Esercizio: eseguire la somma di<br />
Somma di numeri razionali in virgola mobile<br />
+
Somma di numeri razionali in virgola mobile<br />
La limitatezza della precisione dell’aritmetica dei calcolatori porta ad avere dei<br />
problemi con le proprietà delle operazioni aritmetiche.<br />
Ad esempio, la somma in virgola mobile non è associativa, cioè, in generale, non è<br />
vero che x+(y+z) = (x+y)+z<br />
I problemi nascono quando si vogliono sommare due numeri molto grandi di segno<br />
opposto, con altro un numero molto piccolo<br />
x = 1.5 10 <strong>•</strong> 10 38<br />
y = - 1.5 10 <strong>•</strong> 10 38 con x,y,z espressi in singola precisione<br />
z = 1.0 10<br />
x+(y+z) = -1.5 <strong>•</strong> 10 38 + (1.5 <strong>•</strong> 10 38 + 1.0)<br />
= -1.5 <strong>•</strong> 10 38 + 1.5 <strong>•</strong> 10 38 = 0.0 10<br />
(x+y)+z = ( -1.5 <strong>•</strong> 10 38 + 1.5 <strong>•</strong> 10 38 ) + 1.0<br />
= 0.0 + 1.0 = 1.0 10<br />
Moltiplicazioni e divisioni tra numeri interi<br />
Abbiamo visto che le ALU sono in grado di eseguire operazioni di<br />
somma<br />
sottrazione<br />
salto<br />
confronto<br />
operazioni logiche: AND e OR<br />
Ma ci sono altre due operazioni fondamentali che devono essere<br />
implementate: MOLTIPLICAZIONE e DIVISIONE di numeri interi<br />
Vediamo come vengono realizzate...
Moltiplicazione tra numeri interi<br />
Come funziona l’algoritmo “carta e penna” per la moltiplicazione ?<br />
105 * Moltiplicando<br />
204 = Moltiplicatore<br />
---------<br />
420<br />
000<br />
210<br />
----------<br />
21420 Prodotto<br />
I passi dell’algoritmo sono i seguenti :<br />
" considerare le cifre del moltiplicatore una alla volta, da destra a sinistra<br />
" moltiplicare il moltiplicando per la singola cifra del moltiplicatore<br />
" scalare il prodotto intermedio di una cifra alla volta verso sx<br />
rispetto ai precedenti prodotti intermedi ottenuti<br />
" il prodotto si ottiene dalla somma di tutti i prodotti intermedi<br />
Cosa succede in base 2 ?<br />
1011 * Moltiplicando 11 10<br />
101 = Moltiplicatore 5 10<br />
---------<br />
1011<br />
0000<br />
1011<br />
----------<br />
110111 Prodotto 55 10<br />
Osservazioni:<br />
Moltiplicazione tra numeri interi<br />
" il numero delle cifre del prodotto è molto più grande rispetto alle<br />
cifre del moltiplicatore e del moltiplicando.<br />
Ignorando i bit di segno si ha:<br />
moltiplicatore (n bit) moltiplicando (m bit) ==> prodotto (n+m bit)<br />
" Poichè si vogliono rappresentare sia gli operandi che il risultato<br />
delle operazioni su 32 bit bisogna fare attenzione ai casi di<br />
OVERFLOW !
Cosa succede in base 2 ?<br />
1011 * Moltiplicando 11 10<br />
101 = Moltiplicatore 5 10<br />
---------<br />
1011<br />
0000<br />
1011<br />
----------<br />
110111 Prodotto 55 10<br />
Osservazioni: (continua)<br />
Moltiplicazione tra numeri interi<br />
" Poichè ci sono solo le cifre 0 e 1 ogni passo della moltiplicazione<br />
viene semplificato<br />
- si mette una copia del moltiplicando nella posizione opportuna<br />
se la cifra “corrente” del moltiplicatore è 1<br />
- si mette 0 in posizione opportuna se la cifra corrente del<br />
moltiplicatore è 0<br />
Si basa su:<br />
Moltiplicazione tra numeri interi (primo algoritmo)<br />
" shift a destra del moltiplicatore per<br />
considerare, una alla volta, tutte le<br />
sue cifre (dalla meno significativa<br />
alla più significativa)<br />
" shift a sinistra del moltiplicando per<br />
rappresentare correttamente i<br />
prodotti parziali<br />
Moltiplicando Moltiplicatore Prodotto<br />
1011 0101 0000<br />
1011 0101 1011<br />
10110 0010 1011<br />
10110 0010 1011<br />
101100 0001 1011<br />
101100 0001 110111<br />
1011000 0000 110111<br />
1011000 0000 110111<br />
10110000 0000 110111
Moltiplicazione tra numeri interi (primo algoritmo)<br />
Il circuito che implementa l’algoritmo della pagina precedente ? :<br />
Moltiplicazione tra numeri interi (secondo algoritmo)<br />
Il primo algoritmo di moltiplicazione usa un registro a 64bit per il moltiplicando e,<br />
conseguentemente, una ALU a 64bit per la somma<br />
Infatti, Il moltiplicando viene scalato a sinistra di una cifra ad ogni passo,<br />
in modo da non influenzare i bit meno significativi del prodotto<br />
Il secondo algoritmo, invece, per arrivare allo stesso obiettivo, prevede<br />
di scalare il prodotto a destra<br />
In tal modo il moltiplicando può restare fisso e quindi sono necessari<br />
solo 32bit sia per corrispondente registro che per la ALU<br />
Risultato: il circuito diventa più semplice e la moltiplicazione più veloce<br />
Vediamo in dettaglio il secondo algoritmo:
Moltiplicazione tra numeri interi (secondo algoritmo)<br />
Si basa su:<br />
" shift a destra del moltiplicatore per<br />
considerare, una alla volta, tutte le<br />
sue cifre (dalla meno significativa<br />
alla più significativa)<br />
" shift a destra del prodotto per<br />
non influenzare le cifre meno<br />
significative dei prodotti parziali<br />
" ad ogni passo vengono sommati<br />
solo i 32bit più significativi del<br />
prodotto<br />
Moltiplicando Moltiplicatore Prodotto<br />
1011 0101 00000000<br />
1011 0101 10110000<br />
1011 0010 01011000<br />
1011 0010 01011000<br />
1011 0001 00101100<br />
1011 0001 11011100<br />
1011 0000 01101110<br />
1011 0000 01101110<br />
1011 0000 00110111<br />
Moltiplicazione tra numeri interi (secondo algoritmo)<br />
Il circuito che implementa il secondo algoritmo per la moltiplicazione è:
Moltiplicazione tra numeri interi (terzo algoritmo)<br />
Il secondo algoritmo spreca inizialmente i 32bit bassi del prodotto, che sono<br />
esattamente lo spazio necessario per memorizzare il moltiplicatore<br />
Man mano che lo spazio sprecato del prodotto diminuisce (per via dello shift a<br />
destra) diminuiscono anche le cifre significative del moltiplicatore<br />
Il terzo algoritmo prevede quindi la memorizzazione del moltiplicatore<br />
nella parte bassa del prodotto<br />
Con questa soluzione:<br />
" si elimina un registro (quello che prima memorizzava il moltiplicatore)<br />
" il test sulla cifra del moltiplicatore da considerare ad ogni passo<br />
diventa il test sul bit meno significativo del prodotto<br />
Vediamo nei dettagli il terzo (e ultimo!!!) algoritmo per la moltiplicazione...<br />
Si basa su:<br />
Moltiplicazione tra numeri interi (terzo algoritmo)<br />
" memorizzazione del moltiplicatore<br />
nella parte bassa del prodotto<br />
" shift a destra del prodotto per<br />
non influenzare le cifre meno<br />
significative dei prodotti parziali<br />
" ad ogni passo vengono sommati<br />
solo i 32bit più significativi del<br />
prodotto<br />
Moltiplicando Prodotto<br />
1011 00000101<br />
1011 10110101<br />
1011 01011010<br />
1011 01011010<br />
1011 00101101<br />
1011 11011101<br />
1011 01101110<br />
1011 01101110<br />
1011 00110111
Moltiplicazione tra numeri interi (terzo algoritmo)<br />
Il circuito che implementa il terzo algoritmo per la moltiplicazione è:<br />
Moltiplicazione tra numeri interi<br />
Fino ad ora NON abbiamo considerato il SEGNO di moltiplicando e<br />
moltiplicatore<br />
Il modo più semplice di gestire il segno è il seguente:<br />
" convertire moltiplicando e moltiplicatore in numeri positivi<br />
" eseguire il la moltiplicazione<br />
" stabilire il segno del prodotto secondo la regola dei segni,<br />
ricordando i segni originali<br />
ATTENZIONE: gli algoritmi possono effettuare solo 31 iterazioni, lasciando i<br />
segni fuori dal calcolo
Divisione tra numeri interi<br />
Come funziona l’algoritmo di divisione “carta e penna” ?<br />
Dividendo Divisore Quoziente<br />
100 : 6 = 016<br />
10<br />
06<br />
40<br />
36<br />
4 Resto<br />
Si ha: Dividendo = Quoziente * Divisore + Resto<br />
da cui: Resto = Dividendo - Quoziente * Divisore<br />
I passi dell’algoritmo sono i seguenti:<br />
" considerare le cifre del dividendo, partendo dalla cifra più significativa<br />
" vedere quante volte il divisore sta nel gruppo di cifre del dividendo<br />
" scrivere la cifra corrispondente nel quoziente<br />
" sottrarre il multiplo del divisore dal dividendo<br />
" alla fine il resto è minore del divisore<br />
ATTENZIONE: la divisione per ZERO causa errore<br />
Cosa succede in base 2 ?<br />
Dividendo Divisore Quoziente<br />
1101001 : 101 = 0010101<br />
11<br />
110<br />
101<br />
11<br />
110<br />
101<br />
10<br />
101<br />
101<br />
0 Resto<br />
Osservazioni:<br />
Divisione tra numeri interi<br />
" Quante volte il divisore sta nella porzione di dividendo considerata?<br />
Ci sono solo due alternative: 0 volte oppure 1 volta<br />
Questo semplifica l’algoritmo di divisione<br />
" Consideriamo per ora solo numeri positivi
Divisione tra numeri interi (primo algoritmo)<br />
Supponiamo di dover dividere 1101 2 : 0101 2 ( cioè 13 10 : 5 10 )<br />
Il primo algoritmo di divisione procede come segue:<br />
" quoziente memorizzato su un registro a 32 bit e inizializzato a zero<br />
quoziente = 0000<br />
" divisore memorizzato sulla parte alta di un registro a 64 bit<br />
divisore = 01010000<br />
" resto memorizzato su reg. a 64 bit, inizializzato col valore del dividendo<br />
resto = 00001101 = dividendo<br />
" il calcolatore non capisce “al volo” quando il divisore è più piccolo della<br />
porzione di dividendo considerata. Ad ogni passo fa la sottrazione<br />
(dividendo - divisore) e controlla il segno del risultato<br />
" ad ogni passo si esegue lo shift a destra di una posizione del divisore<br />
resto = 00001101 resto = 00001101 resto = 00001101<br />
divisore = 01010000 divisore = 00101000 divisore = 00010100<br />
10111101 11100101 11111001<br />
se il segno è positivo ==> shift a sinistra del quoziente e inserimento di 1<br />
se il segno è negativo ==> shift a sinistra del quoziente e inserimento di 0<br />
+ ripristino del valore precedente di resto<br />
Divisione tra numeri interi (primo algoritmo)<br />
Resto Divisore Quoziente<br />
00001011 01010000 0000<br />
01010000<br />
10111101<br />
00001011 00101000 0000<br />
00101000<br />
11100101<br />
00001011 00010100 0000<br />
00010100<br />
11111001<br />
00001011 00001010 0000<br />
00001010<br />
00000011 00000101 0001<br />
00000101<br />
11111110<br />
00000011 00000010 0010
Divisione tra numeri interi (primo algoritmo)<br />
Il circuito che implementa il primo algoritmo è il seguente:<br />
Divisione tra numeri interi (altri algoritmi)<br />
" Analogamente al caso della moltiplicazione, sono stati studiati dei<br />
raffinamenti per l’algoritmo della divisione<br />
" L’obiettivo è sempre quello di semplificare e rendere più veloce il<br />
circuito che implementa la divisione<br />
" Vediamo solo le modifiche ai circuiti, e non gli algoritmi in dettaglio<br />
(li trovate comunque sul libro di testo)
Divisione tra numeri interi (secondo algoritmo)<br />
Circuito relativo al secondo algoritmo:<br />
Divisione tra numeri interi (terzo algoritmo)<br />
Circuito relativo al terzo algoritmo:
Divisione tra numeri interi<br />
Fino ad ora non abbiamo considerato il SEGNO di dividendo e divisore<br />
Analogamente al caso della moltiplicazione, il modo più semplice di<br />
gestire il segno è il seguente:<br />
" convertire dividendo e divisore in numeri positivi<br />
" eseguire la divisione lasciando i bit di segno fuori dal calcolo<br />
" stabilire il segno del quoziente mediante la regola dei segni,<br />
ricordando i segni originali (quoziente negativo se i segni di dividendo<br />
e divisore sono discordi, positivo altrimenti)<br />
" stabilire il segno del resto mediante la seguente regola:<br />
dividendo e resto devono avere lo stesso segno, indipendentemente<br />
dal segno del divisore e del quoziente