123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232 |
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- namespace MatrixIO
- {
- public struct Fraction : IComparable, IComparable<Fraction>, IEquatable<Fraction>
- {
- #region Value
- private readonly int _numerator;
- public int Numerator { get { return _numerator; } }
- private readonly int _denominator;
- public int Denominator { get { return _denominator; } }
- #endregion
- #region Properties
- private readonly bool _isInLowestTerms;
- public bool IsInLowestTerms { get { return _isInLowestTerms; } }
- #endregion
- #region Constructors
- public Fraction(int numerator, int denominator)
- {
- if (denominator == 0) throw new ArgumentOutOfRangeException("Denominator must not be 0.");
- if(denominator < 0 )
- {
- if(numerator < 0)
- {
- _numerator = Math.Abs(numerator);
- _denominator = Math.Abs(denominator);
- }
- else
- {
- _numerator = -numerator;
- _denominator = Math.Abs(denominator);
- }
- }
- _numerator = numerator;
- _denominator = denominator;
- _isInLowestTerms = false;
- }
- public Fraction(int numerator, int denominator, bool asLowestTerms)
- : this(numerator, denominator)
- {
- if(asLowestTerms)
- {
- var gcd = GreatestCommonDivisor(_numerator, _denominator);
- _numerator = _numerator / gcd;
- _denominator = _denominator / gcd;
- }
- _isInLowestTerms = asLowestTerms;
- }
- private Fraction(bool inLowestTerms, int numerator, int denominator)
- : this(numerator, denominator)
- {
- _isInLowestTerms = inLowestTerms;
- }
- #endregion
- public Fraction GetLowestTerms()
- {
- if (_isInLowestTerms) return this;
- var gcd = GreatestCommonDivisor(_numerator, _denominator);
- return new Fraction(true, _numerator / gcd, _denominator / gcd);
- }
- public Fraction GetReciprocal()
- {
- return new Fraction(_isInLowestTerms, _denominator, _numerator);
- }
-
- public int GetIntegerPart()
- {
- return Numerator / Denominator;
- }
- public IEnumerable<int> GetFractionalPartEnumerator()
- {
- var remainder = (long)Numerator % Denominator;
- while (remainder > 0)
- {
- var newNumerator = (remainder > Denominator) ? remainder : remainder * 10;
- var digit = newNumerator / Denominator;
- yield return digit;
- remainder = (long)newNumerator % Denominator;
- }
- }
- #region Arithmetic Operators
- public static Fraction operator +(Fraction a, Fraction b)
- {
- var lcm = LeastCommonMultiple(a.Denominator, b.Denominator);
- var numerator = (a.Numerator * lcm) + (b.Numerator * lcm);
- var denominator = (a.Denominator * lcm) + (b.Denominator * lcm);
- return new Fraction(numerator, denominator, true);
- }
- public static Fraction operator -(Fraction a, Fraction b)
- {
- var lcm = LeastCommonMultiple(a.Denominator, b.Denominator);
- var numerator = (a.Numerator * lcm) - (b.Numerator * lcm);
- var denominator = (a.Denominator * lcm) - (b.Denominator * lcm);
- return new Fraction(numerator, denominator, true);
- }
- public static Fraction operator *(Fraction a, Fraction b)
- {
- return new Fraction(a.Numerator * b.Numerator, a.Denominator * b.Denominator);
- }
- public static Fraction operator /(Fraction a, Fraction b)
- {
- return a * b.GetReciprocal();
- }
- #endregion
- #region Conversion Operators
- public static explicit operator float(Fraction a)
- {
- return (float)a.Numerator / a.Denominator;
- }
- public static explicit operator double(Fraction a)
- {
- return (double)a.Numerator / a.Denominator;
- }
- public static explicit operator decimal(Fraction a)
- {
- return (decimal)a.Numerator / a.Denominator;
- }
- public static implicit operator Fraction(int a)
- {
- return new Fraction(true, a, 1);
- }
- #endregion
- #region Equality Operators
- public static bool operator ==(Fraction a, Fraction b)
- {
- return ((long)a.Numerator * b.Denominator) == ((long)a.Denominator * b.Numerator);
- }
- public static bool operator !=(Fraction a, Fraction b)
- {
- return !(a == b);
- }
- public static bool operator >(Fraction a, Fraction b)
- {
- return ((long)a.Numerator * b.Denominator) > ((long)a.Denominator * b.Numerator);
- }
- public static bool operator <(Fraction a, Fraction b)
- {
- return ((long)a.Numerator * b.Denominator) < ((long)a.Denominator * b.Numerator);
- }
- #endregion
- #region IComparable<Fraction> Implementation
- public int CompareTo(Fraction other)
- {
- return ((long)Numerator * b.Denominator) - ((long)Denominator * b.Numerator);
- }
- public int CompareTo(object obj)
- {
- throw new NotImplementedException();
- }
- #endregion
- public bool Equals(Fraction other)
- {
- return this == other;
- }
- #region Object overrides
- public override bool Equals(object obj)
- {
- if (obj == null || !(obj is Fraction)) return false;
- return Equals((Fraction)obj);
- }
- public override int GetHashCode()
- {
- return _numerator.GetHashCode() ^ _denominator.GetHashCode();
- }
- public override string ToString()
- {
- // TODO: Call ToString(string format) instead once it's written.
- return String.Format("{0}/{1}", _numerator, _denominator);
- }
- #endregion
- public byte[] GetBytes()
- {
- var bytes = new byte[8];
-
- var numerator = BitConverter.GetBytes(_numerator);
- Buffer.BlockCopy(numerator, 0, bytes, 0, numerator.Length);
- var denominator = BitConverter.GetBytes(_isInLowestTerms ? -_denominator : _denominator);
- Buffer.BlockCopy(denominator, 0, bytes, numerator.Length, denominator.Length);
- return bytes;
- }
- public static Fraction FromBytes(byte[] buffer, int offset)
- {
- throw new NotImplementedException();
- }
- public static int LeastCommonMultiple(int a, int b)
- {
- return LeastCommonMultiple(a, b, GreatestCommonDivisor(a, b));
- }
- public static int LeastCommonMultiple(int a, int b, int gcd)
- {
- return (a * b) / gcd;
- }
- public static int GreatestCommonDivisor(int dividend, int divisor)
- {
- var remainder = -1;
- while (remainder != 0)
- {
- int quotient = dividend / divisor;
- remainder = dividend % divisor;
- if (remainder != 0)
- {
- dividend = divisor;
- divisor = remainder;
- }
- }
- return divisor;
- }
- }
- }
|