Click here to Skip to main content
15,868,016 members
Articles / Programming Languages / C#

Easy Way of Converting a Decimal to a Fraction

Rate me:
Please Sign up or sign in to vote.
3.89/5 (10 votes)
30 Apr 2012CPOL2 min read 117.8K   872   17   15
How to convert a given decimal or double to a fraction in C#

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. However this code has some drawbacks as it focuses mainly on using string manipulation (a more natural way) to achieve its purpose.

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:

  1. Find out whether the given decimal is negative.
  2. Convert decimal to absolute value.
  3. Get integer part of given decimal.
  4. Get the decimal part.
  5. Check whether decimal is recurring. If decimal is recurring, we then return the exact recurring decimal.
  6. If decimal is not recurring, start reduction by changing numerator to 10^no. of decimal, else we subtract 1 from numerator.
  7. Then reduce fraction.

Let's look at the dec2frac method:

C#
private static string Dec2Frac(double dbl)
        {
            char neg = ' ';
            double dblDecimal = dbl;
            if (dblDecimal < 0)
            {
                dblDecimal = Math.Abs(dblDecimal);
                neg = '-';
            }
            var whole = (int) Math.Truncate(dblDecimal);
            if (whole == dbl) {
                return String.Format("{0} because supplied value is not a fraction", dbl); //return no if it's not a decimal
            }
            string decpart = dblDecimal.ToString(CultureInfo.InvariantCulture).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[] {47, 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:

C#
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

While I was developing this class, I discovered the C# String class was not powerful enough (Currently this no longer holds though as LINQ provides a lot of methods for any kind of manipulation). 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:

C#
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--)
    {
        int si = ds.IndexOf(s, StringComparison.Ordinal);
        if (si != -1)
        {
            i++;
            ds = ds.Remove(si, d);
        }
    }
    return i;
}

It may be worthy of note that this method does not do what you may think it's doing. This method checks to see how many times a particular number is occurring inside another number in other to get if a number is recurring. 

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.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer Robotic Systems
Nigeria Nigeria
Chibueze Opata is a software developer studying Computer Science at the University of Nigeria Nsukka. He is also the developer of RoboSAM - A free and unique antivirus solution that relies minimally on signature updates for malware detections.

Comments and Discussions

 
GeneralThoughts Pin
PIEBALDconsult26-Oct-13 20:00
mvePIEBALDconsult26-Oct-13 20:00 
GeneralMy vote of 5 Pin
Joakim Jormelin5-Dec-12 22:57
Joakim Jormelin5-Dec-12 22:57 
GeneralMy vote of 4 Pin
gorgias9915-Mar-11 0:40
gorgias9915-Mar-11 0:40 
GeneralMy vote of 1 Pin
Gustav Brock14-Mar-11 11:23
professionalGustav Brock14-Mar-11 11:23 
GeneralMy vote of 2 Pin
Jasmine250114-Mar-11 10:41
Jasmine250114-Mar-11 10:41 
GeneralMy vote of 2 PinPopular
René Greiner10-Mar-11 4:40
René Greiner10-Mar-11 4:40 
GeneralRe: My vote of 2 Pin
Opata Chibueze10-Mar-11 14:56
Opata Chibueze10-Mar-11 14:56 
GeneralRe: My vote of 2 Pin
René Greiner15-Mar-11 11:33
René Greiner15-Mar-11 11:33 
GeneralRe: My vote of 2 Pin
Opata Chibueze6-Mar-12 22:48
Opata Chibueze6-Mar-12 22:48 
GeneralMy vote of 3 Pin
Toli Cuturicu9-Mar-11 7:56
Toli Cuturicu9-Mar-11 7:56 
GeneralRe: My vote of 3 Pin
Opata Chibueze10-Mar-11 14:46
Opata Chibueze10-Mar-11 14:46 
GeneralRe: My vote of 3 Pin
Toli Cuturicu11-Mar-11 4:35
Toli Cuturicu11-Mar-11 4:35 
Is really 46 a prime number?
What about 41 then? Is it compound?
Do you know anything about C# coding rules? Identifier names and so on?
Why string? It is absurd! The method should clearly return the numerator and the denominator.
(There are many ways to return two or more values...)
And there are way more. Please look for yourself.
GeneralRe: My vote of 3 Pin
Opata Chibueze13-Mar-11 10:19
Opata Chibueze13-Mar-11 10:19 
GeneralRe: My vote of 3 Pin
Jasmine250114-Mar-11 10:40
Jasmine250114-Mar-11 10:40 
GeneralRe: My vote of 3 Pin
Gustav Brock14-Mar-11 11:27
professionalGustav Brock14-Mar-11 11:27 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.