Seite 1 von 1
Funktion als String - ausrechnen
Verfasst: Donnerstag 26. September 2013, 21:36
von meister56
Hallo in die Runde,
also ich hab folgendes Problem:
Gegeben sind Funktionen als String z.B. "t=1/(b^3)*(ln(y/x–a^2*x^2/(2*y^2)))" oder "t=cos(bx+0,5)*sin(y/x–a^0,5*x^2)" und man soll diese dann verändern/Werte einsetzen und das Ergebnis (t=...) ausgeben lassen können. Also verändern und und einsetzen hab ich ohne Probleme hinbekommen, nun aber das berechnen... Dachte einfach die jeweiligen Zeichen (also "^" z.B. in "**") ersetzen und dann mit eval(string) --> das Ergebnis zu bekommen. Das scheitert jedoch anscheinend an den ln() oder den Trigonometrischen Funktionen...
Kann mir da jemand einen Ansatz geben? Oder Eine einfache Idee?.....Einen eigenen Parser hierfür wäre irgendwie zu aufwändig! Muss doch auch was einfaches geben!
Grüße
Re: Funktion als String - ausrechnen
Verfasst: Donnerstag 26. September 2013, 21:54
von BlackJack
@meister56: Schau Dir mal `sympy` an, damit sollte das gehen. Die ^ brauchst Du nicht einmal ersetzen, aber die – sind keine Minuszeichen sondern „en dash”-Zeichen. Und die '0,5' sollte man durch '(1/2)' ersetzen. Und 'bx' ist *ein* Name oder *zwei* mit einer impliziten Multiplikation?
Edit: Ansonsten wenn Du mit dem „evil” `eval()` arbeiten willst, kannst Du da noch optionale Argumente angeben. Zum Beispiel ein Wörterbuch mit den Funktionen die verwendet werden dürfen, und nicht ganz unwichtig den Schlüssel '__builtins__' der zum Beispiel auf den Wert `None` abgebildet wird, damit die eingebauten Funktionen *nicht* so einfach zur Verfügung stehen.
Re: Funktion als String - ausrechnen
Verfasst: Donnerstag 26. September 2013, 22:24
von meister56
danke erstmal für die schnelle antwort!!!!!
also die lösung mit sympy scheint mir auf den ersten blick gut, müsste mich da aber glaub ich einarbeiten bevor man damit vernünftig was anfangen kann...:/ außerdem zusätzlich installieren oder?!
was hat es genau mit den builtins auf sich?...
also wenn ich dann folgenden String habe: "cos(bx+0,5)*sin(y/x–a^0,5*x^2)" ihn dann so umwandle --> "cos(b*x+(1/2))*sin(y/x–a**(1/2)*x**2)" ...was wäre der nächste schritt?
Re: Funktion als String - ausrechnen
Verfasst: Donnerstag 26. September 2013, 22:39
von EyDu
Die kurze Einarbeitung mit Sympy solltest du auf dich nehmen, das ist die einfachste und flexibelste Lösung. Eigentlich brauchst du auch nicht mehr als das hier:
Code: Alles auswählen
>>> from sympy.parsing.sympy_parser import parse_expr
>>> expression = parse_expr("sin(x)*cos(x)")
>>> float(expression.evalf(subs={"x":2}))
-0.3784012476539641
Re: Funktion als String - ausrechnen
Verfasst: Donnerstag 26. September 2013, 22:41
von BlackJack
@meister56: Du hast die zweite '0,5' und das Minuszeichen vergessen und die '^' musst Du wie gesagt nicht ersetzen, die versteht der Parser von `sympy`.
Danach kannst Du zum Beispiel mit der `subs()`-Methode die Variablen durch Werte ersetzen. Und von dem Ergebnis, was in diesem Fall immer noch symbolisch ist, den Gleitkommawert mit der `float()`-Funktion ausrechnen lassen:
Code: Alles auswählen
In [39]: ex = sympy.sympify('cos(b*x+(1/2))*sin(y/x-a^(1/2)*x^2)')
In [40]: ex
Out[40]: -sin(a**(1/2)*x**2 - y/x)*cos(b*x + 1/2)
In [41]: sympy.pprint(ex)
⎛ ⎽⎽⎽ 2 y⎞
-sin⎜╲╱ a ⋅x - ─⎟⋅cos(b⋅x + 1/2)
⎝ x⎠
In [42]: ex.subs({'a': 1, 'b': 2, 'x': 3, 'y': 4})
Out[42]: -sin(23/3)*cos(13/2)
In [43]: float(ex.subs({'a': 1, 'b': 2, 'x': 3, 'y': 4}))
Out[43]: -0.9595049469523168
Die „builtins” sind die eingebauten Funktionen, also alles was man so zur Verfügung hat ohne dass man etwas importieren muss. Und bei `eval()` stehen die normalerweise auch zur Verfügung, so dass dort auch ”Formeln” wie '__import__("os").system("rm - rf ~/")' ”ausgerechnet” werden.
Re: Funktion als String - ausrechnen
Verfasst: Donnerstag 26. September 2013, 23:10
von meister56
Danke, glaube ich habs jetzt!^^