Convertir une variable double en décimal

94

Comment jette-t-on un doubleà decimalqui est utilisé lors du développement de devises. Où Mva-t-il?

decimal dtot = (decimal)(doubleTotal);
flo
la source

Réponses:

83

Vous n'utilisez le que Mpour un littéral numérique, lorsque vous castez simplement:

decimal dtot = (decimal)doubleTotal;

Notez qu'un nombre à virgule flottante n'est pas adapté pour conserver une valeur exacte, donc si vous ajoutez d'abord des nombres ensemble, puis convertissez en, Decimalvous pouvez obtenir des erreurs d'arrondi. Vous souhaiterez peut-être convertir les nombres en Decimalavant de les additionner, ou vous assurer que les nombres ne sont pas des nombres à virgule flottante en premier lieu.

Guffa
la source
comme question complémentaire, pourquoi la conversion explicite est-elle nécessaire? Je l'ai essayé et j'obtiens une erreur selon laquelle un double ne peut pas être explicitement converti en décimal, mais un décimal n'a-t-il pas plus de précision? (c'est-à-dire un peu comme le casting d'un int vers un double peut être implicite.)
4
@Cortana: La précision d'une décimale est plus élevée, mais la plage est plus petite. Une valeur double peut être hors de portée pour une décimale. Voir: stackoverflow.com/questions/7817866/…
Guffa
40

Vous pouvez convertir un double en décimal comme ceci, sans avoir besoin du Msuffixe littéral:

double dbl = 1.2345D;
decimal dec = (decimal) dbl;

Vous devez utiliser le Mlors de la déclaration d'une nouvelle valeur décimale littérale:

decimal dec = 123.45M;

(Sans le M, 123.45 est traité comme un double et ne sera pas compilé.)

Chris Fulstow
la source
28

utiliser la classe de conversion par défaut: Convert.ToDecimal(Double)

Timur Sadykov
la source
1
Non car il lancera un double OverflowException vol_y = (double) Decimal.MaxValue + 10E + 28D; Console.WriteLine ("Convert.ToDecimal (vol_y) =" + Convert.ToDecimal (vol_y));
ToXinE
2
@ToXinE IMHO dans la plupart des cas, une OverflowException est meilleure que la création silencieuse de données erronées
this.myself
16
Convert.ToDecimal(the double you are trying to convert);
À M
la source
2
J'ai appris que la classe Convert est beaucoup plus flexible et sûre qu'une distribution en C #.
Tom
3
"Sûr"? comme quand il ne peut pas cast, il lève une exception au moment de l'exécution au lieu d'une erreur du compilateur? J'ai été mordu par ça tellement de fois que j'évite activement Convert ...
Peter Ritchie
8
Le fil @PeterRitchie est un peu vieux mais il faut le dire: appeler directement la méthode Convert serait l'approche la plus appropriée. Peut-être que je ne suis qu'un maniaque de l'optimisation, mais une instruction de moins à résoudre est un bonus (car l'utilisation de la syntaxe de conversion explicite (Type) est juste une surcharge d'opérateur qui appelle Convert).
Mike Johnson
1
@PeterRitchie: Du point de vue de la conception du langage, il aurait été préférable de demander à un programmeur d'utiliser l'une des deux méthodes de conversion plutôt que d'autoriser un transtypage de doublevers decimal, étant donné que pour une doublevaleur comme (1000000.0 / 3.0) on le ferait dans certains cas veulent couper une précision "excessive" donnant 333333,333333333D, mais dans d'autres cas, on voudrait la conserver, donnant 333333,333333333313931D. Plutôt que de simplement dire «convertir en décimal», le code doit spécifier comment cette conversion doit être effectuée.
supercat
2
@supercat qui ne semble vraiment pas lié à mon premier commentaire car l'utilisation Convert.ToDecimal(double)est la même que (decimal)doubleTotal, sauf si elle est doubleTotalmodifiée pour un type différent, vous éviterez probablement une erreur de compilation et introduiriez une erreur d'exécution plus difficile à trouver car un ToDecimal différent le remplacement peut être appelé. L'opérateur de distribution est beaucoup plus explicite ...
Peter Ritchie
1

Eh bien, c'est une vieille question et j'ai effectivement utilisé certaines des réponses présentées ici. Néanmoins, dans mon scénario particulier, il était possible que la doublevaleur vers laquelle je voulais convertir decimalsoit souvent supérieure à decimal.MaxValue. Donc, au lieu de gérer les exceptions, j'ai écrit cette méthode d'extension:

    public static decimal ToDecimal(this double @double) => 
        @double > (double) decimal.MaxValue ? decimal.MaxValue : (decimal) @double;

L'approche ci-dessus fonctionne si vous ne voulez pas vous soucier de la gestion des exceptions de débordement et si une telle chose se produit, vous voulez simplement garder la valeur maximale possible (mon cas), mais je suis conscient que pour de nombreux autres scénarios, ce ne serait pas le comportement attendu et peut être la gestion des exceptions sera nécessaire.

taquion
la source
1
Cela échouerait dans le cas suivant double _double = (double) decimal.MaxValue; Je suggérerais d'utiliser> = dans la comparaison public static decimal ToDecimal (this double _double) => _double> = (double) decimal.MaxValue? decimal.MaxValue: (décimal) _double;
Martin Eyles