Benutzer:Speifensender/Ganzzahlrundung

aus Wikipedia, der freien Enzyklopädie
Zur Navigation springen Zur Suche springen

Runden auf Ganzzahlen in C# (C# >= 2.0)[Bearbeiten | Quelltext bearbeiten]

Siehe auch Rundung und en:Rounding.

using System;
using System.Collections.Generic;

namespace DummyNamespace
{
	public static class Mathematics
	{
		/// <summary>
		/// Die Strategie, wie sich der Dezimalanteil einer Zahl auf das Rundungsergebnis auswirkt.
		/// Siehe auch http://en.wikipedia.org/wiki/Rounding.
		/// </summary>
		public enum RoundingPolicy
		{
			/// <summary>
			/// Das Ergebnis ist der Ganzzahlteil ohne Dezimalstellen ("Truncate").
			/// </summary>
			TowardsZero,

			/// <summary>
			/// Das Ergebnis ist die größte Ganzzahl, die nicht größer als der Eingabewert ist ("Floor").
			/// </summary>
			Down,

			/// <summary>
			/// Das Ergebnis ist die kleinste Ganzzahl, die nicht kleiner als der Eingabewert ist ("Ceiling").
			/// </summary>
			Up,

			/// <summary>
			/// Das Ergebnis ist der Eingabewert, falls der Eingabewert keine Dezimalstellen hat.
			/// Andernfalls ist das Ergebnis die Ganzzahl,
			/// die am nächsten zu Null liegt, wobei der Eingabewert zwischen Null und dem Ergebnis liegen muss.
			/// </summary>
			AwayFromZero,

			/// <summary>
			/// Das Ergebnis ist die Ganzzahl, die am nächsten zum Eingabewert liegt.
			/// Wenn der Dezimalteil des Eingabewertes gleich 1/2 ist,
			/// ist das Ergebnis der Eingabewert plus 1/2 für positive Eingabewerte,
			/// bzw. der Eingabewert minus 1/2 für negative Eingabewerte.
			/// </summary>
			ToNearest_HalfAwayFromZero,

			/// <summary>
			/// Das Ergebnis ist die Ganzzahl, die am nächsten zum Eingabewert liegt.
			/// Wenn der Dezimalteil des Eingabewertes gleich 1/2 ist,
			/// ist das Ergebnis die Gerade Zahl, die am nächsten zum Eingabewert liegt.
			/// </summary>
			ToNearest_HalfToEven,

			/// <summary>
			/// Das Ergebnis ist die Ganzzahl, die am nächsten zum Eingabewert liegt.
			/// Wenn der Dezimalteil des Eingabewertes gleich 1/2 ist,
			/// ist das Ergebnis der Eingabewert plus 1/2.
			/// </summary>
			ToNearest_HalfUp,
		}

		/// <summary>
		/// Ermittelt den ganzzahligen Teil einer Zahl für eine bestimmte Rundungs-Strategie (<see cref="RoundingPolicy" />).
		/// </summary>
		/// <param name="value">Die Eingabezahl.</param>
		/// <param name="roundingPolicy">Die Rundungs-Strategie.</param>
		/// <returns>Der ganzzahlige Teil der Eingabezahl gemäß der Rundungs-Strategie.</returns>
		public static Decimal GetRoundedInteger(Decimal value, RoundingPolicy roundingPolicy)
		{
			Decimal result;

			switch (roundingPolicy)
			{
				case RoundingPolicy.Down:
					{
						result = Math.Floor(value);
					}
					break;
				case RoundingPolicy.Up:
					{
						result = Math.Ceiling(value);
					}
					break;
				case RoundingPolicy.AwayFromZero:
					{
						result = (
							value >= 0 ?
							Math.Ceiling(value) :
							Math.Floor(value)
						);
					}
					break;
				case RoundingPolicy.TowardsZero:
					{
						result = Math.Truncate(value);
					}
					break;
				case RoundingPolicy.ToNearest_HalfAwayFromZero:
					{
						result = Math.Round(value, MidpointRounding.AwayFromZero);
					}
					break;
				case RoundingPolicy.ToNearest_HalfToEven:
					{
						result = Math.Round(value, MidpointRounding.ToEven);
					}
					break;
				case RoundingPolicy.ToNearest_HalfUp:
					{
						result = (
							IsHalf(value) ?
							Math.Ceiling(value) :
							Math.Round(value)
						);
					}
					break;
				default:
					throw new NotImplementedException(roundingPolicy.ToString());
			}

			return result;
		}

		/// <summary>
		/// Ermittelt, ob der vorzeichenlose Dezimalteil einer Zahl 1/2 ist.
		/// </summary>
		/// <param name="value">Die Eingabezahl.</param>
		/// <returns>True, wenn der vorzeichenlose Dezimalteil einer Zahl 1/2 ist. Sonst false.</returns>
		public static bool IsHalf(Decimal value)
		{
			Decimal fraction = Fraction(value);
			bool result = (fraction == new Decimal(0.5));

			return result;
		}

		/// <summary>
		/// Ermittelt den vorzeichenlosen Dezimalteil einer Zahl.
		/// </summary>
		/// <param name="value">Die Eingabezahl.</param>
		/// <returns>Der vorzeichenlose Dezimalteil.</returns>
		public static Decimal Fraction(Decimal value)
		{
			Decimal result = Math.Abs(value - Math.Truncate(value));

			return result;
		}
	}

