using System;

class Fraction : IComparable
{
    public int Numerator;                 // Zähler
    public int Denominator;               // Nenner

    public Fraction(int n, int d)
    {
        Numerator = n;
        Denominator = d;
    }

    // Liefert den Wert des Bruchs als Dezimalzahl zurück
    public double GetDecimalNumber()
    {
        return Numerator / (double)Denominator;
    }

    // kürzen
    public void Reduce()
    {
        int gcd = Fraction.GCD(this.Numerator, this.Denominator);

        if (gcd > 1)
        {
            this.Numerator /= gcd;
            this.Denominator /= gcd;
        }
    }

    // Größenvergleich
    public int CompareTo(object obj)
    {
        Fraction arg = obj as Fraction;
        if (arg != null)
        {
            int thisNum = (this.Numerator * arg.Denominator);
            int argNum = (arg.Numerator * this.Denominator);
            return thisNum.CompareTo(argNum);
        }
        else
        {
            throw new ArgumentException("kein Fraction-Objekt");
        }
    }



    /*** Operator-Überladungen  ***/

    // Addition
    public static Fraction operator +(Fraction lhs, Fraction rhs)
    {
        int num = (lhs.Numerator * rhs.Denominator) + (rhs.Numerator * lhs.Denominator);
        int den = (lhs.Denominator * rhs.Denominator);

        Fraction result = new Fraction(num, den);
        result.Reduce();

        return result;
    }
    // Subtraktion
    public static Fraction operator -(Fraction lhs, Fraction rhs)
    {
        int num = (lhs.Numerator * rhs.Denominator) - (rhs.Numerator * lhs.Denominator);
        int den = (lhs.Denominator * rhs.Denominator);

        Fraction result = new Fraction(num, den);
        result.Reduce();

        return result;
    }

    // Gleichheit
    public static bool operator ==(Fraction lhs, Fraction rhs)
    {
        return lhs.Equals(rhs);
    }
    // Ungleichheit
    public static bool operator !=(Fraction lhs, Fraction rhs)
    {
        return !(lhs == rhs);
    }

    // kleiner
    public static bool operator <(Fraction lhs, Fraction rhs)
    {
        int num1 = (lhs.Numerator * rhs.Denominator);
        int num2 = (rhs.Numerator * lhs.Denominator);

        return num1 < num2;
    }
    // kleiner gleich
    public static bool operator <=(Fraction lhs, Fraction rhs)
    {
        int num1 = (lhs.Numerator * rhs.Denominator);
        int num2 = (rhs.Numerator * lhs.Denominator);

        return num1 <= num2;
    }
    // größer
    public static bool operator >(Fraction lhs, Fraction rhs)
    {
        int num1 = (lhs.Numerator * rhs.Denominator);
        int num2 = (rhs.Numerator * lhs.Denominator);

        return num1 > num2;
    }
    // größer gleich
    public static bool operator >=(Fraction lhs, Fraction rhs)
    {
        int num1 = (lhs.Numerator * rhs.Denominator);
        int num2 = (rhs.Numerator * lhs.Denominator);

        return num1 >= num2;
    }

    // explizite Konvertierung von Fraction in double
    public static explicit operator double(Fraction frac)
    {
        return frac.Numerator / (double)frac.Denominator;
    }
    // explizite Konvertierung von Fraction in int
    public static explicit operator int(Fraction frac)
    {
        return frac.Numerator / frac.Denominator;
    }
    // implizite Konvertierung von int-Wert in Fraction
    public static implicit operator Fraction(int n)
    {
        return new Fraction(n, 1);
    }


    /*** Object-Methoden überschreiben ***/

    // In String umwandeln
    public override string ToString()
    {
        return "(" + this.Numerator + "/" + this.Denominator + ")";
    }
    // Hashcode
    public override int GetHashCode()
    {
        return Numerator / Denominator;
    }
    // Gleichheit
    public override bool Equals(Object obj)
    {
        Fraction tmp = obj as Fraction;
        return this.Equals(tmp);
    }
    public bool Equals(Fraction frac)
    {
        // Schnelltest auf Reflexivität
        if (Object.ReferenceEquals(this, frac) == true)
            return true;

        // Schnelltest auf Null
        if ((object)frac == null)
            return false;

        // Ansonsten  vergleichen, ob Zähler bei gleichem Nenner gleich
        if ((this.Numerator * frac.Denominator) == (frac.Numerator * this.Denominator))
            return true;
        else
            return false;
    }


    /*** private Methoden ***/

    // bestimmt den größten gemeinsamen Teiler nach Euklid
    private static int GCD(int a, int b)
    {
        int tmp;

        if (b == 0)
            return 0;

        while (a > 0)
        {
            if (a < b)
            {
                tmp = a;
                a = b;
                b = tmp;
            }

            a = a - b;
        }

        return b;
    }
}

