DIGITAL
Letzte Änderung: 01. February 2021, 17:11 Uhr
Letzte Änderung: 01. February 2021, 17:11 Uhr
keine Punkte — im Detail
Im verlinkten Exkurs gibt es einen kurzen Überblick über Grammatiken für formale Sprachen und Compilerbau.
Für die Aufgabe ist es nicht unbedingt nötig, alles durchzuarbeiten — es hilft aber dabei, die Prinzipien hinter den Aufgaben besser zu verstehen.
Worum geht's?
Das ganze Aufgabenblatt beschäftigt sich damit, mathematische Ausdrücke zu manipulieren. Dazu müssen wir diese erstmal in den Rechner bringen.
Wie in der Vorlesung (zu Lehreinheit 8) erklärt, sind Ausdrücke eigentlich Bäume von Operatoren. Dies ist aber relativ schwierig direkt einzugeben (man bräuchte ein komplexes GUI, und die Interaktion wäre immer noch mühsam, wenn man sich nicht eine sehr raffinierte Schnittstelle überlegt). Daher ist es sinnvoll, mathematische Ausdrücke zunächst in linearisierter Form, als einfache Zeichenketten zu repräsentieren. Die Aufgaben, aus einer solchen, linearisierten Kodierung wieder einen Baum zu rekonstruieren, ist in der Informatik als „Parsing“ bekannt. Der Formalismus dahinter ist als kontextfreie Grammatiken/Sprachen bekannt: In jeden Operator im Baum kann man beliebig komplexe, zusammengesetzte Unteroperatoren einsetzen (Teilbäume).
Da es vergleichsweise schwierig ist, "normale" mathematische Ausdrücke mit Klammerung in einen Syntaxbaum zu überführen, gehen wir in dieser Aufgabe von der sogenannten "Umgekehrten Polnischen Notation" aus.
Implementierung des Parsers:
Die praktische Aufgabe besteht nun darin den zuvor selbst hergeleiteten Algorithmus zu einer der oben aufgelisteten Syntaxen zu implementieren.
Anforderungen:
README.md
. 1
, 42
oder 1337
)+
, -
(unär und binär), *
, /
und ^
(potenzieren)x
, y
, a
, b
, ...)sin
, cos
, exp
und log
123.456789
sin
oder mod
erlauben, die auch aus mehr als nur einem Zeichen bestehen. +
,*
,-
), Funktionsnamen (sin
, cos
), Klammern und Variablennamen. Whitespaces (Leerzeichen, Tabs, returns) trennen die Tokens — in der Liste tauchen diese nicht mehr explizit auf. Tokens können aber auch anders getrennt sein (z.B. möchte man, dass in allgemeinen mathematischen Ausdrücken auch 3+4
, also ohne Whitespaces, drei Tokens ergibt).sin a
) als func Dummyoperator Eingabe
auffassen. Indem wir den Dummyoperator schon mit in die Operatorliste nehmen können wir sogar festlegen, wie z.B. ein Ausdruck der Form sin a\textasciicircum 3
übersetzt wird.// string containing the number
string Text = "456";
//number which will contain the result
int Result;
// stringstream used for the conversion constructed with the contents of 'Text'
// ie: the stream will start containing the characters of 'Text'
istringstream convert(Text);
//give the value to 'Result' using the characters in the stream
//if that fails set 'Result' to 0
if ( !(convert >> Result) )
Result = 0;
//'Result' now equal to 456
to_string
, die eine Repräsentative Zeichenkette für die (Teil-)Bäume und Objekte zurückgibt. Es muss dabei nicht exakt die gleiche Zeichenkette enstehen, wie die, die eingegeben wurde. Beispielsweise kann sich die neue bis auf Leerzeichen und Klammerungen unterscheiden. Was jedoch der Fall sein sollte ist, dass diese String-Repräsentation selbst wieder einlesbar ist. Insbesondere gilt dann für jede valide Zeichenkette Expression(Expression(str).to_string()).to_string() == Expression(str).to_string()
Expression(Expression(str).to_string()).to_string() == Expression(str).to_string()
to_string
-Funktionalität gestalten. Noch wissen die Operatorobjekte jedoch nicht, was das Operatortoken eigentlich tut. Übergeben Sie zum Beispiel der Operatordefinition zusätzlich einen Lamba-Ausdruck, der zwei Eingaben erhält und den Operator auf diese beiden anwendet. Implementieren eine Funktion deriv
, die die Ableitung einer einfachen Funktion in gegebenen Variable (z.B. \(x\)) berechnet. Als Operatoren sollen Addition, Subtraktion, Multiplikation und die Funktionen \(\sin(x),\cos(x),\exp(x),\log(x)\) unterstützt werden
Hinweise:
Zum Schluss brauchen wir unbedingt noch etwas hübsche Graphik (Eye Candy muß sein!).
Erstellen Sie eine GUI, bei der der User in einem Textfeld einen mathematischen Ausdruck in einer Variable (x) eingeben kann. Der eingegebene Ausdruck soll dann zusammen mit der passenden Ableitung in der GUI geplottet werden.