x.yxwt 10e oppure 0.xyxwt 10 e+1 (dove x, y, w, t indicano cifre decimali). Il coefficiente della potenza di 10 viene chiamato mantissa del numero. Nel primo caso la mantissa è x.yxwt , mentre nel secondo è 0.xyxwt. La rappresentazione mediante virgola mobile offre due principali vantaggi su altre possibili alternative: rende più semplice automatizzare le operazioni aritmetiche e soprattutto permette di eliminare qualsiasi ambiguità tra zeri significativi e posizionali.
Per illustrare quest' ultimo punto cerchiamo di capire come
interpretare il valore delle cifre del numero 15000. Chiaramente,
si tratta di un numero in cui ci sono 1 decina di migliaia
e 5 migliaia. Però, non è chiaro
se i
tre zeri che seguono vadano interpretati
come " esattamente zero centinaia, zero decine e zero unità"
oppure
come indicatori del valore di decine di migliaia e migliaia delle cifre
precedenti ma senza per questo implicare che il numero in
questione corrisponda ad una conoscenza esatta anche di centinaia,
decine e unità. Nel primo caso, diremo che si tratta di
zeri "significativi" e che le cifre significative del
numero sono in tutto 5. Nel secondo caso, gli zeri servono solo
ad attribuire il giusto valore posizionale a 1 e
5 ma il numero di cifre significative è 2. Con la
rappresentazione in virgola mobile si definiscono significative
tutte le cifre della mantissa di lunghezza finita (zeri inclusi) che siano a destra della prima
cifra diversa da zero.
In notazione binaria il concetto di numero a virgola mobile si estende in modo diretto. Inoltre, poiché le cifre possono essere solo 0 oppure 1, se si opta per la forma "normalizzata" 1.xyzt 2e , in cui la mantissa 1.xyzt inizia sempre per 1, possiamo omettere di indicare l' 1 prima del punto risparmiando un simbolo per rappresentare la mantissa ma mantenendo una cifra (binaria) ignificativa in più di quelle esplicitamente scritte.
Per standardizzare la rappresentazione di numeri binari floating
point è necessario decidere quanti bit utilizzare e come
ripartirli tra mantissa ed esponente. Esistono moltissime
possibili soluzioni e, in principio, i linguaggi di programmazione
dovrebbero essere "neutri" rispetto alle convenzioni di
rappresentazione. Di fatto, fin dalla fine degli anni '80, si
è
imposto lo standard IEEE 754 che, nella revisione del 2008, prevede
tre
rappresentazioni binarie, lasciando ai singoli linguaggi la scelta di quali adottare:
Inoltre, due dei possibili valori dell' esponente sono in realtà
riservati per esprimere dei valori speciali risultanti da possibili
operazioni aritmetiche mal definite come divisioni per zero o rapporti
del tipo 0/0, nonché per rappresentare lo zero e un insieme di
numeri
"denormalizzati" per cui non vale la convenzione del bit nascosto.
In dettaglio, per numeri a
32 bit la codifica è la
seguente.
Indichiamo con S, M ed E i campi di 1, 23 e 8 bit
riservati alla codifica di segno (della mantissa), mantissa ed
esponente.
Il campo "esponente", E, dei floating assume in notazione posizionale valori tra 0 e 255.
In modo analogo per floating a 64 o 128 bit. Lo standard non vieta l'esistenza di ulteriori rappresentazioni. Da segnalare in particolare la presenza su processori Intel di una rappresentazione a 10 byte (80 bit), di cui 15 dedicati all' esponente, ma senza bit nascosto, quindi con mantisse di 64 bit totali tutti espliciti.
Da notare che i valori speciali NaN ( o nan ) e +/- infinito dello
standard IEEE non sono intesi come elementi dell' insieme dei numeri
reali ma come valori speciali da utilizzare nella
programmazione per avviare eventuali procedure di manipolazione
delle condizioni di errore. Talvolta un compilatore può
generare
automaticamente codice di gestione delle condizioni di errore
nascondendo al programmatore la possibilità di accedere ai
valori speciali dello standard IEEE-754. Tuttavia, normalmente,
esistono opzioni del compilatore che permettono di evitare la
gestione automatica.
Infine va aggiunto che lo standard prevede quattro diversi tipi di arrotondamento nell' esecuzione delle operazioni tra numeri a virgola mobile:
Le principali caratteristiche della rappresentazione dei reali che
influenzano le proprietà dell' aritmetica sul computer sono:
i) il numero finito di cifre
significative,
ii) il numero finito di reali,
iii) la loro non
uniformità e
iv) la rappresentazione
mediante una base diversa da quella usuale ( 2
invece di 10).
Vediamo più da vicino come questi fattori intervengono nel caso della rappresentazione mediante 32 bit. Le modifiche per i casi con numero diverso di bit sono ovvie e lasciate come esercizio.
La proprietà i) implica che, dato un numero rappresentato sul computer esiste più di un numero B ( non solo B=0 ) che soddisfa l' equazione
A + B = A
è sufficiente che il rapporto tra B sia ed A sia più piccolo di 2-24 perché sommare A a B divenga equivalente a sommare 0 ad A (con arrotondamento al numero più vicino). Supponiamo, per esempio di voler effettuare la somma:
1.0 246 + 1.0 220
con reali a 32 bit. Il primo numero ha mantissa
1.00000000000000000000000 (23 zeri) ed esponente 46;
il secondo ha la stessa mantissa ed esponente 20.
Per poter sommare i numeri, uno dei due (il minore) viene
trasformato mediante divisioni della mantissa e conseguenti variazioni
dell' esponente della potenza di 2, in modo da avaere lo stesso
esponente del maggiore
e mantissa non più normalizzata:
1.00000000000000000000000 (23 zeri) ed esponente 20 =
0.00000000000000000000000001 (26 zeri a sinistra di 1) ed esponente 46.
A questo punto si possono sommare le mantisse per ottenere la nuova
mantissa:
1.00000000000000000000000001 (tra i due 1 ci sono 25 zeri). L'
esponente del risultato resta 46.
Ed infine, essendo la nuova mantissa già normalizzata, si
scrivono le prime 23 cifre a destra del punto nel campo mantissa del
risultato per ottenere la rappresentazione standardizzata
di 246.
Quindi
1.0 246 + 1.0 220 = 1.0 246 .
In generale, rapportando i valori alla più usuale base 10, possiamo considerare che una mantissa di 24 cifre binarie significative (incluso il bit nascosto) corrisponde approssimativamente a 7 cifre decimali significative. Se sommiamo due numeri decimali rappresentati con sole con 7 cifre significative che differiscono per più di 7 ordini di grandezza, il risultato (entro le sette cifre significative) è indistinguibile dal maggiore tra i due addendi.
La proprietà ii) è all' origine della
possibilità di uscire al di fuori dell' intervallo dei valori
rappresentabili mediante le operazioni aritmetiche. Se lo "sfondamento"
è nella direzione di andare al di là del massimo
valore assoluto possibile, si parla di overflow, e il
risultato sarà uno dei due valori eccezionali +Inf e -Inf.
Mentre, se
si arriva a valori inferiori invalore assoluto al più
piccolo valore
denormalizzato diverso da zero, si parla di underflow e il
risultato viene considerato esattamente uguale a zero.
Es. con 32 bit (10-45)2 vale esattamente
zero.
La proprietà iii) discende anch' essa dalla precisione
finita:
La minima distanza non nulla tra due reali è dell' ordine
di 10
-45 attorno allo zero mentre diviene dell' ordine di 10 31
in prossimità dell' estremo superiore dell' insieme.
Infine occorre aver coscienza anche del punto iv) per poter comprendere come mai conti fatti a partire da costanti numeriche descrivibili esattamente con un numero finito di cifre significative in notazione decimale possano corrispondere a calcoli approssimati in corrispondenza di valori per cui non esiste una conversione binaria dotata di un numero finito di cifre significative.
Anche qui un esempio può aiutare a capire. Consideriamo il risultato della divisione 1/10.
In base 10 è esprimibile con un numero finito di cifre decimali diverse da zero ( 1/10 = 0.100000...10 ). Pertanto la rappresentazione finita ottenuta troncando gli zeri finali non introduce nessuna inesattezza nella rappresentazione decimale.
In base 2 lo stesso numero è rappresentato da
0.000110011001100110011... 2 cioè corrisponde
ad una
rappresentazione periodica di periodo 0011 ( e antiperiodo 0). Se
abbiamo solo n bit per rappresentare questo
numero dovremo necessariamente approssimarlo (troncando o
arrotondando).
Una conseguenza pratica importante è che, mentre in
aritmetica
decimale con un numer finito di cifre i prodotti n*0.1
(n=1,2,3,....)
assumono periodicamente valori in cui la
parte decimale è tutta nulla, in aritmetica binaria con un
numero
finito di cifre questo non è più vero e
potremmo scoprire che su alcuni sistemi 0.1*20.0 non è uguale a 2.0 !
Da questa peculiarità della rappresentazione dei reali si ricava
che possiamo considerare un numero con virgola del computer come un'
approssimazione del valore vero a meno di un errore relativo,
dipendente dal numero, maggiorato dalla precisione macchina εM.
Quindi in generale potremo scrivere:
xcomp=x(1+εx) dove |εx|< εM
dipende da x.
N.B. La precisione macchina definita come sopra dipende dal tipo di
arrotondamento utilizzato. La funzione o costante epsilon messa a
disposizione da linguaggi di programmazione di alto livello come C,
C++, Fortran differisce dalla precisione macchina per un fattore 2,
quando, come di solito avviene, si utilizza ' arrotondamento al numero
rappresentabile più vicino. Pertanto, epsilon(1.0) del Fortran
è due volte la precisione macchina per il tipo real di default.
Tuttavia in molti casi si è interessati solo all' ordine di
grandezza decimale della precisione macchina e si può ignorare
l' eventuale fattore 2.