Wie konvertiere ich eine Dezimalstelle in eine Int?
Wie konvertiere ich eine Dezimalstelle in eine Int?
Antworten:
Verwenden Sie Convert.ToInt32
von mscorlib
wie in
decimal value = 3.14m;
int n = Convert.ToInt32(value);
Siehe MSDN . Sie können auch verwenden Decimal.ToInt32
. Siehe auch MSDN . Schließlich können Sie eine direkte Besetzung wie in machen
decimal value = 3.14m;
int n = (int) value;
welches den expliziten Besetzungsoperator verwendet. Siehe MSDN .
null
vs. 0
vs. ""
). Ich würde empfehlen, Convert niemals zu verwenden, es sei denn, Sie benötigen unbedingt seine Flexibilität (dh in dynamisch typisierten Szenarien)
OverflowException
. Ich glaube, dass @Will hier eine bessere Antwort bietet stackoverflow.com/a/501165/39532
Convert.ToInt32
und Decimal.ToInt32
verhalte dich anders. Von MSDN: Decimal.ToInt32
- Der Rückgabewert ist der integrale Bestandteil des Dezimalwerts; Bruchziffern werden abgeschnitten . Convert.ToInt32
- Rückgabewert auf die nächste 32-Bit-Ganzzahl mit Vorzeichen gerundet . Wenn der Wert auf halbem Weg zwischen zwei ganzen Zahlen liegt, wird die gerade Zahl zurückgegeben. Das heißt, 4.5 wird in 4 und 5.5 in 6 konvertiert.
Das kannst du nicht.
Natürlich könnten Sie das , aber ein int (System.Int32) ist nicht groß genug, um jeden möglichen Dezimalwert aufzunehmen.
Das heißt, wenn Sie eine Dezimalstelle umwandeln, die größer als int.MaxValue ist, wird sie überlaufen, und wenn die Dezimalstelle kleiner als int.MinValue ist, wird sie unterlaufen.
Was passiert, wenn Sie unter / überlaufen? Eines von zwei Dingen. Wenn Ihr Build deaktiviert ist (dh die CLR kümmert sich nicht darum, wenn Sie dies tun), wird Ihre Anwendung nach dem Über- / Unterlauf des Werts fortgesetzt, aber der Wert im int entspricht nicht Ihren Erwartungen. Dies kann zu zeitweiligen Fehlern führen und ist möglicherweise schwer zu beheben. Ihre Anwendung befindet sich in einem unbekannten Zustand, was dazu führen kann, dass Ihre Anwendung alle wichtigen Daten beschädigt, an denen sie arbeitet. Nicht gut.
Wenn Ihre Assembly aktiviert ist (Eigenschaften-> Build-> Erweitert-> Auf arithmetischen Überlauf / Unterlauf prüfen oder die Compileroption / geprüft), löst Ihr Code eine Ausnahme aus, wenn ein Unter- / Überlauf auftritt. Das ist wahrscheinlich besser als nicht; Die Standardeinstellung für Baugruppen ist jedoch nicht die Überprüfung auf Über- / Unterlauf.
Die eigentliche Frage ist: "Was versuchst du zu tun?" Ohne Ihre Anforderungen zu kennen, kann Ihnen niemand sagen, was Sie in diesem Fall tun sollen , außer dem Offensichtlichen: TUN SIE ES NICHT.
Wenn Sie sich speziell NICHT darum kümmern, sind die Antworten hier gültig. Sie sollten jedoch Ihr Verständnis darüber kommunizieren , dass ein Überlauf auftreten kann und dass dies keine Rolle spielt, indem Sie Ihren Cast-Code in einen ungeprüften Block einschließen
unchecked
{
// do your conversions that may underflow/overflow here
}
Auf diese Weise verstehen die Leute, die hinter Ihnen stehen, dass es Ihnen egal ist, und wenn in Zukunft jemand Ihre Builds ändert / überprüft, wird Ihr Code nicht unerwartet kaputt gehen.
Wenn Sie nur den Bruchteil der Zahl löschen und den integralen Teil belassen möchten, können Sie Math.Truncate verwenden.
decimal actual = 10.5M;
decimal expected = 10M;
Assert.AreEqual(expected, Math.Truncate(actual));
int i = (int)d;
gibt Ihnen die abgerundete Zahl.
Wenn Sie auf die nächste gerade Zahl runden möchten (dh> .5 wird aufgerundet), können Sie verwenden
int i = (int)Math.Round(d, MidpointRounding.ToEven);
Im Allgemeinen können Sie zwischen allen numerischen Typen in C # wechseln. Wenn während der Besetzung keine Informationen verloren gehen, können Sie dies implizit tun:
int i = 10;
decimal d = i;
Sie können dies jedoch trotzdem explizit tun, wenn Sie dies wünschen:
int i = 10;
decimal d = (decimal)i;
Wenn Sie jedoch Informationen durch die Besetzung verlieren möchten, müssen Sie dies explizit tun (um zu zeigen, dass Sie sich bewusst sind, dass Sie möglicherweise Informationen verlieren):
decimal d = 10.5M;
int i = (int)d;
Hier verlieren Sie die ".5". Dies mag in Ordnung sein, aber Sie müssen dies explizit angeben und eine explizite Besetzung vornehmen, um zu zeigen, dass Sie möglicherweise die Informationen verlieren.
ToEven
sollten Sie statistische Abweichungen verhindern. Wenn Sie jedoch mit kostenpflichtigen Gegenständen oder Geld arbeiten, AwayFromZero
scheint dies die richtige Wahl zu sein.
decimal vIn = 0.0M;
int vOut = Convert.ToInt32(vIn);
Hier ist eine sehr praktische Webseite zum Konvertieren von Datentypen für andere. http://www.convertdatatypes.com/Convert-decimal-to-int-in-CSharp.html
System.Decimal
implementiert die IConvertable
Schnittstelle, die ein ToInt32()
Mitglied hat.
Funktioniert das Anrufen System.Decimal.ToInt32()
für Sie?
Ein guter Trick für eine schnelle Rundung besteht darin, 0,5 hinzuzufügen, bevor Sie Ihre Dezimalstelle in ein Int umwandeln.
decimal d = 10.1m;
d += .5m;
int i = (int)d;
Geht noch i=10
, aber
decimal d = 10.5m;
d += .5m;
int i = (int)d;
Würde so aufrunden i=11
.
Ich bevorzuge die Verwendung von Math.Round , Math.Floor , Math.Ceiling oder Math.Truncate , um den Rundungsmodus explizit entsprechend festzulegen .
Beachten Sie, dass alle auch Decimal zurückgeben - da Decimal einen größeren Wertebereich als ein Int32 hat, müssen Sie dennoch umwandeln (und auf Überlauf / Unterlauf prüfen).
checked {
int i = (int)Math.Floor(d);
}
Runden einer Dezimalstelle auf die nächste Ganzzahl
decimal a ;
int b = (int)(a + 0.5m);
wann a = 49.9
dannb = 50
wann a = 49.5
dannb = 50
wann a = 49.4
, dann b = 49
etc.
Ich finde, dass der Casting-Operator nicht funktioniert, wenn Sie eine Box-Dezimalstelle haben (dh einen Dezimalwert innerhalb eines Objekttyps). Convert.ToInt32 (dezimal als Objekt) funktioniert in diesem Fall einwandfrei.
Diese Situation tritt auf, wenn IDENTITY / AUTONUMBER-Werte aus der Datenbank abgerufen werden:
SqlCommand foo = new SqlCommand("INSERT INTO...; SELECT SCOPE_IDENTITY()", conn);
int ID = Convert.ToInt32(foo.ExecuteScalar()); // works
int ID = (int)foo.ExecuteScalar(); // throws InvalidCastException
SELECT SCOPE_IDENTITY()
zurückgegeben, numeric(38, 0)
was decimal
von .NET übersetzt wird. foo.ExecuteScalar()
Gibt eine decimal
Box zurück, object
die nicht direkt in eine umgewandelt werden kann int
. (int)(decimal)foo.ExecuteScalar()
oder Convert.ToInt32(foo.ExecuteScalar())
würde funktionieren.
Keine Antwort scheint sich mit der OverflowException / UnderflowException zu befassen, die beim Versuch entsteht, eine Dezimalstelle zu konvertieren, die außerhalb des Bereichs von int liegt.
int intValue = (int)Math.Max(int.MinValue, Math.Min(int.MaxValue, decimalValue));
Diese Lösung gibt den maximal möglichen oder minimalen int-Wert zurück, wenn der Dezimalwert außerhalb des int-Bereichs liegt. Möglicherweise möchten Sie mit Math.Round, Math.Ceiling oder Math.Floor eine Rundung hinzufügen, wenn der Wert innerhalb des int-Bereichs liegt.