web-dev-qa-db-fra.com

Comment les nombres à virgule flottante sont-ils stockés en mémoire?

J'ai lu qu'ils sont stockés sous forme de mantisse et d'exposant

J'ai lu ce document mais je n'ai rien compris.

25
vikky

Pour comprendre comment ils sont stockés, vous devez d’abord comprendre ce qu’ils sont et le type de valeurs qu’ils sont censés gérer.

Contrairement aux nombres entiers, une valeur en virgule flottante est censée représenter des valeurs extrêmement petites et extrêmement grandes. Pour les valeurs à virgule flottante 32 bits normales, cela correspond à des valeurs comprises entre 1.175494351 * 10 ^ -38 à 3.40282347 * 10 ^ + 38.

Clairement, en utilisant seulement 32 bits, il n'est pas possible de stocker tous les chiffres dans de tels nombres.

En ce qui concerne la représentation, vous pouvez voir tous les nombres normaux à virgule flottante sous forme de valeurs comprises entre 1,0 et (presque) 2,0, mis à l'échelle avec une puissance de deux. Donc 1.0 est, tout simplement 1,0 * 2 ^ 0. 2.0 est 1,0 * 2 ^ 1. -5.0 est -1,25 * 2 ^ 2.

Alors, que faut-il pour encoder cela le plus efficacement possible? De quoi avons-nous vraiment besoin?

  • Le signe de l'expression.
  • L'exposant
  • La valeur dans la plage de 1,0 à (presque) 2,0. C’est ce que l’on appelle la "mantisse", c’est-à-dire la signification.

Ceci est codé comme suit, conformément à la norme à virgule flottante IEEE-754.

  • Le signe est un seul bit.
  • L'exposant est stocké sous la forme d'un entier non signé. Pour les valeurs à virgule flottante de 32 bits, ce champ est de 8 bits. 1 représente le plus petit exposant et "tous les uns - 1" le plus grand. (0 et "tous les uns" servent à coder des valeurs spéciales, voir ci-dessous.) Une valeur au milieu (127, dans le cas 32 bits) représente zéro, elle est également appelée biais .
  • En regardant la mantisse (la valeur entre 1.0 et (presque) 2.0), on voit que toutes les valeurs possibles commencent par un "1" (à la fois dans la représentation décimale et binaire). Cela signifie qu'il ne sert à rien de le stocker. Le reste des chiffres binaires est stocké dans un champ entier, dans le cas 32 bits, ce champ est 23 bits.

Outre les valeurs à virgule flottante normales, il existe un certain nombre de valeurs spéciales:

  • Zéro est codé avec exposant et mantisse à zéro. Le bit de signe est utilisé pour représenter "plus zéro" et "moins zéro". Un moins zéro est utile lorsque le résultat d'une opération est extrêmement faible, mais il est toujours important de savoir d'où vient l'opération.
  • plus et moins l'infini - représenté à l'aide d'un exposant "tous les un" et d'un champ de mantisse nul.
  • Pas un nombre (NaN) - représenté à l'aide d'un exposant "tous les un" et d'une mantisse non nulle.
  • Nombres dénormalisés - nombres plus petits que le plus petit nombre normal. Représenté à l'aide d'un champ exposant nul et d'une mantisse non nulle. La particularité de ces nombres est que la précision (c'est-à-dire le nombre de chiffres qu'une valeur peut contenir) diminuera à mesure que la valeur diminue, tout simplement parce qu'il n'y a pas de place pour eux dans la mantisse.

Enfin, voici quelques exemples concrets (toutes les valeurs sont en hex):

  • 1.0: 3f800000
  • -1234.0: c49a4000
  • 100000000000000000000000000.0: 65a96816
36
Lindydancer

En termes simples, il s'agit essentiellement de notation scientifique en binaire. La norme officielle (avec les détails) est IEEE 754 .

7
Wyzard
  typedef struct {
      unsigned int mantissa_low:32;     
      unsigned int mantissa_high:20;
      unsigned int exponent:11;        
      unsigned int sign:1;
    } tDoubleStruct;

double a = 1.2;
tDoubleStruct* b = reinterpret_cast<tDoubleStruct*>(&a);

Voici un exemple de configuration de la mémoire si le compilateur utilise la double précision IEEE 754, qui est la valeur par défaut pour un double C sur la plupart des systèmes actuels.

Le voici sous forme binaire en C et mieux lu wikipedia sur la double précision pour le comprendre.

5
Totonga

J'ai aimé l'explication donnée dans le lien ci-dessous. De plus, la section "Sujets que vous aimerez" pointe vers des réponses à d'autres requêtes similaires.

Partage pour les enregistrements au cas où un débutant cherche l'information.

https://www.log2base2.com/storage/how-float-values-are-stored-in-memory.html

2
AamodG

Il existe différents formats en virgule flottante. La plupart d'entre eux partagent quelques caractéristiques communes: un bit de signe, des bits dédiés au stockage d'un exposant et des bits dédiés au stockage du significande (également appelé mantisse).

La norme à virgule flottante IEEE tente de définir un format unique (ou plutôt un ensemble de formats de quelques tailles) pouvant être implémenté sur divers systèmes. Il définit également les opérations disponibles et leur sémantique. Cela fonctionne très bien et la plupart des systèmes que vous rencontrerez probablement utilisent une virgule flottante IEEE. Mais d'autres formats sont toujours utilisés, ainsi que des implémentations IEEE pas assez complètes. La norme C fournit facultatif la prise en charge de IEEE, mais ne l’oblige pas.

2
Keith Thompson

La mantisse représente les bits les plus significatifs du nombre.

L'exposant représente le nombre de décalages à effectuer sur la mantisse afin d'obtenir la valeur réelle du nombre.

L'encodage spécifie comment sont représentés le signe de la mantisse et le signe de l'exposant (en se déplaçant essentiellement vers la gauche ou vers la droite).

Le document auquel vous faites référence spécifie le codage IEEE, le plus utilisé.

1
mouviciel

J'ai trouvé l'article que vous avez cité assez illisible (et je connais un peu le fonctionnement des flotteurs IEEE). Je vous suggère d'essayer avec la version Wiki de l'explication. C'est assez clair et a plusieurs exemples:

http://en.wikipedia.org/wiki/Single_precision et http://en.wikipedia.org/wiki/Double_precision

1
xanatos

C'est la mise en œuvre définie, bien que IEEE-754 soit de loin le plus courant.

Pour être sûr que IEEE-754 est utilisé:

  • en C, utilisez #ifdef __STDC_IEC_559__
  • en C++, utilisez les constantes std::numeric_limits<float>::is_iec559