Pytanie Konwertuj ułamek tekstu na liczbę dziesiętną


Podobny do to pytanie tylko w C # zamiast JavaScript. Podczas wyszukiwania nie mogłem znaleźć nic dla C #

Mam pole tekstowe, które zajmie pewną ilość, która później jest przechowywana jako podwójne w bazie danych. Jednak możliwe jest, że niektóre wielkości zostaną wprowadzone jako frakcje ciągowe, np. 1/2 dla 0,5. Chcę móc przekonwertować je na wartości dziesiętne przed zapisaniem ich w bazie danych (możliwość konwersji również byłaby dobra, ale nie konieczna). Chcę być w stanie obsłużyć zarówno ułamki, jak i liczby mieszane, np. 2 1/2 zostaje zapisane jako 2,5

Ktoś wie, jak to zrobić?


16
2017-12-16 17:17


pochodzenie


Wrzuciłbym go do biblioteki parsującej, która szuka podobieństw, takich jak spacje, / i tak dalej Int32.Parse i zwróć wynik. - Brad Christie
codeproject.com/Articles/9078/Fraction-class-in-C - Chris Sinclair


Odpowiedzi:


Spróbuj podzielić go na przestrzeń i ukośnik, coś takiego:

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

Hej, zadziałało! Pamiętaj, aby sprawdzić także podział na zero. W rezultacie otrzymasz Infinity, -Infinity lub NaN.


12
2017-12-16 17:23



Dziękuję Ci bardzo! Właśnie zaimplementowałem to w mojej aplikacji i działa idealnie. - J.B
Dlaczego potrzebujemy ogranicznika "" (przestrzeń)? @ U2744 SNOWFLAKE - Don Larynx
Czy nie jest to po prostu użycie poniższej linii? wyświetla się poprawnie. podwójny frac = (podwójny) 1/8; - Don Larynx
@DonLarynx: Jest to funkcja do analizowania łańcucha znaków (np. Danych wprowadzanych przez użytkownika). Nie używałbyś tego jako stałego wyrażenia w swoim programie. Ogranicznik przestrzeni dotyczy mieszanych frakcji, np. 1 1/2. - Ry-♦


I tu jest jeszcze jedno rozwiązanie, ale z nieco więcej bezproblemowa integracja:

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

A ponieważ implementuje niejawny operator, może być używany po prostu przez:

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

Cokolwiek, czego nie można przeanalizować, zwraca stałą Double Double.NaN. Bez wchodzenia na listę możliwych wejść, to działało z pewnymi podstawami. Nie krępuj się, aby dostosować klasę do swoich potrzeb.


7
2017-12-16 17:58





Podziel łańcuch na "/", a następnie podziel dwie liczby.

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

1
2017-12-16 17:19





Możesz spróbować czegoś takiego: http://csharpeval.codeplex.com/ albo to: https://github.com/Giorgi/Math-Expression-Evaluator

Obie biblioteki są pełnymi matematycznymi oceniającymi wyrażenia napisane w języku C #. Prawdopodobnie są one przesadą dla twojego przypadku użycia, ale warto wspomnieć o korzyściach dla innych.


1
2017-12-03 05:45





decimal re = (decimal)1/7;

pracuje dla mnie.


-2
2017-12-30 18:49



Kompilator może to zrobić, ponieważ są to literały liczbowe i / tworzy wyrażenie matematyczne. (decimal)"1/7" zawiodą nieszczęśliwie. - BradleyDotNET
To prawda. Po prostu zignorowałem "tekst" we frakcji tekstowej, przepraszam. Uruchom najpierw funkcję "fractiontodouble" przez innego użytkownika, ale zmień ją tak, aby była frakcyjno-dziesiętna. - Don Larynx