Feedback

C# - Kaufmännisches Runden in Decimal

Veröffentlicht von am 06.11.2006
(4 Bewertungen)
In .NET 1.1 ist, wie in einigen anderen Sprachen auch, das Runden mit Math.Round auf Grund von möglichen Verzerrungen bei Statistiken (siehe Wikipedia, siehe IEEE 754), nicht für ein kaufmännisches Runden geeignet. Aus 3,65 wird (bei Runden auf eine Ziffer) 3,6 da zur nächsten geraden Stelle gerundet wird. Diese statische Methode umgeht diese Besonderheit und ermöglicht ein kaufmännisches Runden.
GFU-Schulungen  [Anzeige]

C# Grundlagen

Die Schulung vermittelt Ihnen die Grundlagen von C# in der Arbeit mit Datentypen sowie bei Klassenbibliotheken. Sie lernen, mit Variablen umzugehen und deren verschiedene Formen zu konvertieren. 

XML und .NET Überblick

Um auf dem neuesten Wissensstand zu sein, sollten Sie unser aktuelles ASP .NET Komplett Seminar belegen.
Nach dem Seminar kennen Sie die wichtigsten Strömungen in der Software-Technologie

/// <summary>
/// Rundet kaufmännisch auf die Anzahl der übergebenen Nachkommastellen
///
/// Achtung: Seit .NET 2.0 gibt es folgende Überladung die dieses Snippet hinfällig machen: Math.Round(3.65m,1,MidpointRounding.AwayFromZero)
/// </summary>
/// <param name="value">Zu rundender Wert</param>
/// <param name="dec">Anzahl der Nachkommastellen</param>
/// <returns>Gerundeter Wert</returns>
public static decimal CommercialRound(decimal value, int dec)
{
	// um die Anzahl der Dezimalstellen nach links verschieben
	decimal x = value * Convert.ToDecimal(Math.Pow(10, dec));

	// Dezimalstellen abtrennen
	decimal y = Math.Floor(x);

	// ist die Differenz größer oder gleich 0.5 soll aufgerundet werden
	if ((x-y) >= 0.5m) y++;

	// um die Anzahl der Dezimalstellen nach rechts verschieben 
	return y / Convert.ToDecimal(Math.Pow(10, dec));
}
Abgelegt unter Round, kaufmännisch, Runden, Decimal, C#, Snippet.

4 Kommentare zum Snippet

BlackDragon schrieb am 07.11.2006:
komisch bei mir macht er das richtig
3,6 = Math.Round(Convert.ToDecimal("3,64"),1,MidpointRounding.AwayFromZero));
3,7 = Math.Round(Convert.ToDecimal("3,65"),1,MidpointRounding.AwayFromZero));
Yellow schrieb am 07.11.2006:
Ja, BlackDragon... da hast du in der Tat recht. Diese Überladung ist seit dem Framework 2.0 neu hinzugekommen. Insofern ist mein Snippet nur für .NET 1.1 zu empfehlen. Wieder etwas gelernt, danke für den Hinweis ;o).
Marvin schrieb am 10.02.2007:
Der Code funktioniert für negative Zahlen nicht zuverlässig.
So liefert bspw. CommercialRound(-1.55m, 1) als Ergebnis -1.5 und nicht -1.6!
Oder ist das Absicht?

Hier meine Implementierung:


public static decimal RoundNumber( decimal number, int decimals )
{
if ( decimals < 0 || decimals > 8 )
throw new ArgumentOutOfRangeException( "decimals must be between 0 and 8", "decimals" );

//Komma verschieben
int shiftFactor = (int)Math.Pow( 10, decimals );
decimal tmp = number * shiftFactor;

//Runden: 0.5 addieren/subtrahieren und dann Nachkommastellen abschneiden
decimal diff = ( tmp >= 0 ? 0.5m : -0.5m );
tmp = (long)( tmp + diff );

//Komma wieder verschieben
return ( tmp / shiftFactor );
}
Yellow schrieb am 14.02.2007:
Hallo Marvin,

danke für den Hinweis. Du hast natürlich recht. Die kaufmännische Rundung muss bei negativen Zahlen abrundnen...
 

Logge dich ein, um hier zu kommentieren!