12,553,155 members (55,595 online)
Tip/Trick
alternative version

23.2K views
9 bookmarked
Posted

# Convert Decimal to Fraction and Vice Versa in C#

, 20 Jul 2013 CPOL
 Rate this:
Class for converting decimals and fractions (allows rounding to a decimal also)

## Introduction

Recently, I was challenged with writing a report to generate a quote for an engineering specification. One of the requirements for this report was to convert decimals to fractions, and vice versa. It was also required to round the fractions to the nearest 1/16 of an inch.

## Background

I had run several internet searches to help me solve these issues and turned up some interesting stuff, but nothing to "do it all." So I combined what I found out there into one class, made some modifications, used it in my report, then decided to share this with my comrades here on CodeProject. My hope is that this class can be utilized, expanded upon, and / or optimized by the community.

## Using the Code

I used Visual Studio to compile and run the class. Writing a test app to use this class should be simple enough.  If not, let me know and I'll push something up here.

#### Notes

• I default the fractions to round to 1/16 as this was the requirement for the report. You can skip rounding all together by not passing in the last two parameters into the "`Convert`" function returning the `string `(fraction) value.
• I wrote a handy little formatter for feet and inches that might help someone too (another requirement for the report I had to write).
```public static class FractionConverter
{
public static string Convert(decimal pvalue,
bool skip_rounding = false, decimal dplaces = (decimal)0.0625)
{
decimal value = pvalue;

if (!skip_rounding)
value = FractionConverter.DecimalRound(pvalue, dplaces);

if (value == Math.Round(value, 0)) // whole number check
return value.ToString();

// get the whole value of the fraction
decimal mWhole = Math.Truncate(value);

// get the fractional value
decimal mFraction = value - mWhole;

// initialize a numerator and denomintar
uint mNumerator = 0;
uint mDenomenator = 1;

// ensure that there is actual a fraction
if (mFraction > 0m)
{
// convert the value to a string so that
// you can count the number of decimal places there are
string strFraction = mFraction.ToString().Remove(0, 2);

// store the number of decimal places
uint intFractLength = (uint)strFraction.Length;

// set the numerator to have the proper amount of zeros
mNumerator = (uint)Math.Pow(10, intFractLength);

// parse the fraction value to an integer that equals
// [fraction value] * 10^[number of decimal places]
uint.TryParse(strFraction, out mDenomenator);

// get the greatest common divisor for both numbers
uint gcd = GreatestCommonDivisor(mDenomenator, mNumerator);

// divide the numerator and the denominator by the greatest common divisor
mNumerator = mNumerator / gcd;
mDenomenator = mDenomenator / gcd;
}

// create a string builder
StringBuilder mBuilder = new StringBuilder();

// add the whole number if it's greater than 0
if (mWhole > 0m)
{
mBuilder.Append(mWhole);
}

// add the fraction if it's greater than 0m
if (mFraction > 0m)
{
if (mBuilder.Length > 0)
{
mBuilder.Append(" ");
}

mBuilder.Append(mDenomenator);
mBuilder.Append("/");
mBuilder.Append(mNumerator);
}

return mBuilder.ToString();
}

// Converts fraction to decimal.
// There are two formats a fraction greater than 1 can consist of
// which this function will work for:
//  Example: 4-1/2 or 4 1/2
// Fractions less than 1 are in the format of 1/2, etc..
public static decimal Convert(string value)
{
string[] dparse;
string[] fparse;
string whole = "0";
string dec = "";
decimal dReturn = 0;

// check for '-' or ' ' separator between whole number and fraction
dparse = value.Contains('-') ? value.Split('-') : value.Split(' ');
int pcount = dparse.Count();

// fraction greater than one.
if (pcount == 2)
{
whole = dparse[0];
dec = dparse[1];
}
// whole number or fraction less than 1.
else if (pcount == 1)
dec = dparse[0];

// split out fractional part of value passed in.
fparse = dec.Split('/');

// check for fraction.
if (fparse.Count() == 2)
{
try
{
decimal d0 = System.Convert.ToDecimal(fparse[0]); // convert numerator
decimal d1 = System.Convert.ToDecimal(fparse[1]); // convert denominator
dReturn = d0 / d1; // divide the fraction (converts to decimal)
decimal dWhole = System.Convert.ToDecimal(whole); // convert
// whole number part to decimal.

dReturn = dWhole + dReturn; // add whole number
// and fractional part and we're done.
}
catch (Exception e)
{
dReturn = 0;
}
}
else
// there is no fractional part of the input.
{
try
{
dReturn = System.Convert.ToDecimal(whole + dec);
}
catch (Exception e)
{
// bad input so return 0.
dReturn = 0;
}
}

return dReturn;
}

private static uint GreatestCommonDivisor(uint valA, uint valB)
{
// return 0 if both values are 0 (no GSD)
if (valA == 0 &&
valB == 0)
{
return 0;
}
// return value b if only a == 0
else if (valA == 0 &&
valB != 0)
{
return valB;
}
// return value a if only b == 0
else if (valA != 0 && valB == 0)
{
return valA;
}
// actually find the GSD
else
{
uint first = valA;
uint second = valB;

while (first != second)
{
if (first > second)
{
first = first - second;
}
else
{
second = second - first;
}
}

return first;
}

}

// Converts a value to feet and inches.
// Examples:
//  12.1667 converts to 12' 2"
//  4 converts to 4'
//  0.1667 converts to 2"
public static bool ReformatForFeetAndInches
(ref string line_type, bool zero_for_blank = true)
{
if (string.IsNullOrEmpty(line_type))
{
if (zero_for_blank)
line_type = "0'";
return true;
}

decimal d = System.Convert.ToDecimal(line_type);
decimal d1 = Math.Floor(d);
decimal d2 = d - d1;
d2 = Math.Round(d2 * 12, 2);

string s1;
string s2;

s1 = d1 == 0 ? "" : d1.ToString() + "'";
s2 = d2 == 0 ? "" : FractionConverter.Convert(d2) + @"""";

line_type = string.Format(@"{0} {1}", s1, s2).Trim();

if (string.IsNullOrEmpty(line_type))
{
if (zero_for_blank)
line_type = "0'";
return true;
}

return true;
}

// Rounds a number to the nearest decimal.
// For instance, carpenters do not want to see a number like 4/5.
// That means nothing to them
// and you'll have an angry carpenter on your hands
// if you ask them cut a 2x4 to 36 and 4/5 inches.
// So, we would want to convert to the nearest 1/16 of an inch.
// Example: DecimalRound(0.8, 0.0625) Rounds 4/5 to 13/16 or 0.8125.
private static decimal DecimalRound(decimal val, decimal places)
{
string sPlaces = FractionConverter.Convert(places, true);
string[] s = sPlaces.Split('/');

if (s.Count() == 2)
{
int nPlaces = System.Convert.ToInt32(s[1]);
decimal d = Math.Round(val*nPlaces);
return  d / nPlaces;
}

return val;
}
}
```

