Comment représenter 0,1 en arithmétique en virgule flottante et décimale

J’essaie de mieux comprendre l’arithmétique en virgule flottante et j’ai lu quelques liens vers “Ce que tout informaticien devrait savoir sur l’arithmétique en virgule flottante”.

Je ne comprends toujours pas comment un nombre comme 0.1 ou 0.5 est stocké dans des nombres flottants et décimaux.

Quelqu’un peut-il s’il vous plaît expliquer comment il est aménagé est la mémoire?

Je sais que le flottant est en deux parties (c.-à-d. Un nombre à la puissance de quelque chose).

J’ai toujours dirigé les gens vers le convertisseur en ligne de Harald Schmidt , ainsi que dans l’ article IEEE754-1985 de Wikipedia avec ses belles images.

Pour ces deux valeurs spécifiques, vous obtenez (pour 0.1):

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

Le signe est positif, c’est assez facile.

L’exposant est 64+32+16+8+2+1 = 123 - 127 bias = -4 , le multiplicateur est donc 2 -4 ou 1/16 .

La mantisse est trapue. Il se compose de 1 (la base implicite) plus (pour tous ces bits, chacun valant 1/(2 n ) car n commence à 1 et augmente à droite), {1/2, 1/16, 1/32, 1/256, 1/512, 1/4096, 1/8192, 1/65536, 1/131072, 1/1048576, 1/2097152, 1/8388608} .

Lorsque vous additionnez tout cela, vous obtenez 1.60000002384185791015625 .

Lorsque vous multipliez cela par le multiplicateur, vous obtenez 0.100000001490116119384765625 , raison pour laquelle ils disent que vous ne pouvez pas représenter 0.1 exactement comme un float IEEE754, et fournit autant d’opportunités sur SO pour les personnes répondant "why doesn't 0.1 + 0.1 + 0.1 == 0.3?" questions de type 🙂


L’exemple 0.5 est considérablement plus facile. C’est représenté comme:

 s eeeeeeee mmmmmmmmmmmmmmmmmmmmmmm 0 01111110 00000000000000000000000 

ce qui signifie que c’est la base implicite, 1 , plus aucun autre additif (tous les bits de mantisse sont à zéro).

Le signe est à nouveau positif. L’exposant est 64+32+16+8+4+2 = 126 - 127 bias = -1 . Le multiplicateur est donc 2 -1 soit 1/2 ou 0.5 .

La valeur finale est donc 1 multipliée par 0.5 ou 0.5 . Voila!


J’ai parfois trouvé plus facile de penser en termes de nombre décimal.

Le nombre 1.345 est équivalent à

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

ou:

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

De même, la représentation IEEE754 pour le 0.8125 décimal 0.8125 est:

 s eeeeeeee mmmmmmmmmmmmmmmmmmmmmmm 0 01111110 10100000000000000000000 

Avec la base implicite de 1, cela équivaut au binary:

  01111110-01111111 1.101 * 2 

ou:

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

qui devient:

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

et devient alors :

 13/8 * 1/2 = 0.8125 

Voir l’entrée Wikipedia et le groupe IEEE , d’abord.

En gros, il y a un signe, un nombre et un exposant. Un nombre dans une base ne peut pas être représenté finement dans une autre base si la base source n’a pas de facteurs présents dans la base de destination. Par exemple, 1/3 ne peut pas être représenté par un nombre décimal fini, mais il est sortingvial de le représenter par un nombre ternaire (base 3): (0.1) 3 .

Donc 0.5 a une représentation binary finie , (0.1) 2 , c’est-à-dire 2 -1 , mais 0.1 a une représentation répétitive car 2 et 10 ont un facteur (5) pas en commun.