Come rappresentare 0,1 in virgola mobile aritmetica e decimale

Sto cercando di capire meglio l’aritmetica in virgola mobile e ho visto alcuni link a “Ciò che ogni scienziato informatico dovrebbe sapere sull’aritmetica in virgola mobile”.

Continuo a non capire come un numero come 0.1 o 0.5 sia memorizzato nei float e come decimali.

Qualcuno può spiegare come è strutturata la memoria?

So che il float è composto da due parti (cioè un numero per la potenza di qualcosa).

Ho sempre indirizzato le persone verso il convertitore online di Harald Schmidt , insieme all’articolo Wikipedia IEEE754-1985 con le sue belle immagini.

Per questi due valori specifici, ottieni (per 0.1):

 s eeeeeeee mmmmmmmmmmmmmmmmmmmmmmm 1/n 0 01111011 10011001100110011001101 | || || || || || +- 8388608 | || || || || |+--- 2097152 | || || || || +---- 1048576 | || || || |+------- 131072 | || || || +-------- 65536 | || || |+----------- 8192 | || || +------------ 4096 | || |+--------------- 512 | || +---------------- 256 | |+------------------- 32 | +-------------------- 16 +----------------------- 2 

Il segno è positivo, è abbastanza facile.

L’esponente è 64+32+16+8+2+1 = 123 - 127 bias = -4 , quindi il moltiplicatore è 2 -4 o 1/16 .

La mantissa è grossa. Consiste di 1 (la base implicita) più (per tutti quei bit con ogni valore 1/(2 n ) poiché n inizia da 1 e aumenta a destra), {1/2, 1/16, 1/32, 1/256, 1/512, 1/4096, 1/8192, 1/65536, 1/131072, 1/1048576, 1/2097152, 1/8388608} .

Quando aggiungi tutti questi elementi, ottieni 1.60000002384185791015625 .

Quando lo si moltiplica per il moltiplicatore, si ottiene 0.100000001490116119384765625 , motivo per cui si dice che non si può rappresentare 0.1 esattamente come un float IEEE754 e fornisce così tante opportunità su SO per le persone che rispondono "why doesn't 0.1 + 0.1 + 0.1 == 0.3?" -tipo domande 🙂


L’esempio 0.5 è sostanzialmente più semplice. È rappresentato come:

 s eeeeeeee mmmmmmmmmmmmmmmmmmmmmmm 0 01111110 00000000000000000000000 

il che significa che è la base implicita, 1 , più nessun altro additivo (tutti i bit della mantissa sono zero).

Il segno è di nuovo positivo. L’esponente è 64+32+16+8+4+2 = 126 - 127 bias = -1 . Quindi il moltiplicatore è 2 -1 che è 1/2 o 0.5 .

Quindi il valore finale è 1 moltiplicato per 0.5 o 0.5 . Ecco!


A volte ho trovato più facile pensarlo in termini di decimali.

Il numero 1.345 equivale a

 1 + 3/10 + 4/100 + 5/1000 

o:

  -1 -2 -3 1 + 3*10 + 4*10 + 5*10 

Allo stesso modo, la rappresentazione IEEE754 per il decimale 0.8125 è:

 s eeeeeeee mmmmmmmmmmmmmmmmmmmmmmm 0 01111110 10100000000000000000000 

Con la base implicita di 1, è equivalente al binario:

  01111110-01111111 1.101 * 2 

o:

  -1 (1 + 1/2 + 1/8) * 2 (no 1/4 since that bit is 0) 

che diventa:

 (8/8 + 4/8 + 1/8) * 1/2 

e poi diventa:

 13/8 * 1/2 = 0.8125 

Vedi prima la voce di Wikipedia e il gruppo IEEE .

Fondamentalmente, c’è un segno, un numero e un esponente. Un numero in una base non può essere rappresentato finitamente in un’altra base se la base di partenza ha fattori non presenti nella base di destinazione. Ad esempio, 1/3 non può essere rappresentato come un numero decimale finito, ma è banale da rappresentare come numero ternario (base-3): (0.1) 3 .

Quindi 0.5 ha una rappresentazione binaria finita , (0.1) 2 , cioè 2 -1 , ma 0.1 ha una rappresentazione ripetitiva perché 2 e 10 hanno un fattore (5) non comune.