Converting a decimal to a fraction in C#
-
09/ذو الحجة/1431 07:02 م
I need to take a decimal like 4.625 and turn it into a fraction. Does anyone have a class that will do it? I found one but it gets stuck in a loop... I copied the code here but if someone has a class that works, I'd appreciate it. Thanks!
using System; using System.Collections.Generic; using System.Text; public class UtilityNumberConversions { public string dec2frac(double dblDecimal) { int intNumerator = 0; int intDenominator = 0; int intNegative = 0; // Declare integer variables double dblFraction = 0; double dblAccuracy = 0; // Declare floating point variables as double precision. string txtDecimal = null; // need a string representation of the input value // in order to determine the required accuracy. // Find the accuracy needed for the output by checking the number of digits behind the decimal point // of the input value. // // dblAccuracy = 1 / 10 ^ (Len(CStr(dblDecimal - Fix(dblDecimal))) - 2) // // While the formula above should work, there is a serious error in the way Excel handles // decimal numbers and there's a huge rounding error issue. Subtracting the int() of // 12.1 from 12.1 produces 0.0999999999 or something similar. Obviously that won't // work for our desired accuracy of the magnitude of the fractional part of the number // so a slower more cumbersome method has to be used... dblAccuracy = 0.1; // Set the initial Accuracy level. txtDecimal = dblDecimal.ToString(); // Get a string representation of the input number. // Check each character to see if it's a decimal point... for (int i = 0; i <= (txtDecimal.Length - 1); i++) { // if it is then we get the number of digits behind the decimal if (txtDecimal.Substring(i, 1) == ".") { dblAccuracy = 1 / Math.Pow(10, (txtDecimal.Length - i)); // assign the new accuracy level, and break; // TODO: might not be correct. Was : Exit For // exit the for loop. } } intNumerator = 0; // Set the initial numerator value to 0. intDenominator = 1; // Set the initial denominator value to 1. intNegative = 1; // Set the negative value flag to positive. if (dblDecimal < 0) { intNegative = -1; // If the desired decimal value is negative, // then set the negative value flag to // negative. } dblFraction = 0; // Set the fraction value to be 0/1. // As long as we're still outside the while (Math.Abs(dblFraction - dblDecimal) < dblAccuracy) { // desired accuracy, then... // If our fraction is too big, if (Math.Abs(dblFraction) > Math.Abs(dblDecimal)) { intDenominator += 1; // increase the denominator // Otherwise } else { intNumerator += intNegative; // increase the numerator. } dblFraction = intNumerator / intDenominator; // Set the new value of the fraction. } return intNumerator.ToString() + "/" + intDenominator.ToString(); // Display the numerator and denominator } }
الإجابات
-
09/ذو الحجة/1431 09:14 م
Here is one that I came up with a couple of years ago, try it out:
public static class FractionConverter { public static string Convert(decimal value) { // 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 teh 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 gratest 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(); } public static decimal Convert(string value) { return 0m; } 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; } } }
public enum Answers { Everything = 0x2A }- تم وضع علامة كإجابة بواسطة ljv_csharp 11/ذو الحجة/1431 01:53 م
جميع الردود
-
09/ذو الحجة/1431 09:14 م
Here is one that I came up with a couple of years ago, try it out:
public static class FractionConverter { public static string Convert(decimal value) { // 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 teh 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 gratest 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(); } public static decimal Convert(string value) { return 0m; } 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; } } }
public enum Answers { Everything = 0x2A }- تم وضع علامة كإجابة بواسطة ljv_csharp 11/ذو الحجة/1431 01:53 م
-
09/ذو الحجة/1431 10:57 م
http://www.vcskicks.com/decimal-to-fraction.php
public string ConvertToFraction(double dValue) { string frac = String.Empty; try { if (dValue > 2147483647 && dValue < 1.0 / 2147483647) frac = "not possible"; if (dValue % 1 == 0) // if whole number frac = dValue.ToString(); else { double dTemp = dValue; int iMultiple = 1; string strTemp = dValue.ToString(); int i = 0; while (strTemp[i] != '.') i++; int iDigitsAfterDecimal = strTemp.Length - i - 1; while (dTemp * 10 < 2147483647 && iMultiple * 10 < 2147483647 && iDigitsAfterDecimal > 0) { dTemp *= 10; iMultiple *= 10; iDigitsAfterDecimal--; } int temp1 = (int)Math.Round(dTemp);//numerator int temp2 = iMultiple;//denominator frac = ReduceFraction(temp1, temp2); } return frac; } catch (Exception) { return frac = "oops"; } } public string ReduceFraction(int Numerator, int Denominator) { try { if (Numerator == 0) { Denominator = 1; return Numerator.ToString() + "/" + Denominator.ToString(); } int iGCD = GCD(Numerator, Denominator); Numerator /= iGCD; Denominator /= iGCD; if (Denominator < 0) // if -ve sign in denominator { //pass -ve sign to numerator Numerator *= -1; Denominator *= -1; } string temp1 = Numerator.ToString(); string temp2 = Denominator.ToString(); string frac = temp1 + "/" + temp2; return frac; } catch (Exception exp) { return"Cannot reduce Fraction"; } } private static int GCD(int iNo1, int iNo2) { // take absolute values if (iNo1 < 0) iNo1 = -iNo1; if (iNo2 < 0) iNo2 = -iNo2; do { if (iNo1 < iNo2) { int tmp = iNo1; // swap the two operands iNo1 = iNo2; iNo2 = tmp; } iNo1 = iNo1 % iNo2; } while (iNo1 != 0); return iNo2; }http://forum.codecall.net/c-programming/8043-convert-any-double-fraction.html
mole on left eye -
11/ذو الحجة/1431 01:53 مThanks for this.. It appears to work just fine. I appreciate your help.
-
12/ذو الحجة/1431 09:53 ص
Just as a matter of interest, you can write a greatest common divisor method more succinctly using recursion, like so:
static uint GreatestCommonDivisor(uint valA, uint valB)
{
if (valB == 0)
return valA;
else
return GreatestCommonDivisor(valB, valA % valB);
}
-
29/ذو القعدة/1432 10:31 ص
private string GetDisplayValue(string value) { try { decimal dc; if (!decimal.TryParse(value, out dc)) return value; if (dc == 0) return "0"; int a, b = 10000, c, d, e; decimal temp; temp = dc; temp = temp - (temp < 0 ? Math.Ceiling(temp) : Math.Floor(temp)); a = (int) (temp*b); e = a; c = b; d = b; while (c != 0) { d = c; c = e%d; e = d; } var sign = dc < 0 ? "-" : ""; var whole = Math.Abs(temp < 0 ? Math.Ceiling(dc) : Math.Floor(dc)) == 0 ? string.Empty : Math.Abs(temp < 0 ? Math.Ceiling(dc) : Math.Floor(dc)) + " "; var fractionTop = Math.Abs(a)/Math.Abs(d) == 0 ? string.Empty : (Math.Abs(a)/Math.Abs(d)).ToString(); var fractionBottom = Math.Abs(b)/Math.Abs(d) == 1 ? string.Empty : (Math.Abs(b)/Math.Abs(d)).ToString(); var separator = fractionTop == string.Empty && fractionBottom == string.Empty ? string.Empty : "/"; return string.Format("{0}{1}{2}{3}{4}", sign, whole, fractionTop, separator, fractionBottom).Trim(); } catch { throw; } }
-
08/ربيع الأول/1433 06:11 ص
void Main() { int w, n, d; RoundToMixedFraction(16.5675, 64, out w, out n, out d); Console.WriteLine("{0} {1}/{2}", w, n, d); // outputs: 16 9/16 } void RoundToMixedFraction(double input, int accuracy, out int whole, out int numerator, out int denominator) { double dblAccuracy = (double) accuracy; whole = (int)(Math.Truncate(input)); var fraction = Math.Abs(input - whole); if(fraction == 0) { numerator = 0; denominator = 1; return; } var n = Enumerable.Range(0, accuracy+1).SkipWhile(e => (e/dblAccuracy) < fraction).First(); var hi = n / dblAccuracy; var lo = (n-1) / dblAccuracy; if((fraction - lo) < (hi - fraction)) n--; if(n == accuracy) { whole++; numerator = 0; denominator = 1; return; } var gcd = GCD(n, accuracy); numerator = n / gcd; denominator = accuracy / gcd; } int GCD(int a, int b) { if(b == 0) return a; else return GCD(b, a % b); }