I numeri reali si rappresentano nei calcolatori in virgola mobile, secondo lo standard IEEE 754: un numero è codificato come segno, esponente e mantissa, come una notazione scientifica binaria. Questa scheda allena la struttura del formato, la codifica/decodifica e i limiti di precisione.
Formato IEEE 754 singola precisione (32 bit): \;1\text{ bit segno}+8\text{ bit esponente}+23\text{ bit mantissa}.
1. Notazione scientifica binaria
Esercizio. Scrivere 6{,}5_{10} in notazione scientifica binaria normalizzata.
Passo 1 — binario: 6{,}5=110{,}1_2 (poiché 4+2+0{,}5=6{,}5).
Passo 2 — normalizzare (un solo 1 prima della virgola):
110{,}1_2=1{,}101_2\times2^{2}.
La forma normalizzata 1{,}f\times2^e è la base dell’IEEE 754: la cifra prima della virgola è sempre 1 (e non si memorizza: bit implicito).
2. Bias dell’esponente
Esercizio. Per la singola precisione (8 bit di esponente), calcolare il bias e l’esponente memorizzato per 2^2.
Il bias per n bit di esponente è 2^{n-1}-1:
\text{bias}=2^{7}-1=127.
L’esponente memorizzato è quello reale più il bias:
E_{mem}=e+\text{bias}=2+127=129=10000001_2.
Il bias permette di rappresentare esponenti negativi senza un bit di segno dedicato: si somma 127 e si confronta.
3. Codifica completa di un float
Esercizio. Codificare 6{,}5 in IEEE 754 singola precisione.
Da 6{,}5=1{,}101_2\times2^2:
- segno: 0 (positivo);
- esponente: 129=10000001;
- mantissa: parte frazionaria 101, completata con zeri a 23 bit: 10100000000000000000000.
6{,}5=\underbrace{0}_{s}\ \underbrace{10000001}_{e}\ \underbrace{10100000000000000000000}_{m}.
Il bit implicito (1 prima della virgola) non si memorizza: la mantissa contiene solo la parte frazionaria.
4. Decodifica di un float
Esercizio. Decodificare il numero IEEE 754: segno 0, esponente 10000010_2, mantissa 01000\dots
Passo 1 — esponente reale: 10000010_2=130, quindi e=130-127=3.
Passo 2 — mantissa con bit implicito: 1{,}01_2=1{,}25.
Passo 3 — valore:
(-1)^0\times1{,}25\times2^3=1{,}25\times8=10{,}0.
Il numero è +10{,}0. La decodifica inverte la codifica: si toglie il bias e si ripristina l’1 implicito.
5. Precisione della singola precisione
Esercizio. Quante cifre decimali significative garantisce la singola precisione (23 bit di mantissa + 1 implicito)?
Con 24 bit effettivi di mantissa, la precisione decimale è:
24\times\log_{10}2=24\times0{,}301=7{,}2\ \text{cifre}.
La singola precisione garantisce circa 7 cifre decimali significative; la doppia precisione (52+1 bit) ne dà circa 15-16. Oltre, i numeri non sono distinguibili.
6. Errore di arrotondamento
Esercizio. Perché 0{,}1_{10} non è rappresentabile esattamente in IEEE 754?
0{,}1 in binario è periodico: 0{,}1_{10}=0{,}00011001100110\overline{0011}_2. Avendo la mantissa un numero finito di bit, il valore viene troncato/arrotondato:
0{,}1_{10}\approx0{,}100000001490\dots\ (\text{singola precisione}).
Da qui i classici errori tipo 0{,}1+0{,}2\ne0{,}3 in molti linguaggi. La virgola mobile rappresenta esattamente solo frazioni con denominatore potenza di 2: ogni altra è approssimata.
7. Numeri speciali: zero, infinito e NaN
Esercizio. In IEEE 754 singola precisione, come si riconoscono zero, infinito e NaN?
La classificazione dipende soprattutto dal campo esponente:
| Esponente | Mantissa | Significato |
|---|---|---|
| tutti 0 | tutti 0 | zero positivo o negativo |
| tutti 0 | non nulla | numero subnormale |
| tra 1 e 254 | qualunque | numero normalizzato |
| tutti 1 | tutti 0 | infinito |
| tutti 1 | non nulla | NaN (Not a Number) |
Esempi:
Un NaN nasce da operazioni non definite, come 0/0 o \sqrt{-1} nei reali. Non va confrontato come un numero ordinario: in IEEE 754, persino il confronto NaN = NaN è falso in molti linguaggi.
8. Numeri subnormali
Esercizio. Qual è il più piccolo numero positivo normalizzato in singola precisione? Perché servono i subnormali?
Per i normalizzati l’esponente memorizzato minimo non nullo è E=1. L’esponente reale è:
Con mantissa nulla, il valore è:
I subnormali usano invece esponente memorizzato 0 e non hanno il bit implicito 1: permettono di rappresentare valori ancora più piccoli, con precisione ridotta. Servono a evitare un salto brusco tra il più piccolo normalizzato e lo zero, rendendo l’underflow più graduale.
9. Somma con perdita di significato
Esercizio. Perché in singola precisione l’operazione (10^8+1)-10^8 può restituire 0 invece di 1?
La singola precisione ha circa 7 cifre decimali significative. Intorno a 10^8 la distanza tra due float rappresentabili consecutivi è maggiore di 1. Quando si calcola:
il valore viene arrotondato di nuovo a 10^8, perché il +1 è troppo piccolo rispetto alla scala del numero. Quindi:
Questo fenomeno si chiama assorbimento o perdita di significato: sommare quantità molto piccole a quantità molto grandi può non cambiare il valore memorizzato.
10. Confronto tra float con tolleranza
Esercizio. Come confrontare due risultati in virgola mobile che dovrebbero essere uguali?
Invece di usare l’uguaglianza esatta a=b, si controlla se la differenza è piccola:
Esempio: se un algoritmo dovrebbe produrre 0{,}3 e ottiene 0{,}3000000004, con \varepsilon=10^{-6}:
quindi i due valori sono equivalenti per la precisione richiesta. Nei problemi numerici seri si usa spesso una tolleranza relativa:
perché un errore assoluto accettabile vicino a 10^9 può essere enorme vicino a 0.
Errori comuni
- Dimenticare il bit implicito. La mantissa memorizza solo la parte frazionaria; l’1 prima della virgola è sottinteso (numeri normalizzati).
- Non applicare il bias all’esponente. L’esponente memorizzato è e+127 (singola precisione): leggerlo direttamente sbaglia l’ordine di grandezza.
- Assumere precisione infinita. La virgola mobile ha precisione finita (~7 cifre in singola): confronti di uguaglianza esatta tra float sono insidiosi.
- Credere ogni decimale rappresentabile. Solo le frazioni con denominatore potenza di 2 sono esatte; 0{,}1, 0{,}3, ecc. sono approssimate.
- Ignorare NaN e infiniti. IEEE 754 non rappresenta solo numeri ordinari: esistono valori speciali che richiedono controlli espliciti.