Laden...

[Komponente] Bruchrechnung (struct Fraction)

Letzter Beitrag vor 12 Jahren 2 Posts 4.782 Views
[Komponente] Bruchrechnung (struct Fraction)

Beschreibung:

Angeregt von Präzises Rechnen mit Nachkommastellen habe ich ein bisschen rumgebastelt und dabei "zufällig" 8) eine Klasse zur Rechnung mit Brüchen erstellt. Wollte sie euch nicht vorenthalten.

public struct Fraction : IFormattable, IEquatable<Fraction>, IComparable<Fraction>
{
    private BigInteger m_Sign;
    private BigInteger m_Numerator;
    private BigInteger m_Denominator;

    public Fraction(BigInteger numerator, BigInteger denominator)
    {
        if (denominator == BigInteger.Zero)
            throw new DivideByZeroException();

        if (numerator != BigInteger.Zero)
        {
            var n = BigInteger.Abs(numerator);
            var d = BigInteger.Abs(denominator);

            var gcd = GreatestCommonDivisor(n, d);

            m_Numerator = n / gcd;
            m_Denominator = d / gcd;
            m_Sign = GetSign(numerator) * GetSign(denominator);
        }
        else
        {
            m_Numerator = BigInteger.Zero;
            m_Denominator = BigInteger.One;
            m_Sign = BigInteger.One;
        }
    }

    public BigInteger Sign { get { return m_Sign; } }
    public BigInteger Numerator { get { return m_Numerator; } }
    public BigInteger Denominator { get { return m_Denominator; } }
    public bool IsPositive { get { return m_Sign == BigInteger.One; } }
    public bool IsNegative { get { return m_Sign == BigInteger.MinusOne; } }
    public bool IsZero { get { return m_Numerator == BigInteger.Zero; } }
    public bool IsRational { get { return m_Denominator != BigInteger.One; } }
    public bool IsInteger { get { return m_Denominator == BigInteger.One; } }
    public decimal DecimalValue { get { return (decimal)m_Numerator / (decimal)m_Denominator; } }

    public Fraction Inverse()
    {
        return new Fraction(m_Sign * m_Denominator, m_Numerator);
    }

    public override string ToString()
    {
        return ToString("");
    }

    public string ToString(string format, IFormatProvider provider = null)
    {
        var sign = IsNegative ? "-" : "";

        switch (format)
        {
            case null:
            case "":
                if (IsZero)
                    return "0";

                if (IsInteger)
                    return sign + m_Numerator.ToString();

                goto case "F";
            case "D":
                return sign + DecimalValue.ToString();
            case "F":
                return sign + m_Numerator.ToString() + "/" + m_Denominator.ToString();
            default:
                throw new FormatException(String.Format("\"{0}\" is not a valid format for fractions!", format));
        }
    }

    public override bool Equals(object obj)
    {
        if (obj is Fraction)
        {
            return Equals((Fraction)obj);
        }

        return false;
    }

    public bool Equals(Fraction other)
    {
        return this == other;
    }

    public int CompareTo(Fraction other)
    {
        if (this > other)
        {
            return 1;
        }
        else if (this < other)
        {
            return -1;
        }
        else
        {
            return 0;
        }
    }

    public override int GetHashCode()
    {
        var signBytes = m_Sign.ToByteArray();
        var numeratorBytes = m_Numerator.ToByteArray();
        var denominatorBytes = m_Denominator.ToByteArray();
        var allBytes = new byte[signBytes.Length + numeratorBytes.Length + denominatorBytes.Length];

        Array.Copy(signBytes, 0, allBytes, 0, signBytes.Length);
        Array.Copy(numeratorBytes, 0, allBytes, signBytes.Length, numeratorBytes.Length);
        Array.Copy(denominatorBytes, 0, allBytes, signBytes.Length + numeratorBytes.Length, denominatorBytes.Length);

        return new BigInteger(allBytes).GetHashCode();
    }

    private static BigInteger GetSign(BigInteger a)
    {
        return a < BigInteger.Zero ? BigInteger.MinusOne : BigInteger.One;
    }

    private static BigInteger GreatestCommonDivisor(BigInteger a, BigInteger b)
    {
        BigInteger t;

        if (a > b)
        {
            t = b;
            b = a;
            a = t;
        }

        while (b != 0)
        {
            t = a % b;
            a = b;
            b = t;
        }

        return a;
    }

    public static Fraction operator -(Fraction a)
    {
        return new Fraction(BigInteger.MinusOne * a.m_Sign * a.m_Numerator, a.m_Denominator);
    }

    public static Fraction operator +(Fraction a, Fraction b)
    {
        return new Fraction(a.m_Sign * a.m_Numerator * b.m_Denominator + b.m_Sign * b.m_Numerator * a.m_Denominator, a.m_Denominator * b.m_Denominator);
    }

    public static Fraction operator -(Fraction a, Fraction b)
    {
        return a + -b;
    }

    public static Fraction operator *(Fraction a, Fraction b)
    {
        return new Fraction(a.m_Sign * b.m_Sign * a.m_Numerator * b.m_Numerator, a.m_Denominator * b.m_Denominator);
    }

    public static Fraction operator /(Fraction a, Fraction b)
    {
        return a * b.Inverse();
    }

    public static bool operator ==(Fraction a, Fraction b)
    {
        return a.m_Sign == b.m_Sign && a.m_Numerator == b.m_Numerator && a.m_Denominator == b.m_Denominator;
    }

    public static bool operator !=(Fraction a, Fraction b)
    {
        return !(a == b);
    }

    public static bool operator >(Fraction a, Fraction b)
    {
        var diff = a - b;

        return diff.IsPositive && !diff.IsZero;
    }

    public static bool operator <(Fraction a, Fraction b)
    {
        var diff = a - b;

        return diff.IsNegative && !diff.IsZero;
    }

    public static bool operator >=(Fraction a, Fraction b)
    {
        var diff = a - b;

        return diff.IsPositive || diff.IsZero;
    }

    public static bool operator <=(Fraction a, Fraction b)
    {
        var diff = a - b;

        return diff.IsNegative || diff.IsZero;
    }
}

Gruß, Christian.

Schlagwörter: Bruch Fraction Bruchrechnung

`There are 10 types of people in the world: Those, who think they understand the binary system Those who don't even have heard about it And those who understand "Every base is base 10"`

EDIT: Habe IComparable sowie Vergleichsoperatoren implementiert.

`There are 10 types of people in the world: Those, who think they understand the binary system Those who don't even have heard about it And those who understand "Every base is base 10"`