Virgola fissa e mobile (IEEE 754): esercizi svolti

Indice dei contenuti

    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:

    EsponenteMantissaSignificato
    tutti 0tutti 0zero positivo o negativo
    tutti 0non nullanumero subnormale
    tra 1 e 254qualunquenumero normalizzato
    tutti 1tutti 0infinito
    tutti 1non nullaNaN (Not a Number)

    Esempi:

    0\ 00000000\ 000\dots0=+0, \qquad 0\ 11111111\ 000\dots0=+\infty.

    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 è:

    e=1-127=-126.

    Con mantissa nulla, il valore è:

    1{,}0_2\times2^{-126}.

    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:

    10^8+1,

    il valore viene arrotondato di nuovo a 10^8, perché il +1 è troppo piccolo rispetto alla scala del numero. Quindi:

    (10^8+1)-10^8\approx10^8-10^8=0.

    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:

    |a-b|<\varepsilon.

    Esempio: se un algoritmo dovrebbe produrre 0{,}3 e ottiene 0{,}3000000004, con \varepsilon=10^{-6}:

    |0{,}3000000004-0{,}3|=4\cdot10^{-10}<10^{-6},

    quindi i due valori sono equivalenti per la precisione richiesta. Nei problemi numerici seri si usa spesso una tolleranza relativa:

    \dfrac{|a-b|}{\max(1,|a|,|b|)}<\varepsilon,

    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.

    Ultimo aggiornamento: