using System; using System.Collections; using System.Collections.Generic; using System.Text; namespace DortikDev { public class Fraction : IEquatable, IEquatable, IComparable, IComparable { #region Enumerators ... public enum FractionForm { Proper, Improper, TopHeavy = Improper }; #endregion #region Private ... int numerator = 0; int denominator = 1; bool autoSimplify = true; #endregion #region Properties ... public int Numerator { get { return this.numerator; } set { if (value == 0) { this.denominator = 1; } this.numerator = value; } } public int Denominator { get { return this.denominator; } set { if (value == 0) { throw new DivideByZeroException("The denominator cannot be equal to zero!"); } else { // if the denominator is negative, we multiply the numerator by -1 // and we use the Abs of the denominator if (value < 0) { this.Numerator *= -1; } this.denominator = Math.Abs(value); } } } public bool AutoSimplify { get { return this.autoSimplify; } set { this.autoSimplify = value; } } public FractionForm Form { get { return (Fraction.Abs(this) < 1) ? FractionForm.Proper : FractionForm.Improper; } } #endregion #region Constructors ... public Fraction() { // ~ } public Fraction(string fraction) { int numerator; int denominator; if (fraction.Contains("/")) { string[] fractionParts = fraction.Split(new char[] { '/' }); if (int.TryParse(fractionParts[0], out numerator) && int.TryParse(fractionParts[1], out denominator)) { Numerator = numerator; Denominator = denominator; } else { throw new ArgumentException("Wrong fraction input!"); } } else { if (int.TryParse(fraction, out numerator)) { Numerator = numerator; } else { throw new ArgumentException("Wrong fraction input!"); } } } public Fraction(int numerator) { this.Numerator = numerator; } public Fraction(int numerator, int denominator) { this.Numerator = numerator; this.Denominator = denominator; } #endregion #region Public Methods ... /// /// Simplifies the fraction /// public void Simplify() { int gcm = greatesCommonDivisor(Numerator, Denominator); Numerator /= gcm; if (Numerator == 0) Denominator = 1; else Denominator /= gcm; } /// /// Adds this fraction to another one /// /// fraction public void Add(Fraction fract) { Fraction fr = new Fraction(); fr.Denominator = this.leastCommonMultiple(Denominator, fract.Denominator); fr.Numerator = (fr.Denominator / Denominator) * Numerator + (fr.Denominator / fract.Denominator) * fract.Numerator; if (AutoSimplify) fr.Simplify(); Numerator = fr.Numerator; Denominator = fr.Denominator; } /// /// Adds a number to this fraction /// /// the number public void Add(int number) { Add(new Fraction(number)); } /// /// Subtracts a fraction from this one /// /// the fraction public void Subtract(Fraction fract) { // изваждането е всъщност събиране с отрицателно число fract.Numerator *= -1; Add(fract); } /// /// Subtracts a number from this fraction /// /// the number public void Subtract(int number) { Subtract(new Fraction(number)); } /// /// Multiplies a fraction with this one /// /// the fraction public void MultiplyWith(Fraction fract) { Numerator *= fract.Numerator; Denominator *= fract.Denominator; if (AutoSimplify) Simplify(); } /// /// Multiplies a number with this fraction /// /// the number public void MultiplyWith(int number) { MultiplyWith(new Fraction(number)); } /// /// Divides this fraction by another one /// /// the target fraction public void DivideBy(Fraction fract) { if (fract == 0) throw new DivideByZeroException("Cannot divide by zero this fraction!"); MultiplyWith(new Fraction(fract.Denominator, fract.Numerator)); } /// /// Divides this fraction by a number /// /// target number public void DivideBy(int number) { if (number == 0) throw new DivideByZeroException("Cannot divide by zero this fraction!"); this.MultiplyWith(new Fraction(1, number)); } /// /// Represents the fraction as a decimal /// /// public decimal ToDecimal() { return (decimal)Numerator / Denominator; } /// /// Rounds the fraction to a regular number /// /// a regular number public int Round() { return Convert.ToInt32(Math.Round(ToDecimal())); } public Fraction GetReciprocal() { if (Numerator == 0) throw new DivideByZeroException("Current fraction is equal to zero! You cannot get its reciprocal one!"); return new Fraction(Denominator, Numerator); } #endregion #region Predefined methods ... /// /// Converts the fraction to a string /// /// a string public override string ToString() { if (Denominator == 1) { // ако знаменателя е равен на 1, то рационалното число съвпада // с цялото число със стойност, равна на числителя на дробта return Numerator.ToString(); } else { // представяме дробта във вида А/В if (Numerator == 0) { // знаменателя е равен на нула => дробта е равна на нула return "0"; } else { return Numerator.ToString() + "/" + Denominator.ToString(); } } } public override int GetHashCode() { return base.GetHashCode(); } /// /// Checks if this fraction is equal to an object /// /// the object /// true / false public override bool Equals(object obj) { if (obj.GetType() == typeof(Fraction)) { return Equals((Fraction)obj); } else if (obj.GetType() == typeof(int)) { return Equals((int)obj); } else { throw new ArgumentException("You cannot compare this fraction with an object of that type!"); } } /// /// Checks if this fraction is equal to another one /// /// the fraction /// true / false public bool Equals(Fraction other) { return (CompareTo(other) == 0); } /// /// Checks if this fraction is equal to a number /// /// the number /// true / false public bool Equals(int other) { return (CompareTo(other) == 0); } /// /// Compares this fraction to another fraction /// /// the fraction /// 1 / 0 / -1 public int CompareTo(Fraction other) { long num1 = this.Numerator * other.Denominator; long num2 = other.Numerator * this.Denominator; if (num1 == num2) return 0; else return (num1 > num2) ? 1 : -1; } /// /// Compares this fraction to a number /// /// the number /// 1 / 0 / -1 public int CompareTo(int other) { Fraction fract = new Fraction(other); return CompareTo(fract); } #endregion #region Operators ... // // Sum // public static Fraction operator +(Fraction lhs, Fraction rhs) { Fraction newFract = new Fraction(lhs.Numerator, lhs.Denominator); newFract.Add(rhs); return newFract; } public static Fraction operator +(Fraction lhs, int rhs) { return lhs + new Fraction(rhs); } public static Fraction operator +(int lhs, Fraction rhs) { return new Fraction(lhs) + rhs; } // // // Subtraction // public static Fraction operator -(Fraction lhs, Fraction rhs) { Fraction newFract = new Fraction(lhs.Numerator, lhs.Denominator); newFract.Subtract(rhs); return newFract; } public static Fraction operator -(Fraction lhs, int rhs) { return lhs - new Fraction(rhs); } public static Fraction operator -(int lhs, Fraction rhs) { return new Fraction(lhs) - rhs; } // // // Multiplication // public static Fraction operator *(Fraction lhs, Fraction rhs) { Fraction newFract = new Fraction(lhs.Numerator, lhs.Denominator); newFract.MultiplyWith(rhs); return newFract; } public static Fraction operator *(Fraction lhs, int rhs) { return lhs * new Fraction(rhs); } public static Fraction operator *(int lhs, Fraction rhs) { return new Fraction(lhs) * rhs; } // // // Division // public static Fraction operator /(Fraction lhs, Fraction rhs) { Fraction newFract = new Fraction(lhs.Numerator, lhs.Denominator); newFract.DivideBy(rhs); return newFract; } public static Fraction operator /(Fraction lhs, int rhs) { return lhs / new Fraction(rhs); } public static Fraction operator /(int lhs, Fraction rhs) { return new Fraction(lhs) / rhs; } // // // Equality // public static bool operator ==(Fraction lhs, Fraction rhs) { return lhs.Equals(rhs); } public static bool operator ==(Fraction lhs, int rhs) { return lhs.Equals(rhs); } public static bool operator !=(Fraction lhs, Fraction rhs) { return !lhs.Equals(rhs); } public static bool operator !=(Fraction lhs, int rhs) { return !lhs.Equals(rhs); } // // // Compare // public static bool operator <(Fraction lhs, Fraction rhs) { return lhs.CompareTo(rhs) < 0; } public static bool operator <(Fraction lhs, int rhs) { return lhs.CompareTo(rhs) < 0; } public static bool operator <=(Fraction lhs, Fraction rhs) { return lhs.CompareTo(rhs) <= 0; } public static bool operator <=(Fraction lhs, int rhs) { return lhs.CompareTo(rhs) <= 0; } public static bool operator >(Fraction lhs, Fraction rhs) { return lhs.CompareTo(rhs) > 0; } public static bool operator >(Fraction lhs, int rhs) { return lhs.CompareTo(rhs) > 0; } public static bool operator >=(Fraction lhs, Fraction rhs) { return lhs.CompareTo(rhs) >= 0; } public static bool operator >=(Fraction lhs, int rhs) { return lhs.CompareTo(rhs) >= 0; } // public static implicit operator Fraction(int number) { return new Fraction(number); } #endregion #region Static Methods ... public static Fraction Abs(Fraction fract) { return new Fraction(Math.Abs(fract.numerator), Math.Abs(fract.Denominator)); } public static Fraction Max(Fraction fract1, Fraction fract2) { if (fract1 > fract2) return new Fraction(fract1.Numerator, fract1.Denominator); else return new Fraction(fract2.Numerator, fract2.Denominator); } public static Fraction Min(Fraction fract1, Fraction fract2) { if (fract1 < fract2) return new Fraction(fract1.Numerator, fract1.Denominator); else return new Fraction(fract2.Numerator, fract2.Denominator); } #endregion #region Auxiliary functions ... /// /// Finds the gratest common diviser of two numbers by Evklid's algorithm /// /// first number /// second number /// the gratest common diviser private int greatesCommonDivisor(int firstNum, int secondNum) { if (secondNum == 0) return firstNum; else return greatesCommonDivisor(secondNum, firstNum % secondNum); } /// /// Finds the least common multiple of two number9s (NOK) /// /// first number /// second number /// the least common multiple private int leastCommonMultiple(int firstNum, int secondNum) { return (firstNum * secondNum) / this.greatesCommonDivisor(firstNum, secondNum); } #endregion } }