Laden...

Polynomkoeffizienten aus string in double[] parsen

Erstellt von ThavalUga vor einem Jahr Letzter Beitrag vor einem Jahr 293 Views
T
ThavalUga Themenstarter:in
2 Beiträge seit 2022
vor einem Jahr
Polynomkoeffizienten aus string in double[] parsen

Hallo liebe Community,
Ich habe folgende Frage, und zwar möchte ich aus einer Benutzereingabe eines Polynoms ein Array mit den Koeffizienten machen. Also z.B. aus string input = "3x4+2x3-x^2+x-5" in ein Array double[] coefficients = {3, 2, -1, 1, -5} , leider werde ich aus online Recherchen nicht schlau daraus und ich komme nicht von alleine darauf wie ich das umsetzten kann.

MfG
Thaval

3.825 Beiträge seit 2006
vor einem Jahr

Selber einen Parser bauen, dazu brauchst Du Split(), SubString() und Double.Parse().

Oder Regex benutzen.

Grüße Bernd

Workshop : Datenbanken mit ADO.NET
Xamarin Mobile App : Finderwille Einsatz App
Unternehmenssoftware : Quasar-3

6.911 Beiträge seit 2009
vor einem Jahr

Hallo ThavalUga,

die Zeichenkette muss geparst werden, dabei gehts am einfachsten mit [Artikel] Regex-Tutorial, wie z.B. ^([+-]?(?:\d+)?)(x(?:\^(\d+))?)?. Wenn du damit nicht vertraut bist, so schauts schrecklich aus, aber wenn das selbst geschrieben wird gehts recht einfach, da für jede "Gruppe" die benötigt wird ein "Block" dasteht.

Schau dir mal im Code die Methode GetPolynomCoefficients an. Dort wird per Regex ein Term gematched, dieser dann geparst und die Eingabe um diesen Term verkürzt. Mit den restlichen Termen gehts dann so weiter, bis letztlich nichts mehr übrig ist.


using System.Text.RegularExpressions;

string input = "3x^4+2x^3-x^2+x-5";

double[] coefficients = GetPolynomCoefficients(input)
    .OrderByDescending(t => t.Power)
    .Select(t => t.Coefficient)
    .ToArray();

Console.WriteLine(input);
for (int i = 0; i < coefficients.Length; ++i)
{
    double c = coefficients[i];
    Console.Write($"{(Math.Sign(c) >= 0 ? "+" : "-")}{Math.Abs(c)}");

    if (i < coefficients.Length - 2)
    {
        Console.Write($"x^{coefficients.Length - 1 - i}");
    }
    else if (i < coefficients.Length - 1)
    {
        Console.Write("x");
    }
}
Console.WriteLine();

static IEnumerable<Term> GetPolynomCoefficients(string input)
{
    // language=regex
    const string Pattern = @"^([+-]?(?:\d+)?)(x(?:\^(\d+))?)?";

    while (input.Length > 0)
    {
        Match match = Regex.Match(input, Pattern);

        if (!match.Success)
        {
            throw new Exception("Given polynom can't be parsed. Bla bla bla (more info about failure and how to recover)");
        }

        if (!TryGetCoefficient(match, out double coefficient))
        {
            throw new Exception("... (something like 'coefficient can't be parsed at index ...')");
        }

        if (!TryGetPower(match, out int power))
        {
            throw new Exception("... (something like 'power can't be parsed at index ...')");
        }

        yield return new Term(coefficient, power);

        input = input[match.Length..];
    }

    static bool TryGetCoefficient(Match match, out double coefficient)
    {
        string value = match.Groups[1].Value;

        if (value.Length == 0 || value == "+")
        {
            coefficient = 1d;
            return true;
        }

        if (value == "-")
        {
            coefficient = -1d;
            return true;
        }

        return double.TryParse(value, out coefficient);
    }

    static bool TryGetPower(Match match, out int power)
    {
        string value = match.Groups[3].Value;

        if (value.Length == 0)
        {
            if (match.Groups[2].Value.Length == 0)
            {
                power = 0;
                return true;
            }

            if (match.Groups[2].Value == "x")
            {
                power = 1;
                return true;
            }
        }

        return int.TryParse(value, out power);
    }
}

public readonly record struct Term(double Coefficient, int Power);

Ohne Regex ginge es auch, aber aufgrund der Sonderfälle wie implizit {+1, -1} als Koeffizient wird schon umständlicher. Genauso wenn die Potenz implizit {1, 0} ist.
D.h. ohne Regex würde eine Art Syntax-Baum benötigt werden und das ist wohl Overkill. BTW: das Regex-Match kann hier als Art "Mini-Syntax-Baum" gesehen werden.

mfG Gü

Stellt fachliche Fragen bitte im Forum, damit von den Antworten alle profitieren. Daher beantworte ich solche Fragen nicht per PM.

"Alle sagten, das geht nicht! Dann kam einer, der wusste das nicht - und hat's gemacht!"

T
ThavalUga Themenstarter:in
2 Beiträge seit 2022
vor einem Jahr

Dankeschön für eure Antworten, damit kann ich weitermachen.