Konvertieren eines Double in ein Int in C #

101

In unserem Code haben wir ein Double, das wir in ein Int konvertieren müssen.

double score = 8.6;
int i1 = Convert.ToInt32(score);
int i2 = (int)score;

Kann mir jemand erklären warum i1 != i2?

Das Ergebnis, das ich bekomme, ist das: i1 = 9und i2 = 8.

Wouter Dorgelo
quelle
5
Math.Truncate(score)ist explizit ausdrückliche Absicht als(int)score
Lu55
3
Aber Math.Truncate gibt ein Doppel oder eine Dezimalzahl zurück, kein int
Sergioet

Antworten:

160

Weil Convert.ToInt32Runden:

Rückgabewert: Auf die nächste vorzeichenbehaftete 32-Bit-Ganzzahl 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.

... während die Besetzung abschneidet :

Wenn Sie von einem Double- oder Float-Wert in einen Integraltyp konvertieren, wird der Wert abgeschnitten.

Update: Weitere Unterschiede finden Sie im Kommentar von Jeppe Stig Nielsen (die jedoch nicht ins Spiel kommen, wenn scorees sich um eine reelle Zahl handelt, wie dies hier der Fall ist).

Jon
quelle
6
Ihr Link erklärt es tatsächlich am besten und es ist nicht so einfach wie rund oder abgeschnitten: Typ: System.Int32-Wert, 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.
Ericosg
@ericosg: Ja, das würde den Unterschied maskieren , wenn scorewaren 8.5statt 8.6. Ich habe die Antwort aktualisiert, um die Anführungszeichen aufzunehmen. Danke für die Eingabe.
Jon
5
Und wenn scorees NaNoder eine Unendlichkeit oder Endlichkeit ist, aber außerhalb des Bereichs von Int32, dann Convert.ToInt32wird eine Ausnahme ausgelöst. Die Besetzung wird eine zurückgeben int, aber Sie werden nicht wissen, welche (in meiner Implementierung Int32.MinValue), weil Sie sich im uncheckedKontext befinden. (Sollten Sie im checkedKontext sein, wird die Besetzung auch in diesen Fällen eine Ausnahme
Jeppe Stig Nielsen
@JeppeStigNielsen: Danke für die Eingabe, ich habe die Antwort aktualisiert, um dies auch zu erwähnen.
Jon
Nett. Aber ich denke, die DoubleTypennummer 10000000000.6(zehn Milliarden Punkt sechs) ist eine "echte" Zahl. Wenn Sie eine Besetzung verwenden int, wird dies zu einem seltsamen Ergebnis führen (es sei denn, Sie befinden sich im checkedKontext, aber wahrscheinlich nicht).
Jeppe Stig Nielsen
13

Beim Casting wird alles nach dem Dezimalpunkt ignoriert, sodass aus 8,6 8 wird.

Convert.ToInt32(8.6) Dies ist der sichere Weg, um sicherzustellen, dass Ihr Double auf die nächste Ganzzahl gerundet wird, in diesem Fall 9.

Neilgmacy
quelle
1
Bonusfrage - Was passiert, wenn der Wert des Doppelten zu groß ist, um in den Int zu drücken ? Dh wenn es höher als int.MAX_VAL ist ?
Konrad Viltersten
1
@KonradViltersten Löst eine Ausnahme aus. Der Wert war entweder zu groß oder zu klein für einen Int32.
Vamsi
11

Sie können Ihr Doppel runden und werfen ist:

(int)Math.Round(myDouble);
David
quelle
4
Die Frage war nun, wie man es macht i1 == i2. Die Frage war, warum sie nicht gleich sind. Abgestimmt.
Adam
5

Im angegebenen Beispiel ist Ihre Dezimalstelle 8,6 . Wäre es 8,5 oder 9,5 gewesen, wäre die Aussage i1 == i2 möglicherweise wahr gewesen. Tatsächlich wäre es für 8.5 wahr und für 9.5 falsch gewesen.

Erläuterung:

Unabhängig vom Dezimalteil int i2 = (int)scoreverwirft die zweite Anweisung den Dezimalteil und gibt Ihnen einfach den ganzzahligen Teil zurück. Sehr gefährlich, da Datenverlust auftreten kann.

Für die erste Aussage können nun zwei Dinge passieren. Wenn der Dezimalteil 5 ist, dh auf halbem Weg ist, muss eine Entscheidung getroffen werden. Runden wir auf oder ab? In C # implementiert die Convert-Klasse die Rundung des Bankiers. Sehen Sie das Informationen finden Antwort. Einfach ausgedrückt, wenn die Zahl gerade ist, runden Sie ab, wenn die Zahl ungerade ist, runden Sie auf.

ZB bedenken Sie:

        double score = 8.5;
        int i1 = Convert.ToInt32(score); // 8
        int i2 = (int)score;             // 8

        score += 1;
        i1 = Convert.ToInt32(score);     // 10
        i2 = (int)score;                 // 9
Evdzhan Mustafa
quelle
2

ToInt32 Runden. Das Casting in int wirft nur die nicht ganzzahlige Komponente weg.


quelle