C# ConvertToInt32 - Rundet, warum?

Basinator

Lt. Junior Grade
Registriert
Jan. 2009
Beiträge
270
Kann mir jemand den Grund erklären?

Convert.ToInt32 20/4 = 5-> int 5

Convert.ToInt32 20/4 -0.5 = 4.5 -> int 4

Convert.ToInt32 20/4 - 0.49999 = 4.50001-> int 5

1. Ich ging davon aus, die Nachkommastellen würden einfach abgeschnitten, ohne Rundungen überhaupt. Habe das von C++ so in Erinnerung, oder liege ich damit falsch?
2. Warum rundet er so...smart? .5 abrunden? Warum?

VS 2015 Community.
 
Zuletzt bearbeitet:
Präzisiere: Ab bis einschl. genau .5 wird abgerundet, alles darüber aufgerundet.

Runden = Auf nächste Int
Abschneiden = Alles hinter dem Komma abtrennen, egal, was das für eine Zahlenfolge war. (Also immer abrunden auf nächsten Int)
 
Hier die Math.Round Method Beschreibung von MSDN.

Aufrunden:
Code:
Math.Ceiling(0.5); --> 1

Abrunden:
Code:
Math.Floor(0.5); --> 0

Greets,
SystemException
 
Zuletzt bearbeitet: (Ergänzung)
Mit welcher Gegenimplementierung von C++ vergleichst du es? Ein einfacher cast (int)#.## ?
 
SystemExceptions Link erklärts ja schon.
In den Beispielen zu round, rundet C# und VBA .5 ab, C++ aber auf. (wundert mich auch, warum MS nen anderen Weg geht, dachte man rundet .5 immer auf?)

Gut, aber beim Thema geht ja ums convertInt, wenns schon beim round() unterschiede gibt, wundert es mich beim convertInt nicht, dass es da auch Unterschiede gibt.
Die Standardimplementierung versucht ja die gängigen Fälle abzudecken. Vermutlich hat man bei MS gedacht, die Rundung sei bei den allermeisten Konvertierungen erwünscht und daher wird dann eben gerundet.
Um bei C++ das Gleiche zu erreichen, muss man dann zu solchen Mitteln greifen, gibt aber vllt auch was Eleganteres heutzutage.
Von daher find ich das Feature ganz nett :)
 
Zuletzt bearbeitet:
Steht doch in der Dokumentation, wieso liest man die nicht?

Rückgabewert
Type: System.Int32
value, auf die nächste 32-Bit-Ganzzahl mit Vorzeichen gerundet.Wenn value genau zwischen zwei ganzen Zahlen liegt, wird die gerade Zahl zurückgegeben (d. h. 4,5 wird in 4 und 5,5 in 6 konvertiert).
 
Dein Problem scheint sich Banker's Rounding zu nennen. Schau dir die Antworten zu diesem StackOverflow Thread an.

Edit: Die Antwort von rille sollte ausreichend sein.

Greets,
SystemException
 
Zuletzt bearbeitet: (Ergänzung)
@Basinator: In der Doku zu der Funktion steht was sie tut und wie sie es tut. Auch das Rundungsverhalten ist erklärt. Wüßte nicht was es da zu erklären gebe.

Wenn man Standardrundungsverhalten haben will nimmt man Convert.ToInt32
Wenn man explizites Rundungsverhalten will, nimmt man Math.Round
Wenn man nicht rundern, sondern clippen will, macht man nen Cast
 
Code:
 Mit welcher Gegenimplementierung von C++ vergleichst du es? Ein einfacher cast (int)#.## ?
Ich meine, es wäre ein Cast gewesen bzw. die Variable einfach ein Int gewesen (zB int GanzZahl = 9/2 => 4).

@Basinator: In der Doku zu der Funktion steht was sie tut und wie sie es tut. Auch das Rundungsverhalten ist erklärt. Wüßte nicht was es da zu erklären gebe.
Dämliche Frage: Wie finde ich am Besten die Dokumentation? Annahme, es gehe um Convert und nicht um Round, so ist zumindest der Mouseover-Text bei mir ein anderer:
"Konvertiert den Wert der angegebenen Gleitkommazahl mit doppelter Genauigkeit in eine entsprechende 32-Bit-Ganzzahl mit Vorzeichen."
Dort finde ich keine entsprechende Beschreibung...

Wenn man nicht rundern, sondern clippen will, macht man nen Cast
Aber ist das bei mir nicht ein Cast? Dort tritt diese Problematik eben auf.
Code:
Console.WriteLine("Float -> Int ausgabe: " + Convert.ToInt32((2.6 * monatGauss - 0.2) - 0.49999999));


