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
EDIT: Habe IComparable sowie Vergleichsoperatoren implementiert.