Преобразование текстовой части в десятичную

Похоже на этот вопрос только на С# вместо JavaScript. Я не мог найти ничего для С# при поиске

У меня есть текстовое поле, которое будет принимать количество, которое позже будет храниться как double в базе данных. Однако возможно, что некоторые количества будут введены в виде струнных фракций, например 1/2 для 0,5. Я хочу, чтобы иметь возможность конвертировать их в десятичные числа, прежде чем хранить их в базе данных (возможность конвертировать назад было бы неплохо, но не обязательно). Я хочу иметь возможность обрабатывать как фракции, так и смешанные числа, например. 2 1/2 сохраняется как 2,5

Кто-нибудь знает способ сделать это?

Ответы

Ответ 1

Попробуйте разбить его на пробел и слэш, например:

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.");
}

Эй, это сработало! Не забудьте также проверить деление на ноль. В результате вы получите Infinity, -Infinity или NaN.

Ответ 2

И вот еще одно решение, но с чуть более бесшовной интеграцией:

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;
    }
}

И поскольку он реализует неявный оператор, его можно использовать просто:

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

Все, что не может быть проанализировано, возвращает двойную константу Double.NaN. Не входя в список возможных входов, это работало с некоторыми основами. Не стесняйтесь настраивать класс в соответствии с вашими потребностями.

Ответ 3

Разделите строку на "/", затем разделите два числа.

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();
}

Ответ 4

Вы можете попробовать что-то вроде этого: http://csharpeval.codeplex.com/ или это: https://github.com/Giorgi/Math-Expression-Evaluator

Обе библиотеки представляют собой полные математические выражения, написанные на С#. Они, вероятно, слишком переполнены для вашего случая использования, но стоит упомянуть в пользу других.

Ответ 5

decimal re = (decimal)1/7;

работает для меня.