namespace Fraction
{
[global::System.Serializable]
public class DenominatorIsZeroException : Exception
{
public DenominatorIsZeroException() { }
public DenominatorIsZeroException(string message) : base(message) { }
public DenominatorIsZeroException(string message, Exception inner) : base(message, inner) { }
protected DenominatorIsZeroException(
System.Runtime.Serialization.SerializationInfo info,
System.Runtime.Serialization.StreamingContext context)
: base(info, context) { }
}
public sealed class Fraction :IComparable<Fraction>
{
//Zähler
public long Numerator { get; private set; }
//Nenner
public long Denominator { get; private set; }
public static readonly Fraction Empty = new Fraction(0,1);
#region ctors
/// <summary>
/// Erzeugt einen Bruch der 1/1 darstellt.
/// </summary>
public Fraction()
{
this.Denominator = 1;
this.Numerator = 1;
}
/// <summary>
/// Konstruktor zum erzeugen von einem benutzerdefinierten Bruch.
/// </summary>
/// <param name="numerator">Der Zähler des Bruches</param>
/// <param name="denominator">Der Nenner des Bruches</param>
public Fraction(long numerator,long denominator)
{
this.InitializeComponent(numerator, denominator);
}
/// <summary>
/// Erzeugt eine Fractionobjekt aus einer Dezimalzahl.
/// </summary>
/// <param name="frac">Die dezimalzahl die zu einem Bruch gemacht werden soll.</param>
public Fraction(double frac)
{
this.InitializeComponent(frac);
}
#endregion
#region öffentliche Methoden
/// <summary>
/// Addiert das aktuelle Bruchobjekt mit einem anderen Bruchobjekt.
/// </summary>
/// <param name="frac">Das zu addierende Bruchobjekt</param>
/// <returns>Gibt die Summe der beiden Bruchobjekte zurück.</returns>
public Fraction Add(Fraction frac)
{
if (frac == null)
throw new ArgumentNullException("frac", "Der Bruch darf nicht null sein");
Fraction newFraction = new Fraction();
newFraction.Denominator = this.Denominator * frac.Denominator;
newFraction.Numerator = (this.Numerator * frac.Denominator) + (frac.Numerator * this.Denominator);
newFraction.InitializeComponent(newFraction.Numerator, newFraction.Denominator);
return newFraction;
}
/// <summary>
/// Addition mit einer Ganz Zahl.
/// </summary>
/// <param name="number">Die zu addierende Zahl.</param>
/// <returns>Ein neues Bruchobjekt basierend auf der Summe des alten und der übergebenen Ganzzahl.</returns>
public Fraction Add(long number)
{
Fraction newFraction = new Fraction(number, 1);
return this.Add(newFraction);
}
public Fraction Add(double number)
{
Fraction newFraction = new Fraction(number);
return this.Add(newFraction);
}
/// <summary>
/// Subtrahiert das aktuelle Bruchobjekt mit einem anderen Bruchobjekt.
/// </summary>
/// <param name="frac">Das zu subtrahierende Bruchobjekt.</param>
/// <returns>Die Differenz der beiden Bruchobjekte.</returns>
public Fraction Substract(Fraction frac)
{
if (frac == null)
throw new ArgumentNullException("frac", "Der Bruch darf nicht null sein");
Fraction newFraction = new Fraction();
newFraction.Denominator = this.Denominator * frac.Denominator;
newFraction.Numerator = (this.Numerator * frac.Denominator) - (frac.Numerator * this.Denominator);
newFraction.InitializeComponent(newFraction.Numerator, newFraction.Denominator);
return newFraction;
}
public Fraction Substract(long number)
{
Fraction newFraction = new Fraction(number, 1);
return this.Substract(newFraction);
}
public Fraction Substract(double number)
{
return this.Substract(new Fraction(number));
}
/// <summary>
/// Multipliziert das aktuelle Bruchobjekt mit einem anderen Bruchobjekt.
/// </summary>
/// <param name="frac">Das zu multiplizierende Bruchobjekt.</param>
/// <returns>Das Produkt der beiden Bruchobjekte.</returns>
public Fraction Multiplie(Fraction frac)
{
if (frac == null)
throw new ArgumentNullException("frac", "Der Bruch darf nicht null sein");
return new Fraction(this.Numerator * frac.Numerator, this.Denominator * frac.Denominator);
}
public Fraction Multiplie(long number)
{
Fraction newFraction = new Fraction(number, 1);
return this.Multiplie(newFraction);
}
public Fraction Multiplie(double number)
{
return this.Multiplie(new Fraction(number));
}
/// <summary>
/// Dividiert das aktuelle Bruchobjekt mit einem anderen Bruchobjekt.
/// </summary>
/// <param name="frac">Das zu dividierende Bruchobjekt.</param>
/// <returns>Der Quotient der beiden Bruchobjekte.</returns>
public Fraction Divide(Fraction frac)
{
if (frac == null)
throw new ArgumentNullException("frac", "Der Bruch darf nicht null sein");
return new Fraction(this.Numerator * frac.Denominator, this.Denominator * frac.Numerator);
}
public Fraction Divide(long number)
{
Fraction frac = new Fraction(number, 1);
return this.Divide(frac);
}
public Fraction Divide(double number)
{
return this.Divide(new Fraction(number));
}
public double ToDouble()
{
return (Convert.ToDouble(this.Numerator) / Convert.ToDouble(this.Denominator));
}
#endregion
#region private Methoden
private void InitializeComponent(long numerator, long denominator)
{
if (denominator == 0)
throw new DenominatorIsZeroException("Der Nenner darf nicht '0' sein");
//den größten gemeinsamen teiler berechnen
long greatestCommonDivider = this.GreatestCommonDivider(numerator,denominator);
this.Denominator = denominator / greatestCommonDivider;
this.Numerator = numerator / greatestCommonDivider;
}
private void InitializeComponent(double number)
{
double tempNumber = number;
int counter = 0;
//solange wie es keine Ganzahl ist, multiplizieren wir die dezimalzahl mit ihrer basis also 10
while (tempNumber % 1 != 0)
{
tempNumber *= 10;
//erhöhen gleichzeitig einen counter wie oft wir das gemacht haben
//dadurch merken wir uns die nachkommastellen
counter++;
}
this.Numerator = (long)tempNumber;
//wir potenzieren unsere nachkommastellen mit 10 um eine relation zwischen zähler und nenner zu erschaffen
//bei 0.5 -> 5/(10^1)
this.Denominator = (long)Math.Pow(10, counter);
this.InitializeComponent(this.Numerator, this.Denominator);
}
private long GreatestCommonDivider(long numerator, long denominator)
{
//zähler und nenner auf absolute ebene bringen
long tempNumerator = Math.Abs(numerator);
long tempDenominator = Math.Abs(denominator);
if (tempNumerator == 0)
return tempDenominator;
while (tempDenominator != 0)
{
if (tempNumerator > tempDenominator)
tempNumerator -= tempDenominator;
else
tempDenominator -= tempNumerator;
}
return tempNumerator;
}
#endregion
#region ToString()
/// <summary>
/// Erstellt eine Standardausgabe ála Zähler/Nenner.
/// </summary>
/// <returns>Gibt den Bruch in Standardformatierung zurück.</returns>
public override string ToString()
{
return this.Numerator.ToString() + "/" + this.Denominator.ToString();
}
/// <summary>
/// Erzeugt eine Benutzerdefinierte Ausgabe
/// </summary>
/// <param name="format">Das Benutzerdefinierte Format. Beispiele sind "-","/","d".</param>
/// <returns></returns>
public string ToString(string format)
{
if(format == null)
throw new ArgumentNullException("format","Es muss ein Format angegeben werden");
switch (format)
{
case "-":
StringBuilder sb = new StringBuilder();
//zaehler einfügen
sb.AppendLine(this.Numerator.ToString());
//größtes element bestimmen über die string.Length eigenschaft
long maxCountOfFractionBar = Math.Max(this.Denominator.ToString().Length, this.Numerator.ToString().Length);
//genauso viele Striche einfügen
for (long i = 0; i < maxCountOfFractionBar; i++)
sb.Append("-");
sb.AppendLine();
//und den Nenner einfügen
sb.AppendLine(this.Denominator.ToString());
return sb.ToString();
case "/":
return this.ToString();
default:
return this.ToString();
}
}
#endregion
#region IComparable<Fraction>
public int CompareTo(Fraction other)
{
return this.ToDouble().CompareTo(other.ToDouble());
}
#endregion
#region Operatoren
#region explicite und implicte Operatoren
public static implicit operator Fraction(long number)
{
return new Fraction(number);
}
public static implicit operator Fraction(double number)
{
return new Fraction(number);
}
#endregion
#region Binärer Operator+
public static Fraction operator +(Fraction frac, Fraction otherFrac)
{
if (frac == null)
throw new ArgumentNullException("frac", "Bruchobjekt darf nicht 'null' sein.");
return frac.Add(otherFrac);
}
public static Fraction operator +(Fraction frac, long number)
{
if (frac == null)
throw new ArgumentNullException("frac", "Bruchobjekt darf nicht 'null' sein.");
return frac.Add(number);
}
public static Fraction operator +(Fraction frac, double number)
{
if (frac == null)
throw new ArgumentNullException("frac", "Bruchobjekt darf nicht 'null' sein.");
return frac.Add(number);
}
#endregion
#region Binärer Operator -
public static Fraction operator -(Fraction frac, Fraction otherFrac)
{
if (frac == null)
throw new ArgumentNullException("frac", "Bruchobjekt darf nicht 'null' sein.");
return frac.Substract(otherFrac);
}
public static Fraction operator-(Fraction frac,long number)
{
if (frac == null)
throw new ArgumentNullException("frac", "Bruchobjekt darf nicht 'null' sein.");
return frac.Substract(number);
}
public static Fraction operator-(Fraction frac,double number)
{
if (frac == null)
throw new ArgumentNullException("frac", "Bruchobjekt darf nicht 'null' sein.");
return frac.Substract(number);
}
#endregion
#region Binärer Operator *
public static Fraction operator *(Fraction frac, Fraction otherFrac)
{
if (frac == null)
throw new ArgumentNullException("frac", "Bruchobjekt darf nicht 'null' sein.");
return frac.Multiplie(otherFrac);
}
public static Fraction operator *(Fraction frac, long number)
{
if (frac == null)
throw new ArgumentNullException("frac", "Bruchobjekt darf nicht 'null' sein.");
return frac.Multiplie(number);
}
public static Fraction operator *(Fraction frac, double number)
{
if (frac == null)
throw new ArgumentNullException("frac", "Bruchobjekt darf nicht 'null' sein.");
return frac.Multiplie(number);
}
#endregion
#region Binärer Operator /
public static Fraction operator /(Fraction frac, Fraction otherFrac)
{
if (frac == null)
throw new ArgumentNullException("frac", "Bruchobjekt darf nicht 'null' sein.");
return frac.Divide(otherFrac);
}
public static Fraction operator /(Fraction frac, long number)
{
if (frac == null)
throw new ArgumentNullException("frac", "Bruchobjekt darf nicht 'null' sein.");
return frac.Divide(number);
}
public static Fraction operator /(Fraction frac, double number)
{
if (frac == null)
throw new ArgumentNullException("frac", "Bruchobjekt darf nicht 'null' sein.");
return frac.Divide(number);
}
#endregion
#endregion
}
}