web-dev-qa-db-fra.com

Lorsque la conversion d'Integer en Single peut perdre en précision

Je lisais n article de Microsoft concernant l'élargissement des conversions et l'option Strict On quand je suis arrivé à la partie

Les conversions suivantes peuvent perdre en précision:

  • Entier à célibataire
  • Longue à simple ou double
  • Décimal en simple ou double

Cependant, ces conversions ne perdent ni informations ni ampleur.

.. mais selon n autre article concernant les types de données ,

  • Le type entier peut stocker de -2.147.483.648 à 2.147.483.647 et

  • Un seul type peut stocker à partir de

    • 1,401298E-45 à 3,4028235E + 38 pour les nombres positifs,
    • et -3,4028235E + 38 à - 1,401298E-45 pour les nombres négatifs

.. donc Single peut stocker beaucoup plus de nombres qu'Integer. Je ne pouvais pas comprendre dans quelle situation une telle conversion d'Integer en Single peut perdre en précision. Quelqu'un pourrait-il expliquer, s'il vous plaît?

27
Vinicius V

Single peut stocker beaucoup plus de nombres qu'Integer

Non, ça ne peut pas. Single et Integer sont tous deux de 32 bits, ce qui signifie que les deux peuvent stocker la quantité exactement la même de nombres, soit 232 = 4294967296 nombres distincts.

Étant donné que le plage de Single est clairement plus grand que cela, il est immédiatement évident (en raison du Pigeonhole Principle) qu'il ne peut pas éventuellement représente tous les nombres dans cette plage.

Et puisque la plage de Integer a exactement la même taille que le nombre maximal de nombres que Integer et Single peuvent représenter, mais Single peut également représenter nombres en dehors de cette plage, il est clair qu'il ne peut pas représenter tous les nombres à l'intérieur de la plage de Integer.

S'il existe certains nombres de Integer qui ne peuvent pas être représentés dans Single, la conversion de Integer en Singledoit peut perdre des informations.

87
Jörg W Mittag

Les types à virgule flottante (tels que simple et double) sont représentés en mémoire par un signe, une mantisse et un exposant. Considérez-le comme une notation scientifique:

Sign*Mantissa*Base^Exponent

Ils - comme vous pouvez vous y attendre - utilisent la base 2. Il existe d'autres ajustements qui permettent de représenter l'infini et le NaN, et l'exposant est décalé (y reviendra), et un raccourci pour la mantisse (y reviendra aussi) . Recherchez la norme IEEE 754 qui couvre sa représentation et ses opérations pour plus de détails.

Pour nos besoins, nous pouvons l'imaginer comme un nombre binaire "mantisse", et un "exposant" qui vous indique où placer le séparateur décimal.


Dans le cas de Single, nous avons 1 bit pour le signe he, 8 pour l'exposant et 23 pour la mantisse.

Maintenant, le fait est que nous allons stocker la mantisse du chiffre le plus significatif. N'oubliez pas que tous les zéros à gauche ne sont pas pertinents. Et étant donné que nous travaillons en binaire, nous savons que le chiffre le plus significatif est un 1 ※. Eh bien, puisque nous le savons, nous n'avons pas à le stocker. Grâce à ce raccourci, la plage effective de la mantisse est de 24 bits.

