20.05.2013 Views

(-1)1 • (1 + 0.010101)

(-1)1 • (1 + 0.010101)

(-1)1 • (1 + 0.010101)

SHOW MORE
SHOW LESS

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

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!