الإجابة 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);
    }