Input von mathm. Funktion

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
kaykay
User
Beiträge: 5
Registriert: Mittwoch 24. September 2014, 13:15

Hallo,

Ich bin dabei Python zu lernen und komme nicht ganz auf die Lösung meines folgenden Problems:

Ich will durch die Eingabe einer mathematischen Funktion mit einer Variablen weiter arbeiten.

Dazu habe ich erstmal folgende Funktion definiert:

t = 2

Code: Alles auswählen

def f(x):
      global y
      y = eval(input("fkt: "))
     return y
Nun will ich mit dieser mathm. Funktion folgendes berechnen:
für ein festes t:
f(x+t) - f(x)

dazu habe ich dann eine weitere Funktion:

Code: Alles auswählen

def rec(f, x):
     z = f(x+t) - f(x)   
    return z

Code: Alles auswählen

for x in range(-3,4):
    print(rec(lambda x: f(x), x))
Nun ist mein Problem folgendes:

Ich muss jedes mal (also für jedes x) die mathm. Funktion 2 mal eingeben...

Was ich nun aber haben will:

Ich will die mathm. Funktion einmal eingeben, und dann soll mir das Programm für diese eine mathm. Funktion und für die x zwischen -3 und 3 die Werte z berechnen...

Hier ein Abbild meiner Situation:

Eingabe von Funktion
Eingabe von Funktion
berechnet mir z für das erste x
Eingabe von Funktion
Eingabe von Funktion
berechnet mir das z für das zweite x
...

etc.

Sollte aber sein:

Eingabe von Funktion
z1 für x1 etc.
z2
z3

Habt ihr Lösungsvorschläge? Achso: Python 3.4.1 unter Windows

MfG
Kai
BlackJack

@kaykay: Ich denke ich habe das Problem nicht verstanden, das ist alles etwas zu verwirrend beschrieben. Darum ist das einzige was mir als Antwort einfällt: Vergiss das es ``global`` und `eval()` gibt. Das sind in aller Regel keine Lösungen sondern Probleme.
kaykay
User
Beiträge: 5
Registriert: Mittwoch 24. September 2014, 13:15

BlackJack hat geschrieben:@kaykay: Ich denke ich habe das Problem nicht verstanden, das ist alles etwas zu verwirrend beschrieben. Darum ist das einzige was mir als Antwort einfällt: Vergiss das es ``global`` und `eval()` gibt. Das sind in aller Regel keine Lösungen sondern Probleme.

Okay, tut mir leid. Hier nochmal mein Problem:

Wenn ich den Code laufen lasse, bin ich gezwungen, für jedes x zwischen -3 und 3 (was auch immer x in range(a,b) ist) die mathem. Funktion 2 mal einzugeben.

Also nach dem Schema

