2010-04-07 5 views
9

Jede intelligente Art und Weise einen Schwimmer so zu konvertieren:C# Schwimmer Dezimalumwandlung

float f = 711989.98f; 

in eine Dezimalzahl (oder doppelt), ohne zu verlieren Präzision?

Ich habe versucht:

decimal d = (decimal)f; 
decimal d1 = (decimal)(Math.Round(f,2)); 
decimal d2 = Convert.ToDecimal(f); 
+0

Weitere Details: ich mit einem alten webservice bin eine Schnittstelle, die dieses große Objekt sendet, die einige Felder als Schwimmer hat. Wenn ich die Umwandlung in Dezimal-Kaboom mache ... keine Pennies mehr! – Adrian4B

+0

Wenn dies von einem Web-Service auf der Leitung kommt, ist es wahrscheinlich XML, was bedeutet, dass kein Float oder Dezimalzahlen - nur Strings. Suchen Sie, wo diese Zeichenfolgen in "internes" Format konvertiert werden – mfeingold

Antwort

11

Es ist zu spät, die 8. Ziffer ging im Compiler verloren. Der Float-Typ kann nur 7 signifikante Ziffern speichern. Sie müssen den Code neu schreiben, die Zuordnung zu Doppel-oder Dezimal wird natürlich das Problem lösen.

+0

danke Ich habe den Typ des Feldes auf zugeordnetes Objekt von Float zu Dezimal geändert und das Konvertierungsproblem gelöst, das während der Deserialisierung aufgetreten ist. – Adrian4B

1

haben Sie versucht?

decimal.TryParse() 

http://forums.asp.net/t/1161880.aspx

Es gibt keine impliziten Konvertierungen zwischen float/double und dezimal. Implizite numerische Konvertierungen sind immer garantiert ohne Genauigkeits- oder Größenverlust und verursachen keine Ausnahme.

+1

Implizite Konvertierungen sind nicht garantiert ohne Genauigkeitsverlust. Konvertieren von '9007199791611905' in' double' ergibt '9007199791611904'. Die direkte Konvertierung in 'float' ergibt' 9007200328482816'. Die Umwandlung in "double" und dann in "float" ergibt "9007199254740992" (was um mehr geht, als wenn die Zahl direkt in 'float' umgewandelt worden wäre). Während Compiler eine implizite Umwandlung von "float" in "double" erlauben, sind solche Konvertierungen weit wahrscheinlicher fehlerhafter als Konvertierungen von "double" in "float", die nicht erlaubt sind, aber sein sollten. – supercat

+1

@supercat anscheinend [Sie können verlustfrei 'float' in' double' konvertieren (http://stackoverflow.com/q/40550861/24874). Die Umwandlung von "double" in "float" führt jedoch wahrscheinlich zu Fehlern, je nachdem, um welchen spezifischen "doppelten" Wert es sich handelt. –

+0

@DrewNoakes: Wenn man eine iterative Berechnung verwendet hat, um die Position eines Objekts mit dem Typ 'double' zu ​​berechnen, und dann mit Grafikroutinen, die' float' akzeptieren, zeichnen würde, würde die Umwandlung in 'float' die Genauigkeit verringern nutzlos, selbst wenn es beibehalten wird; Die Genauigkeit zu verringern würde fast sicher mit der Absicht des Programmierers übereinstimmen. Wenn dagegen ein Code z.B.teilt ein 'int' oder' long' mit einem 'float' und speichert das Ergebnis in einem' double'. Wenn der Programmierer das Ergebnis der Division nicht explizit auf 'float' ausgibt, würde ich nicht davon ausgehen, dass der Programmierer ... – supercat

1

Sie verloren Präzision, sobald Sie 711989.98f geschrieben haben.

711989.98 ist dezimal. Mit f am Ende bitten Sie den Compiler, es in float zu konvertieren. Diese Konvertierung kann nicht ohne Genauigkeitsverlust durchgeführt werden.

Was Sie wahrscheinlich wollen, ist dezimal d = 711989.98m. Dies wird nicht die Genauigkeit verlieren.

+0

Ihr Beispiel verwendet nur ein Double, oder? Es könnte immer noch die Genauigkeit für eine andere Nummer verlieren. Setzen Sie einfach ein "m" am Ende und machen Sie das Literal eine Dezimalzahl, um mit zu beginnen. –

1

Dies kann ein Compiler Fehler sein, weil es wie ein gültiger Schwimmer scheint in eine Dezimalzahl direkt umwandeln sollte. aber es wird nicht ohne Auflösung verlieren. Die Konvertierung von 125.609375 von Float in Dezimal wird die Auflösung verlieren. Die Konvertierung von float nach double und dann double in decimal wird jedoch die Auflösung beibehalten.

float float_val = 125.609375f; 

    decimal bad_decimal_val = (decimal)float_val; //125.6094 

    double double_val = (double)float_val; 
    decimal good_decimal_val = (decimal)double_val;