Der Dokumentation zufolge verwendet die decimal.Round
Methode einen Round-to-Even-Algorithmus, der für die meisten Anwendungen nicht üblich ist. Daher schreibe ich immer eine benutzerdefinierte Funktion, um den natürlicheren Round-Half-Up-Algorithmus auszuführen:
public static decimal RoundHalfUp(this decimal d, int decimals)
{
if (decimals < 0)
{
throw new ArgumentException("The decimals must be non-negative",
"decimals");
}
decimal multiplier = (decimal)Math.Pow(10, decimals);
decimal number = d * multiplier;
if (decimal.Truncate(number) < number)
{
number += 0.5m;
}
return decimal.Round(number) / multiplier;
}
Kennt jemand den Grund für diese Entscheidung zum Framework-Design?
Gibt es eine integrierte Implementierung des Round-Half-Up-Algorithmus in das Framework? Oder vielleicht eine nicht verwaltete Windows-API?
Es könnte für Anfänger irreführend sein, einfach zu schreiben decimal.Round(2.5m, 0)
, 3 als Ergebnis zu erwarten, aber stattdessen 2 zu bekommen.
Antworten:
Wahrscheinlich, weil es ein besserer Algorithmus ist. Im Verlauf vieler durchgeführter Rundungen werden Sie herausfinden, dass alle .5er gleich hoch und runter runden. Dies gibt bessere Schätzungen der tatsächlichen Ergebnisse, wenn Sie beispielsweise eine Reihe gerundeter Zahlen hinzufügen. Ich würde sagen, obwohl es nicht das ist, was manche erwarten, ist es wahrscheinlich das Richtige.
quelle
Die anderen Antworten mit Gründen, warum der Banker-Algorithmus (auch bekannt als Round Half to Even ) eine gute Wahl ist, sind ganz richtig. Es leidet nicht so sehr unter einer negativen oder positiven Verzerrung wie die runde Hälfte von der Nullmethode über die meisten vernünftigen Verteilungen.
Die Frage war jedoch, warum .NET die tatsächliche Rundung von Banker als Standard verwendet - und die Antwort lautet, dass Microsoft den IEEE 754- Standard befolgt hat . Dies wird auch in MSDN für Math.Round unter Bemerkungen erwähnt.
Beachten Sie auch, dass .NET die von IEEE angegebene alternative Methode unterstützt, indem es die
MidpointRounding
Aufzählung bereitstellt . Sie hätten natürlich mehr Alternativen zur Lösung von Bindungen bieten können , aber sie entscheiden sich dafür, nur den IEEE-Standard zu erfüllen.quelle
Obwohl ich die Frage "Warum haben die Designer von Microsoft dies als Standard gewählt?" Nicht beantworten kann, möchte ich nur darauf hinweisen, dass eine zusätzliche Funktion nicht erforderlich ist.
Math.Round
Mit dieser Option können Sie Folgendes angebenMidpointRounding
:quelle
Dezimalstellen werden meistens für Geld verwendet ; Bankrundungen sind bei der Arbeit mit Geld üblich . Oder könnte man sagen.
Bankrunden haben den Vorteil, dass Sie im Durchschnitt das gleiche Ergebnis erzielen, wenn Sie:
Das Runden vor dem Addieren sparte in den Tagen vor dem Computer viel Arbeit.
(In Großbritannien, als wir dezimal gingen, beschäftigten sich Banken nicht mit halben Pence, aber viele Jahre lang gab es immer noch eine halbe Pence-Münze und im Laden endeten die Preise oft mit halben Pence - also viele Rundungen)
quelle
Decmial
s, ja. Dezimalstellen, nein. Für die Nachwelt stimme ich dem ursprünglichen Gefühl hier zu.Verwenden Sie eine andere Überladung der Round-Funktion wie folgt:
Es wird 3 ausgegeben . Und wenn Sie verwenden
Sie werden Bankrundung bekommen.
quelle