Rundung Dezimalwert

8

Ich stehe vor dem Problem, den Dezimalwert in C # mit Math.Round(a, 2);

zu runden

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

    
Shivi 31.07.2012, 13:17
quelle

7 Antworten

8

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.

%Vor%     
CodesInChaos 31.07.2012 13:19
quelle
7

MSDN hat Folgendes zu diesem Verhalten zu sagen:

  

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.

%Vor%     
Icarus 31.07.2012 13:27
quelle
4

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.

    
Guffa 31.07.2012 13:28
quelle
2

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.

    
user9371102 31.07.2012 13:23
quelle
1
%Vor%

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

%Vor%

Ссылка

    
JP Hellemons 31.07.2012 13:20
quelle
1

Es liegt daran, dass Sie ein Doppel und nicht eine Dezimalzahl runden:

%Vor%

Dezimal und Doppel sind sehr unterschiedlich

    
Yngve B-Nilsen 31.07.2012 13:28
quelle
0

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%     
M Afifi 31.07.2012 13:55
quelle

Tags und Links