Skip to content

Instantly share code, notes, and snippets.

@utterstep
Created March 31, 2013 20:49
Show Gist options
  • Save utterstep/5281947 to your computer and use it in GitHub Desktop.
Save utterstep/5281947 to your computer and use it in GitHub Desktop.
Fraction class, can turn any ordinary fraction into decimal
public class Fraction
{
private int[] _decimalDigits;
private int _cycleStart;
private static int GCD(int a, int b)
{
if (a % b == 0)
{
return b;
}
bool aIsEven = (a & 1) == 0;
bool bIsEven = (b & 1) == 0;
if (aIsEven && bIsEven)
{
return 2 * GCD(a >> 1, b >> 1);
} else if (aIsEven) {
return GCD(a >> 1, b);
} else if (bIsEven) {
return GCD(a, b >> 1);
} else if (a > b) {
return GCD((a - b) >> 1, b);
} else {
return GCD((b - a) >> 1, a);
}
}
public int IntegerPart { get; private set; }
public int Numerator { get; private set; }
public int Denominator { get; private set; }
public int CycleLength
{
get
{
return _decimalDigits.Length - _cycleStart;
}
}
public Fraction(int numerator, int denominator)
{
int gcd = GCD(denominator, numerator);
IntegerPart = numerator / denominator;
Numerator = (numerator - (denominator * IntegerPart)) / gcd;
Denominator = denominator / gcd;
ComputeDecimalForm();
}
private void ComputeDecimalForm()
{
HashSet<int> numerators = new HashSet<int>();
List<int> decimalDigits = new List<int>();
int numerator = Numerator;
int denominator = Denominator;
int countOfZeroes = 0;
while (numerator < denominator && numerator > 0)
{
numerator *= 10;
countOfZeroes++;
}
while (numerator % denominator != 0)
{
while (numerator < denominator)
{
numerator *= 10;
}
if (!numerators.Add(numerator))
{
int cycleStart = 0;
foreach (var item in numerators)
{
if (numerator == item)
{
break;
}
cycleStart++;
}
_cycleStart = cycleStart + countOfZeroes;
_decimalDigits = new int[countOfZeroes + decimalDigits.Count];
Array.Copy(decimalDigits.ToArray(), 0, _decimalDigits, countOfZeroes, decimalDigits.Count);
return;
}
decimalDigits.Add(numerator / denominator);
numerator = numerator % denominator;
}
decimalDigits.Add(numerator / denominator);
_decimalDigits = new int[countOfZeroes + decimalDigits.Count];
Array.Copy(decimalDigits.ToArray(), 0, _decimalDigits, countOfZeroes, decimalDigits.Count);
_cycleStart = _decimalDigits.Length;
}
public override string ToString()
{
var sb = new System.Text.StringBuilder(_decimalDigits.Length + 4);
sb.AppendFormat("{0}.", IntegerPart);
for (int i = 1; i < _cycleStart; i++)
{
sb.Append(_decimalDigits[i]);
}
if (_cycleStart < _decimalDigits.Length)
{
sb.Append("(");
for (int i = _cycleStart; i < _decimalDigits.Length; i++)
{
sb.Append(_decimalDigits[i]);
}
sb.Append(")");
}
return String.Format("{0}/{1} == {2}", Numerator + IntegerPart * Denominator, Denominator, sb);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment