21

Similar to this question just in C# instead of JavaScript. I couldn't find anything for C# while searching

I have a text box that will take a quantity, which is later stored as a double in a database. However it is possible that some quantities will be entered as string fractions e.g 1/2 for 0.5. I want to be able to convert these to decimal before storing them to the database (being able to also convert back would be nice but not necessary). I want to be able to handle both fractions and mixed numbers e.g. 2 1/2 is saved as 2.5

Anybody know a way of doing this?

Community
  • 1
  • 1
J.B
  • 1,642
  • 2
  • 15
  • 33

5 Answers5

21

Try splitting it on the space and slash, something like:

double FractionToDouble(string fraction) {
    double result;

    if(double.TryParse(fraction, out result)) {
        return result;
    }

    string[] split = fraction.Split(new char[] { ' ', '/' });

    if(split.Length == 2 || split.Length == 3) {
        int a, b;

        if(int.TryParse(split[0], out a) && int.TryParse(split[1], out b)) {
            if(split.Length == 2) {
                return (double)a / b;
            }

            int c;

            if(int.TryParse(split[2], out c)) {
                return a + (double)b / c;
            }
        }
    }

    throw new FormatException("Not a valid fraction.");
}

Hey, it worked! Remember to check for a division by zero, too. You'll get Infinity, -Infinity, or NaN as a result.

Ry-
  • 218,210
  • 55
  • 464
  • 476
  • 2
    Thank you very much! Just implemented this into my app and it works perfectly. – J.B Dec 16 '12 at 18:09
  • Why do we need to use a delimiter ' ' (the space)? @U2744 SNOWFLAKE – Don Larynx Dec 30 '14 at 18:26
  • Also doesn't simply using the following line work? it outputs correctly. double frac = (double)1/8; – Don Larynx Dec 30 '14 at 18:32
  • @DonLarynx: This is a function to parse a string (e.g. user input). You wouldn’t use it as a constant expression in your program. The space delimiter is for mixed fractions, e.g. `1 1/2`. – Ry- Dec 30 '14 at 20:16
9

And here is yet one more solution, but with a bit more seamless an integration:

public class FractionalNumber
{
    public Double Result
    {
        get { return this.result; }
        private set { this.result = value; }
    }
    private Double result;

    public FractionalNumber(String input)
    {
        this.Result = this.Parse(input);
    }

    private Double Parse(String input)
    {
        input = (input ?? String.Empty).Trim();
        if (String.IsNullOrEmpty(input))
        {
            throw new ArgumentNullException("input");
        }

        // standard decimal number (e.g. 1.125)
        if (input.IndexOf('.') != -1 || (input.IndexOf(' ') == -1 && input.IndexOf('/') == -1 && input.IndexOf('\\') == -1))
        {
            Double result;
            if (Double.TryParse(input, out result))
            {
                return result;
            }
        }

        String[] parts = input.Split(new[] { ' ', '/', '\\' }, StringSplitOptions.RemoveEmptyEntries);

        // stand-off fractional (e.g. 7/8)
        if (input.IndexOf(' ') == -1 && parts.Length == 2)
        {
            Double num, den;
            if (Double.TryParse(parts[0], out num) && Double.TryParse(parts[1], out den))
            {
                return num / den;
            }
        }

        // Number and fraction (e.g. 2 1/2)
        if (parts.Length == 3)
        {
            Double whole, num, den;
            if (Double.TryParse(parts[0], out whole) && Double.TryParse(parts[1], out num) && Double.TryParse(parts[2], out den))
            {
                return whole + (num / den);
            }
        }

        // Bogus / unable to parse
        return Double.NaN;
    }

    public override string ToString()
    {
        return this.Result.ToString();
    }

    public static implicit operator Double(FractionalNumber number)
    {
        return number.Result;
    }
}

And because it implements the implicit operator, it can be used simply by:

Double number = new FractionalNumber("3 1/2");

Anything that can't be parsed returns the Double constant Double.NaN. Without getting in to a laundry list of possible inputs, this worked with some basics. Feel free to tweak the class to fit your needs.

Brad Christie
  • 100,477
  • 16
  • 156
  • 200
1

Split the string on the "/" then divide the two numbers.

public float FractionToDecimal(String input)
{
    String[] fraction = input.Split(new[] { "/" }, StringSplitOptions.RemoveEmptyEntries);
    if (fraction.Length != 2)
    {
        throw new ArgumentOutOfRangeException();
    }
    Int32 numerator, denominator;
    if (Int32.TryParse(fraction[0], out numerator) && Int32.TryParse(fraction[1], out denominator))
    {
        if (denominator == 0)
        {
            throw new InvalidOperationException("Divide by 0 occurred");
        }
        return (float)numerator / denominator;
    }
    throw new ArgumentException();
}
Ian R. O'Brien
  • 6,682
  • 9
  • 45
  • 73
1

You might try something like this: http://csharpeval.codeplex.com/ or this: https://github.com/Giorgi/Math-Expression-Evaluator

Both libraries are full mathematical expression evaluators written in C#. They're probably overkill for your use case, but worth mentioning for the benefit of others.

Roy Tinker
  • 10,044
  • 4
  • 41
  • 58
-2
decimal re = (decimal)1/7;

works for me.

Garo Yeriazarian
  • 2,533
  • 18
  • 29
Don Larynx
  • 685
  • 5
  • 15
  • 1
    The compiler can do this because those are numeric literals, and the `/` forms a math expression. `(decimal)"1/7"` will fail miserably. – BradleyDotNET Dec 30 '14 at 19:59
  • That's true. I just ignored "text" in text fraction, I apologize. Run the function "fractiontodouble" by another user, first, but alter it so it's fractiontodecimal. – Don Larynx Dec 30 '14 at 21:02