## Share

 Software Developer (Senior) United States
I've been a software developer for over 25 years. Worked on commercial grade Point of Sale and Order Entry software applications.

Worked with Symbol Technology Handheld bar code scanners quite a bit. Written Sqllite libraries that run on these devices.

Develop client/server solutions in ASP.NET. MVC, and MVVM design patterns.

## You may also be interested in...

 First Prev Next
 Run this code in Visual Studio 2005 Barrywl31-Aug-15 6:58 Barrywl 31-Aug-15 6:58
 Test App for FractionConverter nbrooks11-Aug-13 5:12 nbrooks 11-Aug-13 5:12
 My vote of 2 Philippe Mori19-Jul-13 13:03 Philippe Mori 19-Jul-13 13:03
 Re: My vote of 2 Patrick Harris19-Jul-13 15:28 Patrick Harris 19-Jul-13 15:28
 Re: My vote of 2 Garth J Lancaster19-Jul-13 17:49 Garth J Lancaster 19-Jul-13 17:49
 Re: My vote of 2 Patrick Harris20-Jul-13 5:45 Patrick Harris 20-Jul-13 5:45
 Re: My vote of 2 Garth J Lancaster20-Jul-13 19:43 Garth J Lancaster 20-Jul-13 19:43
 Re: My vote of 2 Patrick Harris20-Jul-13 21:35 Patrick Harris 20-Jul-13 21:35
 Re: My vote of 2 Philippe Mori23-Jul-13 14:31 Philippe Mori 23-Jul-13 14:31
 Re: My vote of 2 Patrick Harris24-Jul-13 4:18 Patrick Harris 24-Jul-13 4:18
 Re: My vote of 2 Philippe Mori24-Jul-13 4:48 Philippe Mori 24-Jul-13 4:48
 Re: My vote of 2 Patrick Harris24-Jul-13 5:10 Patrick Harris 24-Jul-13 5:10
 Re: My vote of 2 Philippe Mori24-Jul-13 5:38 Philippe Mori 24-Jul-13 5:38
 Re: My vote of 2 Patrick Harris24-Jul-13 6:05 Patrick Harris 24-Jul-13 6:05
 Re: My vote of 2 Philippe Mori24-Jul-13 6:21 Philippe Mori 24-Jul-13 6:21
 Re: My vote of 2 Patrick Harris24-Jul-13 8:25 Patrick Harris 24-Jul-13 8:25
 Re: My vote of 2 Philippe Mori24-Jul-13 8:31 Philippe Mori 24-Jul-13 8:31
 Re: My vote of 2 Patrick Harris24-Jul-13 8:36 Patrick Harris 24-Jul-13 8:36
 Re: My vote of 2 Philippe Mori24-Jul-13 9:09 Philippe Mori 24-Jul-13 9:09
 Re: My vote of 2 Patrick Harris25-Jul-13 3:49 Patrick Harris 25-Jul-13 3:49
 Last Visit: 31-Dec-99 18:00     Last Update: 24-Oct-16 18:50 Refresh 1

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

Web02 | 2.8.161021.1 | Last Updated 20 Jul 2013
Article Copyright 2013 by Patrick Harris