Ich stehe vor dem Problem, den Dezimalwert in C # mit Math.Round(a, 2);
Wenn ich 1.275 um zwei Dezimalpunkte runder mache, ist das Ergebnis 1.27. Wenn ich dasselbe für 1.375 mache, ist das Ergebnis 1.38.
Warum wird nicht zwischen 1.275 und 1.28 gerundet?
Danke
Ich kann Ihr Problem nicht reproduzieren:
%Vor% Ich vermute, dass Ihr Anspruch, dass Sie einen decimal
-Wert verwenden, falsch ist und dass Sie stattdessen double
value verwenden. double
kann nicht viele Dezimalwerte genau darstellen, also wenn du 1.275
schreibst, ist es tatsächlich 1.27499 ... 1.375
ist einer der wenigen darstellbaren onces, also ist es tatsächlich 1.375
.
Wenn sich Ihr Code um eine genaue Dezimaldarstellung kümmert, zum Beispiel wenn Sie an Geld arbeiten, müssen Sie decimal
und nicht binäres Gleitkomma wie double
oder float
verwenden.
Aber selbst wenn Sie eine Dezimaldarstellung verwenden, verhält sich das Runden für viele Benutzer unerwartet:
%Vor% Standardmäßig verwendet Math.Round
MidpointRounding.ToEven
, auch bekannt als Bankrunde . Dadurch wird vermieden, dass eine Verzerrung immer bei .5
aufgerundet wird.
Sie können eine Überladung von Round
verwenden, die einen Rundungsmodus benötigt, und sie auf AwayFromZero
setzen, um das erwartete Verhalten zu erhalten.
MSDN hat Folgendes zu diesem Verhalten zu sagen:
%Vor%Hinweise für Anrufer
Wegen des Genauigkeitsverlustes, der daraus resultieren kann Darstellen von Dezimalwerten als Fließkommazahlen oder Ausführen arithmetische Operationen auf Fließkommawerten, in einigen Fällen die Die Round-Methode (Double, Int32) scheint die Mittelpunktswerte nicht zu runden der nächste gerade Wert in der Dezimalstelle der Ziffern. Das ist im folgenden Beispiel dargestellt, wobei 2.135 auf 2.13 gerundet wird statt 2.14. Dies geschieht, weil intern die Methode multipliziert wird Wert durch 10 Ziffern und die Multiplikationsoperation in diesem Fall leidet unter einem Verlust der Präzision.
Wenn Sie einen Decimal
Wert haben, wird 1.275
korrekt auf 1.28
gerundet.
Wenn Sie einen Double
-Wert haben, verhält es sich nicht gleich, weil der Wert 1.275
nicht genau dargestellt werden kann. Wenn Sie den double
-Wert 1.275
verwenden, ist er tatsächlich etwas kleiner als der genaue Wert 1.275
, also etwa 1.2749999999999999
.
Wenn dieser Wert gerundet wird, wird er nicht genau zwischen 1.27
und 1.28
, sondern etwas näher an 1.27
liegen, also wird er abgerundet und nicht abgerundet.
Dies ist ein schrecklicher Hack, aber versuchen Sie es mit Format. Es verwendet unerklärlicherweise die Rundung, an die wir alle gewöhnt sind.
%Vor%(ODER)
Nur zur Information: Ab .Net Version 2.0 ist es möglich zu definieren, wie die "0,5 Fälle" mit einem Parameter MidpointRounding gerundet werden. Es kann ToEven oder AwayFromZero sein. Also würde "Standard" Runden so aussehen:
%Vor%Dies würde den Wert "2.3" zurückgeben.
wie in den Kommentaren dieses Blogs vorgeschlagen: Ссылка
Welche Version des .Net-Frameworks verwenden Sie? Wenn es über 1.1 liegt, können Sie das midpointrounding und setze es auf AwayFromZero
Es liegt daran, dass Sie ein Doppel und nicht eine Dezimalzahl runden:
%Vor%Dezimal und Doppel sind sehr unterschiedlich
Erwartetes Verhalten gemäß der Dokumentation.
Wenn Dezimalzahlen beispielsweise gleich 1 sind, sind beide 2,15 und 2,15000 auf 2,2 gerundet, weil .05 und .05000 beide in der Mitte zwischen .1 und .2 und .1 ist ungerade. Wenn Dezimalzahlen gleich 1, 2,05 und 2.05000 werden beide auf 2.0 gerundet, da .05 und .05000 beide in der Mitte zwischen .0 und .1 liegen und .0 gerade ist. Das Verhalten von diesem Methode folgt IEEE Standard 754, Abschnitt 4. Diese Art der Rundung ist manchmal als Rundung zum nächsten oder Bankrunden bezeichnet. Es minimiert Rundungsfehler, die sich aus der konsistenten Rundung von a ergeben Mittelpunktswert in einer einzigen Richtung. Um den Typ von zu steuern Runden, die von der Round (Decimal, Int32) -Methode verwendet werden, rufen Sie die Decimal.Round (Dezimal, Int32, MidpointRounding) Überladung.
Von Math.Round (dezimal, int) . Probieren Sie
aus %Vor%Tags und Links c# floating-point