Es ging mir primär um Convert.ToInt32 und nicht um Math.Round.

Hatte da gestern und heute mich recht kaputtgesucht, man muss erstmal darauf kommen, wo der Fehler eigentlich ist und die gedachte Logik an sich korrekt war...
 
Basinator schrieb:
Dämliche Frage: Wie finde ich am Besten die Dokumentation?
Suchmaschine: System.Convert, ggf. mit nem msdn dran und schon bist du da. Oder versteh ich da was falsch?
Basinator schrieb:
"Konvertiert den Wert der angegebenen Gleitkommazahl mit doppelter Genauigkeit in eine entsprechende 32-Bit-Ganzzahl mit Vorzeichen."
Dort finde ich keine entsprechende Beschreibung...
Du siehst dir dort auch die Beschreibung der Funktion an, nicht die des Rückgabewerts.
https://msdn.microsoft.com/en-us/library/ffdk7eyz%28v=vs.110%29.aspx schrieb:
Converts the value of the specified double-precision floating-point number to an equivalent 32-bit signed integer.

Return Value
Type: System.Int32

value, rounded to the nearest 32-bit signed integer. If value is halfway between two whole numbers, the even number is returned; that is, 4.5 is converted to 4, and 5.5 is converted to 6.
Basinator schrieb:
Aber ist das bei mir nicht ein Cast? Dort tritt diese Problematik eben auf.
Code:
Console.WriteLine("Float -> Int ausgabe: " + Convert.ToInt32((2.6 * monatGauss - 0.2) - 0.49999999));
Das ist ein Cast:
Code:
(Int32)((2.6 * monatGauss - 0.2) - 0.49999999)
 
rille schrieb:
Nutzt du Visual Studio? Dann einfach Cursor drauf und F1 drücken.
Wow, coole Sache! Wird leider extra im Browser und nicht in VS selbst geöffnet.

Suchmaschine: System.Convert, ggf. mit nem msdn dran und schon bist du da. Oder versteh ich da was falsch?
Ging mir um eine komfortable Möglichkeit dazu. Ständig Google manuell bedienen ist halt umständlich...

Du siehst dir dort auch die Beschreibung der Funktion an, nicht die des Rückgabewerts.
...und manche Infos gibt es im MouseOver nicht.

Convert.ToX und Cast sind unterschiedlich? Okidoki!
 
Basinator schrieb:
Convert.ToX und Cast sind unterschiedlich? Okidoki!

Casten ist ja nicht konvertieren, sondern eher so ne Art Neuinterpretation ohne Berücksichtigung von Rechenregeln oder Ähnlichem.
Wenn du dem System sagst dass es 1.4 als Int interpretieren soll, dann wird da ne 1 draus. Weil ne Ganzzahl ja keine Kommastellen hat und ansonsten keine Regeln angewendet werden.
Wenn du dem System sagst dass du 1.4 in ein Int konvertieren willst, dann schaut es sich das an und legt Standardkonvertierungsregeln an. Und die hat Yuuri ja schon zitiert.

PS: Dass die Doku in einem Browserfenster geöffnet wird und nicht innerhalb von Visual Studio, müsste man eigentlich in den Optionen umstellen können. Weiß aber grad nicht wo.
 
Ging mir um eine komfortable Möglichkeit dazu. Ständig Google manuell bedienen ist halt umständlich...
Ich mach sowas mit Shortcuts:
Alt+Tab zum Browser
STRG+K sprung ich Suchfenster von Firefox
evtl STRG+Bild runter um die Suche von google auf stackoverflow umzuschalten
Frage tippen
Enter

So landet man ohne Maus sehr schnell beim Ergebnis ;)
 
Der Vollständigkeit halber die Implementierung von ToInt32:

Code:
public static int ToInt32(double value)
{
    if (value >= 0)
    {
        if (value < 2147483647.5)
        {
            int result = (int)value;
            double dif = value - result;
            if (dif > 0.5 || dif == 0.5 && (result & 1) != 0) result++;
            return result;
        }
    }
    else
    {
        if (value >= -2147483648.5)
        {
            int result = (int)value;
            double dif = value - result;
            if (dif < -0.5 || dif == -0.5 && (result & 1) != 0) result--;
            return result;
        }
    }
    throw new OverflowException(Environment.GetResourceString("Overflow_Int32"));
}
 
Zurück
Oben