Conversion d'un double en un entier en C #

103

Dans notre code, nous avons un double que nous devons convertir en un entier.

double score = 8.6;
int i1 = Convert.ToInt32(score);
int i2 = (int)score;

Quelqu'un peut-il m'expliquer pourquoi i1 != i2?

Le résultat que j'obtiens est que: i1 = 9et i2 = 8.

Wouter Dorgelo
la source
5
Math.Truncate(score)est une intention plus explicitement exprimée que(int)score
Lu55
3
Mais Math.Truncate renvoie un double ou une décimale, pas un int
Sergioet

Réponses:

165

Parce que les Convert.ToInt32tours:

Valeur de retour: arrondi à l'entier signé 32 bits le plus proche. Si la valeur est à mi-chemin entre deux nombres entiers, le nombre pair est renvoyé; c'est-à-dire que 4,5 est converti en 4 et 5,5 est converti en 6.

... pendant que le casting tronque :

Lorsque vous convertissez une valeur double ou flottante en un type intégral, la valeur est tronquée.

Mise à jour: Voir le commentaire de Jeppe Stig Nielsen ci-dessous pour des différences supplémentaires (qui cependant n'entrent pas en jeu s'il scores'agit d'un nombre réel comme c'est le cas ici).

Jon
la source
6
Votre lien l'explique le mieux, et ce n'est pas aussi simple que round vs truncate: Type: valeur System.Int32, arrondie à l'entier signé 32 bits le plus proche. Si la valeur est à mi-chemin entre deux nombres entiers, le nombre pair est renvoyé; c'est-à-dire que 4,5 est converti en 4 et 5,5 est converti en 6.
ericosg
@ericosg: Ouais, cela masquerait la différence si scorec'était 8.5au lieu de 8.6. J'ai mis à jour la réponse pour inclure les citations. Merci pour la contribution.
Jon
5
Et si scoreest NaNou un infini ou fini mais en dehors de la plage de Int32, alors Convert.ToInt32lèvera une exception. Cast retournera un int, mais vous ne saurez pas lequel (dans mon implémentation c'est Int32.MinValue) parce que vous êtes dans le uncheckedcontexte. (Si vous êtes dans le checkedcontexte, le casting lancera également une exception dans ces cas.)
Jeppe Stig Nielsen
@JeppeStigNielsen: Merci pour la contribution, j'ai mis à jour la réponse pour mentionner cela aussi.
Jon
Agréable. Mais je pense que le Doublenombre type 10000000000.6(dix milliards virgule six) est un nombre «réel». Utiliser un casting intsur qui donnera un résultat étrange (sauf si vous êtes dans le checkedcontexte, mais vous ne l'êtes probablement pas).
Jeppe Stig Nielsen
13

La diffusion ignorera tout ce qui se trouve après la virgule décimale, donc 8.6 devient 8.

Convert.ToInt32(8.6) est le moyen sûr de s'assurer que votre double est arrondi à l'entier le plus proche, dans ce cas 9.

négligence
la source
1
Question bonus - que se passe-t-il si la valeur du double est trop grande pour être poussée dans l' int ? C'est-à-dire s'il est supérieur à int.MAX_VAL ?
Konrad Viltersten le
1
@KonradViltersten Lève une exception La valeur était soit trop grande soit trop petite pour un Int32.
Vamsi
11

vous pouvez arrondir votre double et lancer ist:

(int)Math.Round(myDouble);
David
la source
4
la question était maintenant de savoir comment faire i1 == i2. La question était de savoir pourquoi ils ne sont pas égaux. Voté contre.
Adam
5

Dans l'exemple fourni, votre décimal est 8,6 . S'il avait été 8,5 ou 9,5, l'affirmation i1 == i2 aurait pu être vraie. En fait, cela aurait été vrai pour 8,5 et faux pour 9,5.

Explication:

Indépendamment de la partie décimale, la deuxième instruction int i2 = (int)scoresupprimera la partie décimale et vous renverra simplement la partie entière. Chose assez dangereuse à faire, car une perte de données pourrait survenir.

Maintenant, pour la première déclaration, deux choses peuvent arriver. Si la partie décimale est 5, c'est-à-dire qu'elle est à mi-chemin, une décision doit être prise. Arrondissons-nous vers le haut ou vers le bas? En C #, la classe Convert implémente l'arrondi du banquier. Voir cette réponse pour une explication plus approfondie. En termes simples, si le nombre est pair, arrondissez vers le bas, si le nombre est impair, arrondissez vers le haut.

Par exemple, considérez:

        double score = 8.5;
        int i1 = Convert.ToInt32(score); // 8
        int i2 = (int)score;             // 8

        score += 1;
        i1 = Convert.ToInt32(score);     // 10
        i2 = (int)score;                 // 9
Evdzhan Mustafa
la source
2

ToInt32 tours. La conversion en int jette simplement le composant non entier.


la source