Es wäre hilfreich zu wissen, ob Sie auf das nächste int runden oder nur die Zahlen nach der Dezimalstelle fallen lassen möchten (dh: immer abrunden)
Dinah
128
Ich sehe ehrlich gesagt keinen Sinn darin, echte Fragen herunterzustimmen. Ja, die Antwort könnte auf Google gefunden werden, aber würde es nicht einfach die Qualität der Website verbessern, wenn die Leute aufhören würden, jede zweite Frage zu schließen? Es ist nicht so, dass diese Frage Spam oder so ist, und ich bin sicher, dass es für viele
Neulinge
Antworten:
268
Verwenden Sie Convert.ToInt32von mscorlibwie in
decimalvalue=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
decimalvalue=3.14m;int n =(int)value;
welches den expliziten Besetzungsoperator verwendet. Siehe MSDN .
Achtung: Convert hat ein überraschendes Verhalten für bestimmte Conversions ( nullvs. 0vs. ""). Ich würde empfehlen, Convert niemals zu verwenden, es sei denn, Sie benötigen unbedingt seine Flexibilität (dh in dynamisch typisierten Szenarien)
Eamon Nerbonne
1
-1, da dies für Werte wie decimal.MaxValue und decimal.MinValue nicht funktioniert und zu einem führt OverflowException. Ich glaube, dass @Will hier eine bessere Antwort bietet stackoverflow.com/a/501165/39532
Mezoid
8
Sei vorsichtig, denn Convert.ToInt32und Decimal.ToInt32verhalte 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.
vezucci
67
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));
Obwohl ich vermute, dass sie unter der Haube dasselbe sind, wenn die Eingabe eine Dezimalzahl ist, fühle ich mich mit Decimal.Truncate wohler als mit Math.Truncate, da letzteres auch Doubles akzeptiert und daher so verstanden werden kann, dass gerade Zahlen abgeschnitten werden können das sind nicht Basis 10, im Gegensatz zu Decimal.Truncate, was eine echte Kürzung einer Basis 10-Zahl ist.
Brian
7
Nicht aktivierte Kontexte gelten nicht für Dezimalstellen. Operationen mit Dezimalstellen lösen unabhängig davon OverflowExceptions aus.
Dave
46
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.
Sie möchten tatsächlich, dass MidpointRounding.AwayFromZero immer * * .5 aufgerundet wird
Elijah Lofgren
@ElijahLofgren Es kommt irgendwie darauf an: Wenn Sie Statistiken erstellen, ToEvensollten Sie statistische Abweichungen verhindern. Wenn Sie jedoch mit kostenpflichtigen Gegenständen oder Geld arbeiten, AwayFromZeroscheint dies die richtige Wahl zu sein.
Aus der Dokumentation : "Diese API unterstützt die .NET Framework-Infrastruktur und ist nicht für die direkte Verwendung in Code vorgesehen." Warum nicht Convert.ToInt32 verwenden?
H. Wolper
7
Ein guter Trick für eine schnelle Rundung besteht darin, 0,5 hinzuzufügen, bevor Sie Ihre Dezimalstelle in ein Int umwandeln.
Warum sich die Mühe machen, wenn es Math.Floor und Math.Ceiling gibt?
Badaro
Zu dieser Zeit war ich ziemlich neu in C # und aus irgendeinem Grund wusste ich nicht, dass diese Funktionen existieren. Es ist eigentlich ein Trick, den ich aus C / C ++ gelernt habe, wo er offensichtlich nützlicher war.
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).
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 =newSqlCommand("INSERT INTO...; SELECT SCOPE_IDENTITY()", conn);int ID =Convert.ToInt32(foo.ExecuteScalar());// worksint ID =(int)foo.ExecuteScalar();// throws InvalidCastException
Hinzufügen von mehr als Referenz: Dies liegt daran, dass Sie nur den gleichen Originaltyp entpacken können. Hier wird SELECT SCOPE_IDENTITY()zurückgegeben, numeric(38, 0)was decimalvon .NET übersetzt wird. foo.ExecuteScalar()Gibt eine decimalBox zurück, objectdie nicht direkt in eine umgewandelt werden kann int. (int)(decimal)foo.ExecuteScalar()oder Convert.ToInt32(foo.ExecuteScalar())würde funktionieren.
Rageit
0
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.
Antworten:
Verwenden Sie
Convert.ToInt32
vonmscorlib
wie inSiehe MSDN . Sie können auch verwenden
Decimal.ToInt32
. Siehe auch MSDN . Schließlich können Sie eine direkte Besetzung wie in machenwelches den expliziten Besetzungsoperator verwendet. Siehe MSDN .
quelle
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/39532Convert.ToInt32
undDecimal.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
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.
quelle
gibt Ihnen die abgerundete Zahl.
Wenn Sie auf die nächste gerade Zahl runden möchten (dh> .5 wird aufgerundet), können Sie verwenden
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:
Sie können dies jedoch trotzdem explizit tun, wenn Sie dies wünschen:
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):
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.
quelle
ToEven
sollten Sie statistische Abweichungen verhindern. Wenn Sie jedoch mit kostenpflichtigen Gegenständen oder Geld arbeiten,AwayFromZero
scheint dies die richtige Wahl zu sein.Dies sollte gut funktionieren.
quelle
Hier ist eine sehr praktische Webseite zum Konvertieren von Datentypen für andere. http://www.convertdatatypes.com/Convert-decimal-to-int-in-CSharp.html
quelle
System.Decimal
implementiert dieIConvertable
Schnittstelle, die einToInt32()
Mitglied hat.Funktioniert das Anrufen
System.Decimal.ToInt32()
für Sie?quelle
Ein guter Trick für eine schnelle Rundung besteht darin, 0,5 hinzuzufügen, bevor Sie Ihre Dezimalstelle in ein Int umwandeln.
Geht noch
i=10
, aberWürde so aufrunden
i=11
.quelle
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).
quelle
dezimal
d = 5.5
;ref: Linktext
quelle
Runden einer Dezimalstelle auf die nächste Ganzzahl
wann
a = 49.9
dannb = 50
wann
a = 49.5
dannb = 50
wann
a = 49.4
, dannb = 49
etc.quelle
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:
Siehe 4.3.2 Unboxing-Konvertierungen
quelle
SELECT SCOPE_IDENTITY()
zurückgegeben,numeric(38, 0)
wasdecimal
von .NET übersetzt wird.foo.ExecuteScalar()
Gibt einedecimal
Box zurück,object
die nicht direkt in eine umgewandelt werden kannint
.(int)(decimal)foo.ExecuteScalar()
oderConvert.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.
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.
quelle