Visualizzatore dei bit dei numeri in virgola mobile IEEE 754
Scompone e mostra la configurazione di bit di un numero decimale in precisione singola, a 32 bit, e doppia, a 64 bit, secondo la norma IEEE 754, oppure converte in senso inverso dalla configurazione al decimale. Distingue con colori diversi segno, esponente e mantissa e riconosce NaN, infiniti e numeri denormalizzati.
L'esempio classico: perché 0,1 più 0,2 non fa 0,3
Calcolando `0.1 + 0.2` in JavaScript si ottiene `0.30000000000000004`, che non coincide con `0.3`. Osservando la configurazione di bit in precisione doppia se ne comprende la ragione.
| Valore | Esadecimale in precisione doppia (64 bit) | Binario in precisione doppia (64 bit) |
|---|---|---|
| 0.1 | 0x3FB999999999999A | 0011111110111001100110011001100110011001100110011001100110011010 |
| 0.2 | 0x3FC999999999999A | 0011111111001001100110011001100110011001100110011001100110011010 |
| 0.3 | 0x3FD3333333333333 | 0011111111010011001100110011001100110011001100110011001100110011 |
| 0.1 + 0.2 | 0x3FD3333333333334 | 0011111111010011001100110011001100110011001100110011001100110100 |
In binario 0,1, 0,2 e 0,3 sono tutti numeri periodici infiniti: non entrano nei 52 bit finiti della mantissa e vengono arrotondati. Poiché gli errori di arrotondamento di 0,1 e 0,2 non si compensano, la loro somma risulta in una configurazione che differisce di un solo bit da quella che rappresenta esattamente 0,3, ossia 0x3FD3333333333334. Provate a inserire questi valori nello strumento qui sopra e a confrontare l'ultimo bit.
Consigli per l'uso
- Convertendo in bit 0,1, 0,2 e 0,3 in precisione doppia e confrontandoli con il risultato di 0,1 più 0,2, cioè 0.30000000000000004, si vede a colpo d'occhio che differiscono per un solo bit finale.
- Inserendo «-0» nel campo decimale si ottiene una configurazione in cui è acceso soltanto il bit di segno, diversa da quella del più zero. Numericamente 0 e -0 sono uguali, ma la rappresentazione in bit è un'altra cosa.
- Quando l'esponente è tutto a zero, una mantissa nulla indica lo zero e una mantissa non nulla un numero denormalizzato, cioè la rappresentazione particolare che, a scapito della precisione, esprime valori estremamente vicini allo zero.
- Passando dalla precisione singola, a 32 bit, a quella doppia, a 64 bit, si osserva come per uno stesso valore 0,1 cambi l'entità dell'errore di arrotondamento, maggiore in precisione singola.
- Nella conversione inversa a partire dai bit occorre indicare un numero esadecimale con il prefisso `0x` oppure un binario con tante cifre quante ne richiede la precisione scelta, con il prefisso `0b` facoltativo.
Domande frequenti
A proposito — come nacque la «lingua comune» chiamata IEEE 754
Prima del 1985 ciascun costruttore adottava una propria rappresentazione dei numeri in virgola mobile. Fra IBM, DEC e Cray, calcolando lo stesso valore 0,1 si ottenevano arrotondamenti e intervalli rappresentabili leggermente diversi, e portare un programma da una macchina all'altra faceva puntualmente divergere i risultati numerici. Per porre fine alla confusione, un gruppo guidato da William Kahan dell'Università della California a Berkeley, che aveva collaborato anche alla progettazione del coprocessore matematico Intel 8087, definì nel 1985 la norma IEEE 754 come standard trasversale al settore.
L'idea centrale della norma sta nel ripartire i compiti fra tre parti — segno, esponente e mantissa — per approssimare con un numero finito di bit, 32 o 64, l'infinità dei numeri reali. L'esponente si occupa dell'ordine di grandezza, la mantissa della precisione delle cifre significative: così, con pochi bit, si trattano con duttilità numeri piccolissimi e grandissimi. Il fatto che l'esponente sia memorizzato sommandovi una polarizzazione — 127 in precisione singola e 1023 in quella doppia — è un accorgimento che permette di stabilire quale numero sia il maggiore confrontando semplicemente le sequenze di bit, senza le complicazioni del complemento a due degli interi con segno.
In binario si rappresentano «esattamente» soltanto le frazioni il cui denominatore è una potenza di due: un mezzo, un quarto, tre ottavi. Il valore decimale 0,1 corrisponde alla frazione un decimo, ma dieci non è una potenza di due e in binario diventa il numero periodico infinito 0,0001100110011… Per farlo entrare in una mantissa finita non resta che troncarlo e arrotondarlo: è questa la ragione di fondo per cui 0,1 non è rappresentabile con esattezza. Ed è per lo stesso motivo che i sistemi contabili, che devono trattare esattamente il decimale, ricorrono all'aritmetica intera o a tipi decimali appositi anziché alla virgola mobile.
La norma è stata poi rivista nel 2008 e nel 2019, con l'aggiunta della mezza precisione a 16 bit, della quadrupla a 128 bit e delle disposizioni sui numeri decimali in virgola mobile, ma la struttura fondamentale in tre parti e l'impostazione delle modalità di arrotondamento sono rimaste quelle della prima edizione del 1985. Poiché i tipi float e double di quasi tutti i linguaggi di programmazione vi si conformano, la domanda «perché 0,1 più 0,2 non fa 0,3» descrive un fenomeno comune a ogni linguaggio.