	public class RoundedIntegerTester
	{
		static void Main(string[] args)
		{
			List<Decimal> values = new List<decimal>();
			{
				//Die 0 einfügen
				values.Add(0m);

				//Beträge der zu testenden Zahlen (außer 0)
				{
					//definieren...
					List<Decimal> absoluteValues = new List<Decimal>(
						new Decimal[] {
							    0.01m, 0.5m, 0.99m, 
							1m, 1.01m, 1.5m, 1.99m, 
							2m, 2.01m, 2.5m, 2.99m, 
							3m, 3.01m, 3.5m, 3.99m, 
							4m, 4.01m
						}
					);

					//... und einfügen
					foreach (Decimal absoluteValue in absoluteValues)
					{
						values.Add(+absoluteValue);
						values.Add(-absoluteValue);
					}
				}
			}
			values.Sort(); //zu testende Zahlen sortieren

			//alle möglichen RoundingPolicies holen
			Array roundingPolicies = Enum.GetValues(typeof(Mathematics.RoundingPolicy));

			//LOG-Datei erstellen
			using (System.IO.StreamWriter writer = new System.IO.StreamWriter(@"c:\RoundedIntegerTester.log"))
			{
				//Trennzeichen
				string separator = ";";

				//Kopfzeile
				{
					string line = "x" + separator;

					foreach (Mathematics.RoundingPolicy roundingPolicy in roundingPolicies)
					{
						line += roundingPolicy + separator;
					}

					writer.WriteLine(line);
				}

				//Zahlen testen
				{
					foreach (Decimal value in values)
					{
						string line = value + separator;

						foreach (Mathematics.RoundingPolicy roundingPolicy in roundingPolicies)
						{
							//Ergebnis holen
							Decimal y = Mathematics.GetRoundedInteger(value, roundingPolicy);

							line += y + separator;
						}

						writer.WriteLine(line);
					}
				}
			}

			//Datei für MediaWiki-Tabelle erstellen
			using (System.IO.StreamWriter writer = new System.IO.StreamWriter(@"c:\RoundedIntegerTester.MediaWikiTable"))
			{
				//Tabelle
				writer.WriteLine(
					"{|" +
					" class=" + "\"" + "wikitable" + "\""
				);
				{
					//Kopfzeile
					{
						writer.WriteLine("! " + "x");

						foreach (Mathematics.RoundingPolicy roundingPolicy in roundingPolicies)
						{
							writer.WriteLine("! " + roundingPolicy);
						}
					}

					//Zahlen testen
					{
						foreach (Decimal value in values)
						{
							writer.WriteLine("|" + "-");
							writer.WriteLine("| " + value);

							foreach (Mathematics.RoundingPolicy roundingPolicy in roundingPolicies)
							{
								//Ergebnis holen
								Decimal y = Mathematics.GetRoundedInteger(value, roundingPolicy);

								writer.WriteLine("| " + y);
							}
						}
					}
				}

				writer.WriteLine("|}");
			}
		}
	}
}


Das Ergebnis der Ganzzahlrundung sollte folgende Werte haben:

x Down Up AwayFromZero TowardsZero ToNearest_HalfAwayFromZero ToNearest_HalfToEven ToNearest_HalfUp
-4,01 -5 -4 -5 -4 -4 -4 -4
-4 -4 -4 -4 -4 -4 -4 -4
-3,99 -4 -3 -4 -3 -4 -4 -4
-3,5 -4 -3 -4 -3 -4 -4 -3
-3,01 -4 -3 -4 -3 -3 -3 -3
-3 -3 -3 -3 -3 -3 -3 -3
-2,99 -3 -2 -3 -2 -3 -3 -3
-2,5 -3 -2 -3 -2 -3 -2 -2
-2,01 -3 -2 -3 -2 -2 -2 -2
-2 -2 -2 -2 -2 -2 -2 -2
-1,99 -2 -1 -2 -1 -2 -2 -2
-1,5 -2 -1 -2 -1 -2 -2 -1
-1,01 -2 -1 -2 -1 -1 -1 -1
-1 -1 -1 -1 -1 -1 -1 -1
-0,99 -1 0 -1 0 -1 -1 -1
-0,5 -1 0 -1 0 -1 0 0
-0,01 -1 0 -1 0 0 0 0
0 0 0 0 0 0 0 0
0,01 0 1 1 0 0 0 0
0,5 0 1 1 0 1 0 1
0,99 0 1 1 0 1 1 1
1 1 1 1 1 1 1 1
1,01 1 2 2 1 1 1 1
1,5 1 2 2 1 2 2 2
1,99 1 2 2 1 2 2 2
2 2 2 2 2 2 2 2
2,01 2 3 3 2 2 2 2
2,5 2 3 3 2 3 2 3
2,99 2 3 3 2 3 3 3
3 3 3 3 3 3 3 3
3,01 3 4 4 3 3 3 3
3,5 3 4 4 3 4 4 4
3,99 3 4 4 3 4 4 4
4 4 4 4 4 4 4 4
4,01 4 5 5 4 4 4 4