※: À moins que le nombre que nous stockons soit nul. Pour cela, nous aurons tous les bits mis à zéro. Cependant, si nous essayons d'interpréter cela sous la description que j'ai donnée, vous auriez un 2 ^ 24 (le 1 implicite) multiplié par 1 (2 à la puissance de l'exposant 0). Donc, pour y remédier, l'exposant zéro est une valeur spéciale. Il existe également des valeurs spéciales pour stocker l'infini et NaN dans l'exposant.

Selon le décalage de l'exposant - en plus d'éviter les valeurs spéciales - son décalage permet de placer le point décimal avant le début de la mantisse ou après sa fin, sans avoir besoin d'avoir un signe pour l'exposant.


Cela signifie que pour les grands nombres, le type à virgule flottante placera le point décimal au-delà de la fin de la mantisse.

N'oubliez pas que la mantisse est un nombre de 24 bits. Il ne représentera jamais un nombre de 25 bits ... il n'a pas ce bit supplémentaire. Ainsi, le single ne peut pas distinguer entre 2 ^ 24 et 2 ^ 24 + 1 (ce sont les premiers nombres de 25 bits, et ils diffèrent sur le dernier bit, qui n'est pas représenté dans le single).

Ainsi, pour les entiers, la plage du simple est de -2 ^ 24 à 2 ^ 24. Et essayer d'ajouter 1 à 2 ^ 24 donnera 2 ^ 24 (car en ce qui concerne le type, 2 ^ 24 et 2 ^ 24 + 1 ont la même valeur). Essayez-le en ligne . C'est pourquoi il y a une perte d'informations lors de la conversion d'un entier en un seul. Et c'est aussi pourquoi une boucle qui utilise un simple ou un double pourrait en fait être une boucle infinie sans que vous vous en rendiez compte.

28
Theraot

Voici un exemple réel de la perte de précision lors de la conversion de Integer en Single:

Le type Single peut stocker tous les entiers de -16777216 à 16777216 (inclus), mais il ne peut pas stocker tous les entiers en dehors de cette plage. Par exemple, il ne peut pas stocker le numéro 16777217. Pour cette raison, il ne peut pas stocker tout nombre impair supérieur à 16777216.

Nous pouvons utiliser Windows PowerShell pour voir ce qui se passe si nous convertissons un Integer en Single et vice-versa:

PS C:\Users\tanne> [int][float]16777213
16777213
PS C:\Users\tanne> [int][float]16777214
16777214
PS C:\Users\tanne> [int][float]16777215
16777215
PS C:\Users\tanne> [int][float]16777216
16777216
PS C:\Users\tanne> [int][float]16777217
16777216
PS C:\Users\tanne> [int][float]16777218
16777218
PS C:\Users\tanne> [int][float]16777219
16777220

Notez que 16777217 a été arrondi à 16777216 et 16777219 a été arrondi à 16777220.

25
Tanner Swett

Les types à virgule flottante sont similaires à la "notation scientifique" en physique. Le nombre est divisé en un bit de signe, un exposant (multiplicateur) et une mantisse (chiffres significatifs). Ainsi, à mesure que l'amplitude de la valeur augmente, la taille du pas augmente également.

La virgule flottante simple précision a 23 bits de mantisse, mais il y a un "implicite 1", donc la mantisse est effectivement de 24 bits. Par conséquent, tous les entiers d'une magnitude allant jusqu'à 224 peut être représenté exactement en virgule flottante simple précision.

Au-dessus, on peut représenter successivement moins de nombres.

  • À partir de 224 à 225 seuls les nombres pairs peuvent être représentés.
  • À partir de 225 à 226 seuls les multiples de 4 peuvent être représentés.
  • À partir de 226 à 227 seuls les multiples de 8 peuvent être représentés.
  • À partir de 227 à 228 seuls les multiples de 16 peuvent être représentés
  • À partir de 228 à 229 seuls les multiples de 32 peuvent être représentés
  • À partir de 229 à 230 seuls les multiples de 64 peuvent être représentés
  • À partir de 230 à 231 seuls les multiples de 128 peuvent être représentés

Donc des 232 valeurs entières signées 32 bits possibles seulement 2 * (224 + 7 * 223) = 9 * 224 peut être représenté en virgule flottante simple précision. Cela représente 3,515625% du total.

12
Peter Green

Les flotteurs simple précision ont 24 bits de précision. Tout ce qui dépasse est arrondi au nombre de 24 bits le plus proche. Il pourrait être plus facile à comprendre en notation scientifique décimale, mais gardez à l'esprit que les flottants réels utilisent le binaire.

Supposons que vous disposez de 5 chiffres décimaux de mémoire. Vous pouvez choisir d'utiliser ceux comme un entier non signé régulier, vous permettant d'avoir n'importe quel nombre entre 0 et 99999. Si vous voulez pouvoir représenter des nombres plus grands, vous pouvez utiliser la notation scientifique et allouer simplement deux chiffres pour être l'exposant, donc vous pouvez maintenant représenter n'importe quoi entre 0 et 9,99 x 1099.

Cependant, le plus grand nombre que vous pouvez représenter exactement est maintenant seulement 999. Si vous avez essayé de représenter 12345, vous pouvez obtenir 1,23 x 104ou 1,24 x 104, mais vous ne pouvez représenter aucun des nombres intermédiaires, car vous ne disposez pas de suffisamment de chiffres.

8
Karl Bielefeldt