fkt: (hier muss ich die fkt. eingeben)
fkt: (hier muss ich die fkt. eingeben)
(hier wird der 1. Wert für f(x+t) - f(x) angezeigt, also das Ergebnis für x = -3 (fängt ja bei -3 an, da range(-3,4))
fkt: (hier muss ich die fkt. eingeben)
fkt: (hier muss ich die fkt. eingeben)
(hier wird der 2. Wert für f(x+t) - f(x) angezeigt, also das Ergebnis für x = -2
und so weiter bis ich bei x = 3 angekommen bin.

Jedoch will ich, dass ich nur ein einziges mal die mathm. Funktion eingeben muss und der Code dann automatisch die Werte für x im Bereich -3,3 (f(x+t) - f(x)) berechnet.

Wenn eval und global nur Probleme bereiten, wie kann ich das sonst machen? Wenn ich das eval weglasse bei input von der funktion, wird dieser nur als String gelesen, und nicht als Funktion mit einer Variablen x an sich, oder? Mfg
Benutzeravatar
MagBen
User
Beiträge: 799
Registriert: Freitag 6. Juni 2014, 05:56
Wohnort: Bremen
Kontaktdaten:

Probier das mal:

Code: Alles auswählen

# Der Benutzer soll alle Funktionen aus math benutzen koennen.
from math import *

def read_f():
    # globals() wird uebergeben, damit der Benutzer alles math benutzen kann.
    return  eval(raw_input("fkt: "), globals())

def rec(f, x, t):
    return f(x+t) - f(x)

f = read_f()

t = 2 # warum auch immer
for x in range(-3,4):
    print "f(%f)=%f" % (x, rec(f,x,t))
Eingabe der Funktion "lambda x: x**2-1"

Code: Alles auswählen

fkt: lambda x: x**2-1
f(-3.000000)=-8.000000
f(-2.000000)=-4.000000
f(-1.000000)=0.000000
f(0.000000)=4.000000
f(1.000000)=8.000000
f(2.000000)=12.000000
f(3.000000)=16.000000
Eingabe der Funktion "lambda x: sin(pi*x/10.)"

Code: Alles auswählen

fkt: lambda x: sin(pi*x/10.)
f(-3.000000)=0.500000
f(-2.000000)=0.587785
f(-1.000000)=0.618034
f(0.000000)=0.587785
f(1.000000)=0.500000
f(2.000000)=0.363271
f(3.000000)=0.190983
a fool with a tool is still a fool, www.magben.de, YouTube
Benutzeravatar
MagBen
User
Beiträge: 799
Registriert: Freitag 6. Juni 2014, 05:56
Wohnort: Bremen
Kontaktdaten:

Die Ausgabe ist falsch formatiert, anstatt

Code: Alles auswählen

print "f(%f)=%f" % (x, rec(f,x,t))
sollte es besser

Code: Alles auswählen

print "rec(%f)=%f" % (x, rec(f,x,t))
sein.

Eingabe der Funktion "lambda x: x**2-1"

Code: Alles auswählen

fkt: lambda x: x**2-1
rec(-3.000000)=-8.000000
rec(-2.000000)=-4.000000
rec(-1.000000)=0.000000
rec(0.000000)=4.000000
rec(1.000000)=8.000000
rec(2.000000)=12.000000
rec(3.000000)=16.000000
a fool with a tool is still a fool, www.magben.de, YouTube
kaykay
User
Beiträge: 5
Registriert: Mittwoch 24. September 2014, 13:15

Vielen Dank!

Ich habe nun aus deinem Code das raw_input in input umgewandelt, da meines Wissens nach raw_input aus python 2.x das input in python 3.x ist.
Zudem habe ich bei print klammern hinzugefügt.

Edit: falsch geklammert, danke.

Zudem habe ich noch eine weitere Frage:

Gibt es eine Möglichkeit, dass ich bei der Eingabe im Shell das "lambda x:" weglassen kann, und das Ziel trotzdem erreicht wird?

MfG
Benutzeravatar
MagBen
User
Beiträge: 799
Registriert: Freitag 6. Juni 2014, 05:56
Wohnort: Bremen
Kontaktdaten:

OK, ich hab's mit Python 2.7 gemacht, print musst Du nun so schreiben (achte auf die Klammerung):

Code: Alles auswählen

print("rec(%f)=%f" % (x, rec(f,x,t)))
input("abc") macht in Python 2.7 das gleiche wie eval(raw_input("abc")), warum sollte das in Python 3 anders sein?
Bei Input kann man (in Python 2.7) keinen Kontext (wie z.B. globals()) übergeben. Den brauchst Du aber wenn Du dem Benutzer die Eingabe von "sin(2*pi*x)" ermöglichen willst.
kaykay hat geschrieben:Gibt es eine Möglichkeit, dass ich bei der Eingabe im Shell das "lambda x:" weglassen kann, und das Ziel trotzdem erreicht wird?
Du kannst es selbst vor das Ergebnis von raw_input einfügen, dann musst Du die Variablenbezeichnung "x" aber fest vorschreiben.
a fool with a tool is still a fool, www.magben.de, YouTube
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

MagBen hat geschrieben: input("abc") macht in Python 2.7 das gleiche wie eval(raw_input("abc")), warum sollte das in Python 3 anders sein?
Weil das ``input`` aus Python 2 als unnötig angesehen worden ist und daher in Python 3 entfällt ;-)

Und generell: Das ganze ist alles nicht gerade sauber und ``eval`` und Konsorten sind einfach gefährlich. Wenn man wirklich beliebige mathematische Funktionen abarbeiten will, sollte man sich sympy o.ä. angucken.
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
Benutzeravatar
MagBen
User
Beiträge: 799
Registriert: Freitag 6. Juni 2014, 05:56
Wohnort: Bremen
Kontaktdaten:

Hyperion hat geschrieben:Weil das ``input`` aus Python 2 als unnötig angesehen worden ist und daher in Python 3 entfällt
Da habe ich wohl nach dem falschen Buch gelernt. :(
Hyperion hat geschrieben:Wenn man wirklich beliebige mathematische Funktionen abarbeiten will, sollte man sich sympy o.ä. angucken.
Um einfach nur Funktionswerte von vorgegebenen Funktionen auszurechnen, ist das unnötig. Sympy braucht man erst, wenn man Gleichungen analytisch lösen will oder Funktionen analytisch differenzieren oder integrieren will. Hier geht es ja einfach nur um das (gefährliche) Parsen der Benutzereingaben mit eval.
a fool with a tool is still a fool, www.magben.de, YouTube
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

MagBen hat geschrieben:Da habe ich wohl nach dem falschen Buch gelernt. :(
Ach i wo... sofern das tolle Bewertungen auf amazon hatte... :twisted: SCNR
MagBen hat geschrieben: Um einfach nur Funktionswerte von vorgegebenen Funktionen auszurechnen, ist das unnötig. Sympy braucht man erst, wenn man Gleichungen analytisch lösen will oder Funktionen analytisch differenzieren oder integrieren will. Hier geht es ja einfach nur um das (gefährliche) Parsen der Benutzereingaben mit eval.
Ja, genau um das gefährliche Parsen geht es! :-)
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
Benutzeravatar
MagBen
User
Beiträge: 799
Registriert: Freitag 6. Juni 2014, 05:56
Wohnort: Bremen
Kontaktdaten:

Hyperion hat geschrieben:a, genau um das gefährliche Parsen geht es!
Und mit Sympy kannst Du also Stringeingaben so parsen, dass nachher ausführbare Funktionen rauskommen ohne dafür eval zu benutzen?
a fool with a tool is still a fool, www.magben.de, YouTube
kaykay
User
Beiträge: 5
Registriert: Mittwoch 24. September 2014, 13:15

MagBen hat geschrieben:OK, ich hab's mit Python 2.7 gemacht, print musst Du nun so schreiben (achte auf die Klammerung):

Code: Alles auswählen

print("rec(%f)=%f" % (x, rec(f,x,t)))
kaykay hat geschrieben:Gibt es eine Möglichkeit, dass ich bei der Eingabe im Shell das "lambda x:" weglassen kann, und das Ziel trotzdem erreicht wird?
Du kannst es selbst vor das Ergebnis von raw_input einfügen, dann musst Du die Variablenbezeichnung "x" aber fest vorschreiben.
Wie meinst du das? Verstehe ich leider nicht ganz..

Muss ich bei def read_f() das x in die Klammern setzen? Also => read_f(x)?

Dann taucht nämlich das Problem auf, das wenn ich die Funktion durch folgendes starten will:

f = read_f(x)

x nicht definiert ist und ich eine Fehlermeldung bekomme.

MfG
Zuletzt geändert von kaykay am Donnerstag 25. September 2014, 14:49, insgesamt 1-mal geändert.
Benutzeravatar
MagBen
User
Beiträge: 799
Registriert: Freitag 6. Juni 2014, 05:56
Wohnort: Bremen
Kontaktdaten:

Python 2.7

Code: Alles auswählen

def read_f():
    # globals() muss uebergeben werden, damit der Benutzer alles aus math benutzen kann.
    return  eval("lambda x:%s" % raw_input("fkt(x): "), globals())
Python 3 (wahrscheinlich):

Code: Alles auswählen

def read_f():
    # globals() muss uebergeben werden, damit der Benutzer alles aus math benutzen kann.
    return  eval("lambda x:%s" % input("fkt(x): "), globals())
Eingabe "cos(x)":

Code: Alles auswählen

fkt(x): cos(x)
rec(-3.000000)=1.530295
rec(-2.000000)=1.416147
rec(-1.000000)=0.000000
rec(0.000000)=-1.416147
rec(1.000000)=-1.530295
rec(2.000000)=-0.237497
rec(3.000000)=1.273655
a fool with a tool is still a fool, www.magben.de, YouTube
BlackJack

@MagBen: Warum muss ``globals()`` übergeben werden? Das sollte der Defaultwert sein.
Benutzeravatar
MagBen
User
Beiträge: 799
Registriert: Freitag 6. Juni 2014, 05:56
Wohnort: Bremen
Kontaktdaten:

BlackJack hat geschrieben:Warum muss ``globals()`` übergeben werden? Das sollte der Defaultwert sein.
Wenn ich es weglasse, dann kommt (bei Python 2.7) bei einer Eingabe der Funktion "cos(x)" die Fehlermeldung "NameError: name 'cos' is not defined".
a fool with a tool is still a fool, www.magben.de, YouTube
kaykay
User
Beiträge: 5
Registriert: Mittwoch 24. September 2014, 13:15

Tatsächlich kann ich globals() weglassen, und cos(x) etc. wird trotzdem erkannt! Vielen dank nochmal.

Kennt ihr übrigens eine hilfreiche Seite für das plotten mit matplotlib? Ausführliche Tutorials wären da sehr hilfreich.
Benutzeravatar
MagBen
User
Beiträge: 799
Registriert: Freitag 6. Juni 2014, 05:56
Wohnort: Bremen
Kontaktdaten:

kaykay hat geschrieben:Tatsächlich kann ich globals() weglassen, und cos(x) etc. wird trotzdem erkannt!
Erstaunlich, ein Unterschied zwischen Python 2 und 3?
kaykay hat geschrieben:Kennt ihr übrigens eine hilfreiche Seite für das plotten mit matplotlib? Ausführliche Tutorials wären da sehr hilfreich.
Kein wirkliches Tutorial, aber eine sehr schöne Sammlung an Beispielen: http://matplotlib.org/gallery.html
a fool with a tool is still a fool, www.magben.de, YouTube
Sirius3
User
Beiträge: 18335
Registriert: Sonntag 21. Oktober 2012, 17:20

Python 2:

Code: Alles auswählen

>>> from math import cos
>>> f = eval('lambda x: cos(x**2)')
>>> f(0.5)
0.96891242171064473
Antworten