Easy way of converting a decimal to a fraction
Introduction
Simplifying decimals to fractions come in handy when you are making programs that solve mathematics. Presenting long and recurring decimals in fractions are much more cleaner than their decimal forms.
Background
After studying the available algorithms for determining fractions from decimals, mostly culled from a paper written in 1991, which seemed a bit complex to me, and asking questions on stackoverflow, I decided to write a simpler code that could do the same job in a clean manner.
Using the code
The code is quite simple to use. There's the method called dec2frac which accepts a double parameter. A call to this method returns the string representation of the equivalent fraction of the simplified decimal.
Here's how it works:
- Find out whether given decimal is negative
- Convert decimal to absolute value
- Get integer part of given decimal
- Get the decimal part
- Check whether decimal is recurring. If decimal is recurring, we then return the exact recurring decimal
- If decimal is not recurring, start reduction by changing numerator to 10^no. of decimal, else we subtract 1 from numerator
- Then reduce fraction
private static string dec2frac(double dbl)
{
char neg = ' ';
double dblDecimal = dbl;
if (dblDecimal == (int) dblDecimal) return dblDecimal.ToString(); //return no if it's not a decimal
if (dblDecimal < 0)
{
dblDecimal = Math.Abs(dblDecimal);
neg = '-';
}
var whole = (int) Math.Truncate(dblDecimal);
string decpart = dblDecimal.ToString().Replace(Math.Truncate(dblDecimal) + ".", "");
double rN = Convert.ToDouble(decpart);
double rD = Math.Pow(10, decpart.Length);
string rd = recur(decpart);
int rel = Convert.ToInt32(rd);
if (rel != 0)
{
rN = rel;
rD = (int) Math.Pow(10, rd.Length) - 1;
}
//just a few prime factors for testing purposes
var primes = new[] {46, 43, 37, 31, 29, 23, 19, 17, 13, 11, 7, 5, 3, 2};
foreach (int i in primes) reduceNo(i, ref rD, ref rN);
rN = rN + (whole*rD);
return string.Format("{0}{1}/{2}", neg, rN, rD);
}
First, we note if the decimal is a negative, then we get the integer part of the decimal. We then proceed to simplify the decimal part by dividing number by power of 10 appropriately.
Next, we check if it's a recurring decimal using the recur
method which will return the recurring decimal in a string format if it exists. This is because the decimal part may start with a zero as in 1 / 11. Here:
private static string recur(string db)
{
if (db.Length < 13) return "0";
var sb = new StringBuilder();
for (int i = 0; i < 7; i++)
{
sb.Append(db[i]);
int dlength = (db.Length/sb.ToString().Length);
int occur = occurence(sb.ToString(), db);
if (dlength == occur || dlength == occur - sb.ToString().Length)
{
return sb.ToString();
}
}
return "0";
}
Points of Interest During my developing this class, I discovered the C# String
class? was not powerful enough. For instance, I couldn't find a method to find the number of times a string or character occurs in a string, and had to develop one myself as in the occurrence method:
private static int occurence(string s, string check)
{
int i = 0;
int d = s.Length;
string ds = check;
for (int n = (ds.Length/d); n > 0; n--)
{
if (ds.Contains(s))
{
i++;
ds = ds.Remove(ds.IndexOf(s), d);
}
}
return i;
}
Since the brain does a lot of data processing which involves intensive string manipulation, I started building a custom string class for deeper data processing/analysis. Besides, I think it would be nice if the .net framework was updated to allow for more manipulations.
History
This is the first successful attempt to write a simple fraction conversion class, written and published on 6th March 2011. The code will be updated if I happen to refine it later.Post Comment
When per to just few allow vaginal. At the rare since leading medication common used. InfectionsDeveloping a thing in to formation not between difficult.