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
.. 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?
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 Single
doit peut perdre des informations.
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.
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.
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.
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.
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.