Corso di per il corso di Laurea di Ingegneria Meccanica Codifiche per numeri decimali: virgola fissa e mobile Università degli Studi di Udine - A.A. 2010-2011 Docente Ing. Sandro Di Giusto Ph.D. 1
Rappresentazioni dei numeri con virgola Come abbiamo detto, l'ultimo aspetto da considerare nella codifica dei numeri binari, è quello relativo ai numeri razionali, con virgola In generale esistono almeno due notazioni distinte per gestire i numeri con virgola A virgola fissa (fixed point) A virgola mobile (floating point) Nelle prossime slide confronteremo i due metodi, analizzando i principi di funzionamento, i pregi ed i difetti 2
Rappresentazione dei numeri in virgola fissa Il metodo a virgola fissa ha il pregio di essere molto semplice da implementare ed anche da capire (per l'uomo) Ha lo svantaggio di essere assolutamente poco flessibile e preciso ed inadatto per descrivere contemporaneamente numeri molto piccoli o molto grandi Il principio di funzionamento è molto semplice: Oltre a definire una profondità di parola per la rappresentazione di un numero, si definisce anche in modo statico/fisso la profondità della parte intera e di quella frazionaria In questo modo si attribuiscono su n bit totali, n i bit per descrivere la parte intera (al solito in complemento a 2) e n f = n-n i bit per descrivere la parte frazionaria La parte intera si scrive secondo le regole standard finora viste, mentre la parte frazionaria si scrive tenendo presente che il numero è sempre positivo ed usando esponenti negativi per la base 2 3
Rappresentazione dei numeri in virgola fissa La parte frazionaria segue infatti lo stesso principio che si usa con il sistema numerico decimale Es. 1.56 10 = 1*10 0 +5*10-1 +6*10-2 Nel caso binario la differenza sta nel fatto che la base per l'appunto è 2 e non 10 Es. 1.00101 2? 10 1*2 0 +0*2-1 +0*2-2 +1*2-3 +0*2-4 +1*2-5 = 1+0.125+0.03125 = 1.15625 10 Convertire un numero dalla base binaria a quella decimale richiede quindi la solita formula, leggermente rimaneggiata: n f n i 1 N 10 = k =n f n f 1 d k 2 k n f k =0 Convertire invece un numero dalla base decimale a quella binaria è un'operazione non immediata e soprattutto che non offre garanzia di correttezza, una volta fissata una profondità n f n 1 d k 2 k n f= k=0 d k 2 k n f 4
Rappresentazione dei numeri in virgola mobile Molto più interessante è invece la rappresentazione in virgola mobile, che quindi analizzeremo in maggior dettaglio L'idea della notazione in virgola mobile è quella di utilizzare nel modo più efficiente possibile tutti i bit della parola, senza dover sacrificare a priori un certo numero di bit per la parte intera ed i restanti per la parte frazionaria Per ottenere questo risultato il sistema si basa sul concetto di notazione scientifica di un numero, ovvero quel modo di rappresentare un valore reale attraverso l'uso congiunto di una parte decimale e di un esponente: Es. 123.45 10 1.2345 10 *10 2 Es. 0.0000678 10 6.78 10 *10-5 Es. 987654321 10 9.87654321 10 *10 8 5
La notazione scientifica La notazione scientifica prevede che il numero sia scritto sempre con una sola cifra intera, seguita dalle cifre decimali necessarie e dall'opportuna base ed esponente Se la parte intera è sempre un numero diverso da 0, allora il numero si dice scritto in notazione scientifica normalizzata Questa stessa notazione può essere ovviamente utilizzata anche nel campo dei numeri binari Es. 10011.101 2 1.0011101 2 *2 4 Nel sistema binario ovviamente la forma normalizzata prevede che la cifra intera sia necessariamente un 1 (per cui la mantissa rappresenta un numero compreso tra 1 e 2) Il risultato è che un numero scritto in notazione scientifica normalizzata in base binaria, deve rispettare questo schema: 1.xxxxxxxx*2 yyyy Da notare che ora la virgola prende il nome di virgola binaria 6
Lo standard IEEE 754 Anche nel caso della virgola mobile tuttavia esiste il problema di decidere quanti bit utilizzare per descrivere la mantissa e quanti invece per descrivere l'esponente, una volta scelta la profondità di parola n Tale scelta è ovviamente arbitraria e ognuno può definirsi i propri valori per tali parametri, come risultato dei propri compromessi Tuttavia esiste una formalizzazione dello standard floating point, chiamato standard IEEE 754 per virgola mobile che è universalmente accettato dalla quasi totalità dei calcolatori e che stabilisce in modo inequivocabile tutte le regole da seguire per scrivere correttamente tali numeri Lo standard IEEE 754 definisce 3 tipi di formati (in realtà 4): A precisione singola (32 bit) A precisione doppia (64 bit) A precisione doppia estesa (più di 79 bit, generalmente 80) 7
Lo standard IEEE 754 La differenza principale dei vari formati è che ovviamente permettono precisioni e range di descrivibilità superiori Per tutti i formati comunque la struttura del dato è la seguente: 1 bit di segno, s (1 per negativi, 0 per positivi) n e bit di esponente, E n m bit di mantissa, M (detta precisione del numero) Il numero può dunque essere rappresentato in generale con questa formula: N = 1 s M 2 E Va però notato che, trattando numeri in notazione scientifica normalizzata, essi hanno per costruzione tutti necessariamente un 1 come prima cifra e perciò è possibile ometterla nella scrittura della mantissa (guadagnando un bit ulteriore); la formula quindi diventa: N = 1 s 1 M 2 E (si parla di bit implicito o bit nascosto) 8
Lo standard IEEE 754 Vediamo ora qualche dettaglio sulle varianti di formato disponibili Singola precisione (32 bit) 1 bit di segno, s 8 bit di esponente (segno incluso) 23 bit di mantissa (che diventano 24 bit virtuali con l'1 implicito ) Può descrivere numeri che vanno da 2.0 10 *10-38 fino a 2.0 10 *10 38 (e ovviamente lo stesso range anche nel campo negativo) Doppia precisione (64 bit) 1 bit di segno, s 11 bit di esponente (segno incluso) 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 s esponente mantissa 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41... 7 6 5 4 3 2 1 0 s esponente mantissa 52 bit di mantissa (che diventano 53 bit virtuali con l'1 implicito ) Può descrivere numeri che vanno da circa 2.0 10 *10-308 fino a circa 2.0 10 *10 308 (e ovviamente lo stesso range anche nel campo negativo) 9
Lo standard IEEE 754 E' evidente come il range di numeri descrivibili e la loro precisione, in particolare per la doppia precisione, siano davvero notevoli Possono tuttavia esistere dei casi in cui il numero che si vuole rappresentare sia troppo piccolo per poter essere rappresentato (underflow) o troppo grande (overflow), per cui è necessario passare a rappresentazioni ancora più precise Lo standard IEEE 754 ha anche cercato di focalizzare molti sforzi per realizzare formati che semplificassero poi il più possibile anche la gestione e le operazione banali su tali numeri A tal proposito estrema importanza è stata data alla possibilità di poter effettuare in modo rapido dei confronti fra numeri Per ottenere questo è stato ad esempio isolato per primo il bit di segno s, dato che un numero positivo è certamente maggiore di uno negativo, a prescindere dal valore di esponente e mantissa 10
Lo standard IEEE 754 Il campo esponente è stato piazzato subito dopo il segno s, poiché tra due numeri in notazione scientifica a e b, a parità di segno, chi ha esponente maggiore è anche certamente il maggiore dei due (e solo a parità di esponente occorre confrontare la mantissa) Infine la mantissa è scritta in binario puro senza segno e quindi i confronti si fanno banalmente con pochi controlli sui bit Nasce però ovviamente un problema nel campo esponente, poiché non si tratta di un numero in binario puro, ma di un numero con segno Se si scrive l'esponente in modulo e segno o in complemento a 2, il confronto tra un esponente più piccolo ed uno più grande non è immediato e richiederebbe parecchie operazioni Se però si potesse scrivere l'esponente come un numero binario senza segno (quindi solo positivo), i confronti tra esponenti si potrebbero fare in estrema rapidità, allo stesso modo con cui si fanno sulla mantissa Per ottenere questo vantaggio si usa la tecnica di polarizzazione, o scrittura dell'esponente in eccesso P 11
La polarizzazione Il principio della polarizzazione è molto semplice: Prendendo ad esempio un numero in precisione singola (32 bit), l'esponente deve essere scritto in 8 bit, ovvero potrebbe assumere i valori tra -128 e +127 (in complemento a 2) o in generale tra 0 e 255 (se lo prendiamo come un numero positivo) Se ora assumiamo come valore di polarizzazione P il numero 127, possiamo scrivere la formula vista in precedenza in questo modo: N = 1 s 1 M 2 E P In questo caso avremo che per E=1 (il più piccolo possibile) otteniamo un esponente utile di -126, mentre per un E=254 (il massimo possibile) otteniamo un esponente utile di +127 Abbiamo quindi ottenuto una mappatura che porta una scrittura di numeri solo positivi (da 0 a 255) verso una scrittura che descrive in modo crescente numeri negativi e positivi (da -127 a +128), permettendoci quindi ora di trattare E come un numero positivo 12
Le codifiche dei numeri speciali Identico trucco è utilizzabile nel sistema a doppia precisione in cui però il valore di polarizzazione P è pari a 1023 Un'ultima cosa va accennata a riguardo dello standard IEEE 754, ovvero la capacità di esprimere anche valori particolari, attraverso un'opportuna codifica Per ottenere questo alcuni valori di E ed M sono stati riservati e quindi non sono utilizzabili nelle rappresentazioni standard Il numero 0 è descritto da E=0 ed M=0 (s non conta) I numeri normalizzati si descrivono come visto prima, ma usando valori dell'esponente compresi tra 1 e 254 (per la singola precisione) e quindi ottenendo esponenti utili tra -126 e +127 I numeri denormalizzati devono avere E=0 ed M può assumere qualunque valore, escluso lo 0 I numeri infiniti, con E=255 e M=0 I NAN (Not A Number), con E=255 e M diverso da 0 13
Le codifiche dei numeri speciali Ovviamente ragionamenti del tutto analoghi, seppure con le opportune distinzioni nei valori, valgono anche per il formato a doppia precisione Sui numeri in virgola mobile ovviamente sono definite anche tutte le principali operazioni, quali somma, sottrazione, moltiplicazione e divisione, ma non saranno trattate in questo corso 14
Esempio di calcolo in singola precisione Si rappresenti in singola precisione il numero -19,3125 10 Il bit di segno è 1 poiché il numero è negativo S = 1 (1 bit) Si converte il numero 19,3125 10 in due passi: Parte intera (binario puro): 19 10 = 10011 2 Parte frazionaria (binario puro): 0,3125 10 = 0,0101 2 La mantissa non normalizzata è dunque: 10011,0101 2 La mantissa normalizzata diventa: 1,00110101*2 4 F = 00110101000000000000000 (23 bit, senza bit nascosto) L'esponente 4 10 devo scriverlo su 8 bit con bias 127: 4 + 127 = 131 = 10000011 2 (binario puro) E = 1000011 (8 bit) Risultato (su 32 bit): 1 1 0 0 0 0 0 1 1 0 0 1 1 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 s esponente mantissa = C19A8000 16 15
Esempio di calcolo in singola precisione Si decodifichi in decimale il numero in singola precisione 3A9B3000 16 Decodifichiamo il valore esadecimale in binario 3A9B3000 16 = Il bit di segno è 0 quindi il numero decimale è positivo S = 0 0 0 1 1 1 0 1 0 1 0 0 1 1 0 1 1 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 s esponente mantissa L'esponente compreso di bias è scritto sugli 8 bit seguenti: 01110101 2 = 117 10 (binario puro) Tolgo il bias (127 10 ) per riottenere l'esponente reale: 117-127 = -10 10 = E La mantissa è scritta sui 23 bit seguenti: Reintegro il bit nascosto iniziale: 1,00110110011000000000000 2 Effettuo la moltiplicazione per l'esponente: 0,000000000100110110011 2 Decodifico la mantissa in decimale: 0.001183987 10 = S Il risultato finale è dunque: +0.001183987 10 = +1.183987*10-3 16