Wandeln Sie eine doppelte Variable in eine Dezimalzahl um

90

Dies wird einigen wie eine dumme Frage erscheinen, aber ich muss ein Doppel in eine Dezimalzahl umwandeln, um sie als Währung zu verwenden. Wohin geht das M?

decimal dtot = (decimal)(doubleTotal);
flo
quelle

Antworten:

79

Sie verwenden das nur Mfür ein numerisches Literal, wenn Sie es umsetzen, ist es nur:

decimal dtot = (decimal)doubleTotal;

Beachten Sie, dass eine Gleitkommazahl nicht dazu geeignet ist, einen genauen Wert beizubehalten. Wenn Sie also zuerst Zahlen addieren und dann in konvertieren, Decimalkönnen Rundungsfehler auftreten. Möglicherweise möchten Sie die Zahlen konvertieren, Decimalbevor Sie sie addieren, oder sicherstellen, dass die Zahlen überhaupt keine Gleitkommazahlen sind.

Guffa
quelle
Warum ist als Folgefrage die explizite Konvertierung erforderlich? Ich habe es ausprobiert und erhalte die Fehlermeldung, dass ein Double nicht explizit in eine Dezimalzahl umgewandelt werden kann, aber eine Dezimalstelle nicht präziser ist. (dh ähnlich wie das
4
@Cortana: Die Genauigkeit einer Dezimalstelle ist höher, aber der Bereich ist kleiner. Ein Doppelwert kann für eine Dezimalstelle außerhalb des Bereichs liegen. Siehe: stackoverflow.com/questions/7817866/...
Guffa
39

Sie können ein Double in eine solche Dezimalzahl umwandeln, ohne das MLiteral-Suffix zu benötigen :

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

Sie sollten Folgendes verwenden, Mwenn Sie einen neuen wörtlichen Dezimalwert deklarieren:

decimal dec = 123.45M;

(Ohne das Mwird 123.45 als Double behandelt und nicht kompiliert.)

Chris Fulstow
quelle
28

Standardkonvertierungsklasse verwenden: Convert.ToDecimal(Double)

Timur Sadykov
quelle
1
Nein, da eine OverflowException ausgelöst wird. Double vol_y = (double) Decimal.MaxValue + 10E + 28D; Console.WriteLine ("Convert.ToDecimal (vol_y) =" + Convert.ToDecimal (vol_y));
ToXinE
2
@ ToXinE IMHO in den meisten Fällen ist eine OverflowException besser als ein stillschweigendes Erstellen falscher Daten
this.myself
16
Convert.ToDecimal(the double you are trying to convert);
Tom
quelle
2
Ich habe gelernt, dass die Convert-Klasse viel flexibler und sicherer ist als eine Besetzung in C #.
Tom
3
"Sicher"? Wie, wenn es nicht umgewandelt werden kann, wird zur Laufzeit eine Ausnahme anstelle eines Compilerfehlers ausgelöst? Ich bin so oft davon gebissen worden, dass ich Convert aktiv meide ...
Peter Ritchie
8
@ PeterRitchie-Thread ist ein bisschen alt, aber dies sollte gesagt werden: Das direkte Aufrufen der Convert-Methode wäre der geeignetere Ansatz. Vielleicht bin ich nur ein Optimierungsfreak, aber eine Anweisung weniger zu lösen ist ein Bonus (da die Verwendung der expliziten (Typ-) Cast-Syntax nur eine Operatorüberladung ist, die Convert aufruft).
Mike Johnson
1
@PeterRitchie: Aus Sicht des Sprachdesigns wäre es besser gewesen, von einem Programmierer eine von zwei Konvertierungsmethoden zu verlangen, als eine Typumwandlung von doublebis zuzulassen decimal, da dies für einen doubleWert wie (1000000.0 / 3.0) in einigen Fällen der Fall wäre möchte "überschüssige" Präzision abschneiden, was 333333.333333333D ergibt, aber in anderen Fällen möchte man sie beibehalten, was 333333.33333333333313931D ergibt. Anstatt einfach "in Dezimal konvertieren" zu sagen, sollte der Code angeben, wie diese Konvertierung durchgeführt werden soll.
Superkatze
2
@supercat, das wirklich nichts mit meinem ersten Kommentar zu tun zu haben scheint, da die Verwendung Convert.ToDecimal(double)dieselbe ist wie (decimal)doubleTotal, außer wenn Sie doubleTotalzu einem anderen Typ wechseln, würden Sie wahrscheinlich einen Fehler bei der Kompilierung vermeiden und einen schwer zu findenden Laufzeitfehler einführen, weil ein anderes ToDecimal Override wird möglicherweise aufgerufen. Cast Operator ist viel expliziter ...
Peter Ritchie
1

Nun, das ist eine alte Frage, und ich habe tatsächlich einige der hier gezeigten Antworten verwendet. In meinem speziellen Szenario war es jedoch möglich, dass der doubleWert, in den ich konvertieren wollte, decimaloft größer war als decimal.MaxValue. Anstatt Ausnahmen zu behandeln, habe ich diese Erweiterungsmethode geschrieben:

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

Der obige Ansatz funktioniert, wenn Sie sich nicht um die Behandlung von Überlaufausnahmen kümmern möchten und wenn so etwas passiert, möchten Sie nur den maximal möglichen Wert beibehalten (mein Fall), aber ich bin mir bewusst, dass dies für viele andere Szenarien nicht das erwartete Verhalten wäre und möglicherweise wird die Ausnahmebehandlung benötigt.

Taquion
quelle
1
Dies würde im folgenden Fall fehlschlagen double _double = (double) decimal.MaxValue; Ich würde vorschlagen,> = im Vergleich zu verwenden. Public static decimal ToDecimal (dieses doppelte _double) => _double> = (double) decimal.MaxValue? decimal.MaxValue: (dezimal) _double;
Martin Eyles