Mathematische Formel zusammensetzen

  • Allgemein

Es gibt 6 Antworten in diesem Thema. Der letzte Beitrag () ist von ErfinderDesRades.

    Mathematische Formel zusammensetzen

    Hallo,
    ich würde gerne eine mathematische Formel aus Variablen zusammensetzen. Wichtig wäre mir dabei ein variabler Operator.

    Also statt
    1+2=3

    Möchte ich haben
    Zahl1 Operator Zahl2 = Zahl3

    Aber wie löse ich so was in VB?
    Ich weiß nicht, ob es das ist was du brauchst, aber hier ist ein kleiner Ausschnitt aus einem meiner Projekte um die Stelle innerhalb eines Strings festzustellen wo der Operator ist:

    Du formst deine Formel mit myFormel.toArray() in ein Array of Char um. Dann gehst du jetzt mit einer Forschleife jeden einzelnen Buchstaben durch und guckst ob es ein Operator ist.
    Pseudo:

    Quellcode

    1. For i as Integer = 0 to myCharArray.Count
    2. if charisoperator(myCharArray) = True then
    3. 'i ist jetzt die Stelle wo in deinem String der Operator steht
    4. end if
    5. next


    Mit dieser Funktion kann man herausfinden, ob ein Char ein Operator ist:

    VB.NET-Quellcode

    1. Private Function CharIsOperator(testChar As Char) As Boolean
    2. Select Case testChar
    3. Case "+"C, "-"C, "*"C, "/"C, "^"C
    4. Return True
    5. Case Else
    6. Return False
    7. End Select
    8. End Function

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Telcrome“ ()

    Hi
    soll das zur Ausführungszeit ausgewertet werden? Dann wäre das so möglich:
    Gruppiere einfach Buchstaben nach gewissen Regeln. So z.B.
    - Operatoren bestehen aus +, -, *, /, %, |, &, =, :
    - Namen bestehen aus (Letter|'_') (LetterOrDigit|'_')
    - Zahlen bestehen aus Digit
    - Leerzeichen dienen als Trennzeichen innerhalb von Gruppen, d.h. z.B. a b sind zwei Gruppen vom Typ Name.
    Anschließend gehst du den String mit einer Variablen i (For i = 0 To str.Length -1) und setzt einen Marker an die Position, an der das erste nicht-Leerzeichen (char.IsWhitespace) ist. Der Marker gibt dir immer den Start einer Gruppe an und sobald die Gruppe wechselt, wird ein Token generiert. Das Token modellierst du als Klasse mit einer String-Variable und ggf. auch der zugehörigen Gruppe. Beim Gruppenwechsel setzt du den Marker an die Position des letzten Buchstaben. Leerzeichengruppen werden je nach Syntaxdefinition gesondert behandelt.
    Hier mal ein Beispiel:
    " 1+-21=3" - der Marker ist ursprünglich an Position 0, i läuft bis 4 durch und entfernt die Leerzeichen-Gruppe (wird ja übersprungen). Setze Marker auf die 1
    "1+-21=3" - i läuft bis zum + und hängt die Zahlen-Gruppe "1" als Token an eine Liste der Tokens an. Setze Marker auf das +.
    "+-21=3" - i läuft bis zum - und hängt die Operator-Gruppe + an. Operatoren werden halt bereits gesondert ausgewertet. Marker steht eben auf -
    "-21=3" - i läuft bis zur 2, hängt - an, Marker steht auf 2
    "21=3" - i läuft bis zum =, hängt 21-Token an, Marker steht auf =
    "=3" - i läuft bis zur 3, hängt =-Token an, Marker steht auf 3
    "3" - i läuft bis zum Ende, hängt 3-Token an, Marker steht aum Ende
    "" - Fertig
    Der Marker dient dir einfach als Zwischenspeicher für den Tokenanfang. Damit kannst du dann eben einfach str.Substring(marker, i - marker) verwenden, um ein Token aus dem String zu extrahieren.
    Sobald du die Liste der Tokens hast, gehst du alle Tokens durch und überprüfst deren syntaktischen Aufbau auf Korrektheit (z.B. "a+b+)", "=3" sind syntaktisch nicht korrekt). Da musst du eben Regeln aufstellen:
    <expression> := <expression> <binop> <expression> | <unop> <expression> | (<expression>) | <number> | <variable> | <function> <expression>
    <name> := <namestartchar> <namechar>
    <namestartchar> := <letter> | '_'
    <namechar> := <namestartchar> | <digit>
    <binop> := +|-|*|/|%|&| | |
    <unop> := +|-
    (ja, das sind keine korrekten Regex-Ausdrücke, aber dann wären sie kompletter brainfuck)
    usw.
    Diese Regeln sollten teilweise schon vom Tokenizer beachtet werden. Was dasteht sind einfach syntaktische Regeln, die einzuhalten sind. Z.B. <name>, <number>, <unop> bzw. <binop> sind bereits vom Tokenizer ermittelt worden. Die Zuordnung der Operatoren übernimmt dann allerdings explizit noch mal die syntaktische Analyse. Nachdem die syntaktische Analyse fertig ist, sollte ein korrekter Syntaxbaum vorhanden sein. Im nächsten Schritt ordnest du die die Operatoren nach Präzedenz, löst Funktions-und Variablennamen auf (Punkt-Vor-Strich, unäre Operatoren vor binären, etc.) und überprüfst im nachfolgenden Schritt darauf, ob die Typen zueinander passen. Den Schritt kannst du ggf. auslassen, wenn du eh nur auf Teilmengen der reellen Zahlen operierst.

    Achja: binäre Operatoren sind Operatoren zwischen zwei Ausdrücken, z.B. a + b, 1 + 3, (1*2)+3, unäre sind auf einem Ausdruck, z.B. -3, -a.

    Ansonsten könntest du, wenn es nicht zur Laufzeit ausgewertet werden soll, auf jeden Fall entweder einen Delegaten oder eine Klasse definieren, die dir die Auswertung übernimmt. Wenn es keine primitiven Datentypen sind, kannst du auch direkt über op_Addition, etc. auf die Operatoren zugreifen und sie somit als Delegaten verwenden.

    Gruß
    ~blaze~
    Hm, da habe ich mich wohl falsch ausgedrückt. Mir ist der Operator bekannt. Das Programm liefert per Zufallsgenerator 3 Variablen: die beiden Zahlen und den Operator. Aber wie setze ich diese 3 Variablen zu einer Formel zusammen, damit sie berechnet werden kann?

    Ich könnt natürlich folgendes machen:

    Quellcode

    1. if operator1="+" then
    2. Ergebnis=Zahl1 + Zahl2
    3. elseif operator1="-" then
    4. Ergebnis=Zahl1 - Zahl2
    5. end if

    Aber das muss doch auch irgendwie anders gehen. Ohne if oder case.

    tolox schrieb:

    Ohne if oder case.
    Nö, geht nicht.
    Aber Du kannst Dir ein Enum für alle Operatoren anlegen, dazu ein Dictionary(Of String, OperatorEnum), da kannst Du mit den Enum-Werten arbeiten, das ist effizienter und leichter debug-bar als Operatoren in String-Form.
    Außerdem weißt Du bereits beim Zugriff auf das Dictionary, ob ein Operator existiert oder nicht.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!