Wenn Sie mit 10 Fingern abzählen, wie Menschen es tun, Sie haben keine Probleme den Dezimalwert exprimierenden 8.075 genau:
8.075 = 8 x 10^1 + 0 x 10^0 + 7 x 10^-1 + 5 x 10^-2
Aber Computer mit zwei Fingern abzählen, sie brauchen diesen Wert in auszudrücken Potenzen von 2:
8.075 = 1 x 2^3 + 0 x 2^2 + 0 x 2^1 + 0 x 2^0 + 0 x 2^-1 + 0 x 2^-2 + 0 x 2^-3 +
1 x 2^-4 + 0 x 2^-5 + 0 x 2^-6 + 1 x 2^-7 + 1 x 2^-8 + 0 x 2^-9 + 0 x 2^-10 +
1 x 2^-11 + ...
gab ich die Bedingungen mit dem Finger krampf eingeben, aber der Punkt ist, dass, egal wie viele Potenzen von 2 Sie hinzufügen, werden Sie nie genau 8.075m bekommen. Ein ähnliches Problem, wie Menschen niemals das Ergebnis von 10/3 genau schreiben können, hat eine unendliche Anzahl von Ziffern in der Fraktion. Sie können das Ergebnis dieses Ausdrucks nur dann genau schreiben, wenn Sie mit 6 Fingern zählen.
Ein Prozessor natürlich nicht über genügend Speicher eine unendliche Anzahl von Bits speichern einen Wert darzustellen. So müssen sie gestutzt die Ziffernfolge, einen Wert vom Typ Doppel kann 53 Bits speichern.
Als Ergebnis der Dezimalwert 8.075 gerundet wird, wenn es in dem Prozessor gespeichert ist. Die Folge von 53 Bits, zurück in Dezimal konvertiert, ist der Wert ~ 8.074999999999999289. Was dann wie erwartet von Ihrem Code auf 8,07 gerundet wird.
Wenn Sie 10 Finger Mathe Ergebnisse wollen, müssen Sie einen Datentyp verwenden, die Zahlen in der Basis speichert 10. Das ist der System.Decimal Typ in .NET ist. Fix:
decimal result = Math.Round(8.075m, 2, MidpointRounding.AwayFromZero)
Beachten Sie die Verwendung des Buchstaben m in den 8.075m wörtlichen im Snippet, ein wörtlichen vom Typ dezimal. Wählt die Math.Round() - Überladung aus, die mit 10 Fingern zählt, zuvor haben Sie die Überladung verwendet, die System.Double, die 2-Finger-Version, verwendet.
Sie beachten Sie, dass ein erheblicher Nachteil ist mit System.Decimal zu berechnen, ist es langsam. Viel, viel langsamer als mit System.Double, einem Werttyp, der direkt vom Prozessor unterstützt wird. Dezimalmathematik wird in Software ausgeführt und ist nicht hardwarebeschleunigt.
Ich bin sehr zweifelhaft .net solche Fehler haben würde, wenn es das ist, was passiert ist, dann wurde ich bin sicher, dass es auf diese Weise aus einem Grunde implementiert. –
Sie können einen Dezimaltyp verwenden, da sie präziser sind: 'Math.Round (8.075m, 2, MidpointRounding.AwayFromZero) ' –
Wir brauchen Jon Skeet hier – VladL