Answered by:
decimal or double to mixed fraction in C#
Question

Dear team,
i want to convert double to fraction mixed fraction.
eg MessageBox.Show(DoubleToFraction(27.523869));
public static string DoubleToFraction(double num, double epsilon = 0.0001, int maxIterations = 100) { double[] d = new double[maxIterations + 2]; d[1] = 1; double z = num; double n = 1; int t = 1; int wholeNumberPart = (int)num; double decimalNumberPart = num  Convert.ToDouble(wholeNumberPart); while (t < maxIterations && Math.Abs(n / d[t]  num) > epsilon) { t++; z = 1 / (z  (int)z); d[t] = d[t  1] * (int)z + d[t  2]; n = (int)(decimalNumberPart * d[t] + 0.5); } return string.Format((wholeNumberPart > 0 ? wholeNumberPart.ToString() + " " : "") + "{0}/{1}", n.ToString(), d[t].ToString() ); }
in excel the answer is "27 417/796" but i am not geting the result.
for 40.1242236024845 i have to get "40 20/161"
kindly help me..
Answers

using System; using System.Collections.Generic; using System.Linq; public class Program { public static void Main() { Func<double,int,string>d2s=(nmbr,mxDvsr)=> { var f=Math.Abs(nmbrMath.Truncate(nmbr)); if(f<=1.0/mxDvsr)return $"{nmbr}: NA"; var num=Math.Abs(nmbr); int i=(int)Math.Truncate(nmbr),d2=0,d1=1,d; do(d2,d1)=(d1,(d=d1*(int)(num=1/(num(int)num))+d2));while(Math.Abs(d)<mxDvsr); return$"{i}: {(int)(f*d2+0.5)}/{d2}"; }; const int maxDivisor=1_000; // const int maxDivisor=1_000_000; new List<double>{ 24.000228 ,24.052228 ,27.523869 ,40.124223 ,40.1242236024845 } .ForEach(d=>Console.WriteLine($"{d}\n\t\t{d2s(d,maxDivisor)}")) ; } } /* The output for maxDivisor=1_000 24.000228 24.000228: NA 24.052228 24: 34/651 27.523869 27: 417/796 40.124223 40: 20/161 40.1242236024845 40: 20/161 The output for maxDivisor=1_000_000 24.000228 24: 57/250000 24.052228 24: 13057/250000 27.523869 27: 111988/213771 40.124223 40: 15368/123713 40.1242236024845 40: 20/161 */
Do you see any inconsistency?
Notice how small the code is...
Don't bother with the format; just copy and paste into an advanced IDE&Compiler.
•
 Edited by ritehere40Banned Thursday, July 26, 2018 12:28 AM some words missing
 Marked as answer by mann madhan1 Thursday, July 26, 2018 5:54 AM
Thursday, July 26, 2018 12:20 AM
All replies

Where did you get your algorithm? Excel doesn't allow arbitrary fractional conversions. Beyond some standard numbers it only goes to 3 digits of fractions. This site is useful for coming up with math formulas and it provides calculators as well. Part of this depends upon whether you want accurate vs approximate. Accurate is good in some cases but approximates generally look better. In your scenario the fractions you are coming up with evaluate to the correct decimals. So what issue are you having?
Michael Taylor http://www.michaeltaylorp3.net

A different approach which seems to work well. I am not sure quite how many digits it will handle, but it seems to be quite a few.
I have not clue about performance....
public static string DoubleToFraction(double num, int maximumNumberOfDecimalsToConsider) { int wholeNumberPart = (int)num; double decimalNumberPart = num  Convert.ToDouble(wholeNumberPart); long denominator = (long)Math.Pow(10, maximumNumberOfDecimalsToConsider); long numerator = (long)(decimalNumberPart * (double)denominator); var fraction = ReduceFraction(numerator, denominator); return string.Format("{0} : {1}/{2}", wholeNumberPart, fraction.Item1, fraction.Item2); } public static Tuple<long, long> ReduceFraction(long numerator, long denominator) { Tuple<long, long> numDen = new Tuple<long, long>(numerator, denominator); if (numerator % denominator == 0) { numDen = new Tuple<long, long>(1, denominator/numerator); } else { int maximumPossibleFactor = (int)Math.Min(Math.Sqrt(numerator), Math.Sqrt(denominator)); for (int possibleFactor = 2; possibleFactor <= maximumPossibleFactor; possibleFactor++) { if (numerator % possibleFactor == 0 && denominator % possibleFactor == 0) { numDen = ReduceFraction(numerator / possibleFactor, denominator / possibleFactor); } } } return numDen; }
Ethan
Ethan Strauss


Dear ethan,
MessageBox.Show(DoubleToFraction(27.523869,3));
your function is returning "27 : 523/1000"
27 : 523/1000 is the correct answer; its just that Ethan's submethod to reduce the fraction isn't working (though wouldn't make a difference in this case, since 523 is a prime number).
I changed Ethan's code by stealing a 'greatest common denominator' function and using that instead:
public static string DoubleToFraction(double num, int maximumNumberOfDecimalsToConsider) { int wholeNumberPart = (int)num; double decimalNumberPart = num  Convert.ToDouble(wholeNumberPart); long denominator = (long)Math.Pow(10, maximumNumberOfDecimalsToConsider); long numerator = (long)(decimalNumberPart * (double)denominator); long gcd; GreatestCommonD(ref numerator, ref denominator, out gcd); return string.Format("{0} : {1}/{2}", wholeNumberPart, numerator, denominator); } static void GreatestCommonD(ref long Numerator, ref long Denominator, out long greatestCommonD) { greatestCommonD = 0; for (int x = 1; x <= Denominator; x++) { if ((Numerator % x == 0) && (Denominator % x == 0)) greatestCommonD = x; } if (greatestCommonD == 0) { return; } else { Numerator = Numerator / greatestCommonD; Denominator = Denominator / greatestCommonD; } }
 Edited by RJP1973 Tuesday, July 24, 2018 8:07 AM


Dear RJP,
In excel the answer is "27 417/796" but the function is returning "27 : 523/1000". what fumula Microsoft excel is using.
That is good question and one I cannot immediately answer (but I will continue to ponder it).
If you actually calculate 417/796 you get 0.52386934673366834170854271356784 (to the limits of Calc). Which is obviously not your input of 0.523869.
My guess is its giving you the lowest fraction it can while approximating the input to a certain point, rather than giving you the fraction that exactly equals your input but has a larger numerator.
As an aside, to explain the results myself and others have posted here (if you're not sure how our results come about), then consider
 0.5 ≡ 5/10, reducible to 1/2
 0.52 ≡ 52/100, reducible to 13/25
 0.523 ≡ 523/1000, not reducible as 523 is prime.
 Edited by RJP1973 Tuesday, July 24, 2018 11:52 AM


Hi,
I think that the algorithm you need will really depend on how you will handle rounding issues.
Note that my algorithm when called as
DoubleToFraction(27.523869, 6);
returns 27 : 523869/1000000 which is exactly the input. It can get arbitrarily close (to many digits) to any input.
Why do you need a fraction? How exact does the value need to be? If the goal is to mimic Excel, then the question is: What algorithm does Excel use? If that's what you need to know, an Excel forum is probably the best place to ask.
Ethan
ps. RJP. My reduce fraction function is working for me. Can you describe how it is breaking for you?
Ethan Strauss




By my calculation (using Excel)
24 13057/250000= 24.0522280000000
24 34/651 = 24.0522273425499...
These numbers are almost the same, but my calculation is exactly equal to your input, but the answer you report from Excel is off by about 0.0000007.
I am not clear on what the issue is. Is this difference between values too large?
Ethan
Ethan Strauss