Mit else den Block von vorne beginnen

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
Julian Linne
User
Beiträge: 5
Registriert: Sonntag 19. Januar 2014, 18:27

Guten Abend liebes Python-Forum,

Ich bin neu hier im Forum und auch neu sowohl bei Python als auch allgemein beim Programmieren - in der Schule zwar etwas mit Java rumgespielt, aber ohne jegliche Struktur.. Ich studiere Mathematik und muss ab und an auch Programmieraufgaben in Python lösen, das hat bisher auch immer ganz gut geklappt mit der knappen Einführung, die wir bekommen haben - jetzt steh ich aber gerade auf dem Schlauch:

Ich programmiere (oder besser, versuche es..) eine Interpolationsfunktion (Splineinterpolation, um genau zu sein), die liefert mir (richtig, soweit ich das getestet habe, auch wenns nichts zur Sache tut :D ) eine Zusammengesetze Funktion bzw. deren Koeffizienten, das schaut dann ungefähr so aus:
für x aus [0,1]: y=x
für x aus ]1,2]: y=2x-1
Jetzt soll ich "nur" die Funktion an beliebigen, gegebenen x-Werten auswerten, also sollte soetwas rauskommen:
f(0.5)=0.5
f(1.5)=2

und so weiter. Jetzt müsste ich das ganze allerdings in Python umsetzen, so weit bin ich gekommen:

Kurz zur Erklärung: in x stehen meine auszuwertenden x-Werte der Größe nach sortiert, in data stehen die Stützstellen meiner Interpolation ebenfalls sortiert nach Größe, in der 0. Spalte die x-Werte, in der 1. die y-Werte. in X stehen die x-Werte bereits mit dem passenden Exponenten verrechnet, in s meine koeffizienten, schaut dann so aus:
s

Code: Alles auswählen

[[-0.33333333  1.          1.33333333 -3.        ]
 [ 0.16666667 -2.          7.33333333 -7.        ]]
X

Code: Alles auswählen

[[  1.728   1.44    1.2     1.   ]
 [  3.375   2.25    1.5     1.   ]
 [ 12.167   5.29    2.3     1.   ]
 [ 50.653  13.69    3.7     1.   ]]
Jetzt geht's eigentlich richtig los: Ich hab versucht, die x-Werte mit den Stützstellen zu vergleichen und das klappt auch alles super, solange alle x-Werte in den Definitionsbereich einer Funktion fallen. Ich suche jetzt quasi eine Möglichkeit, mit dem else-Block wieder direkt in den while-Block zu springen, ohne den Index der For-Schleife zu erhöhen - ansonsten überspring ich den Wert, der nicht mehr im 1. Definitionsbereich liegt.

Code: Alles auswählen

f=1 
    for j in range(0,h):
        while x[j]<data[f,0]: 
            y[j]=np.inner(s[f-1],X[j]) 
            break
        else:
            if x[j]==data[f,0]:
                y[j]=data[f,1]
            else:
                f+=1
Ich krieg das Programm auch für die Aufgabe zum laufen, wenn ich einfach die while-Schleife nochmal in den else-Block kopiere, aber ich will das ja eigentlich schön programmieren und nicht bloß die Aufgabe lösen...
Forensuche hab ich benutzt, aber nichts gefunden, ich hab diverse Tutorien durchgeschaut, aber nichts gefunden. Liegt evtl. auch daran, dass mir keine kurze Umschreibung meines Problems einfällt, mit der man sinnvoll bei Freund Google oder in Foren suchen könnte. Ich zerbrech mir seit 14 Uhr nur über den Schritt den Kopf und komm einfach nicht weiter.. Also ich würde mich über einen kleinen Tipp sehr freuen!
Falls ich irgendwelche wichtigen Informationen vergessen hab - sorry, einfach nachfragen! Ich versuch dann, die so schnell wie möglich nachzuliefern.

Viele Grüße,
Jul
Sirius3
User
Beiträge: 17711
Registriert: Sonntag 21. Oktober 2012, 17:20

Kannst Du eine vollständige Funktion schreiben. Was ist z.B. data?

Was soll das für eine while-Schleife sein, die sofort mit »break« abgebrochen wird. Das ist als in Wirklichkeit ein »if«!
Und wenn Du die Bedingung umdrehst, hast Du auch kein Problem mehr mit übersprungenen Werten.
Zuletzt geändert von Sirius3 am Sonntag 19. Januar 2014, 20:14, insgesamt 1-mal geändert.
Julian Linne
User
Beiträge: 5
Registriert: Sonntag 19. Januar 2014, 18:27

Hallo Sirius3,

erstmal danke für die schnelle Antwort - dass es diese Funktionen schon gibt, ist mir bewusst. Wir müssen in unserer Klausur allerdings auch zumindest kleine Programme als Code aufschreiben. Meine Frage ist also gar nicht so arg auf die Funktion der Spline-Interpolation ausgerichtet, sondern viel mehr auf das konkrete Problem mit else. Trotzdem danke für den Hinweis mit der Dokumentation, das werd ich mir gleich mal anschauen, vll find ich ja etwas, wie ich das schöner machen kann.

Edit1: So, hier hab ich mal die vollständige Funktion, wie ich sie gebastelt habe:

Code: Alles auswählen

data=np.matrix([[1,-1],[2,1],[4,1]])
s=[[-0.33333333,1.,1.33333333,-3.][0.16666667,-2.,7.33333333,-7.]]
x=array([1.5,1.2,3.7,2.3]

def evalSpine(s,x):
    n=s.shape[0]
    h=x.shape[0]
    x=sort(x)
    y=mat(np.zeros((h,1)))
    X=np.zeros((h,4))
    for i in range (0,h):
        for j in range(0,4):
            X[i,j]=x[i]**(3-j)
    f=1 
    for j in range(0,h):
        if x[j]<data[f,0]: 
            y[j]=np.inner(s[f-1],X[j]) 
            break
        else:
            if x[j]==data[f,0]:
                y[j]=data[f,1]
            else:
                f+=1

Ich verstehe nicht ganz, was du mit "Bedingung umdrehen" meinst - ich glaub, ich steh gerade ziemlich auf dem Schlauch..
Sirius3
User
Beiträge: 17711
Registriert: Sonntag 21. Oktober 2012, 17:20

Ich schreib das mal in Pseudo-Code auf:

Code: Alles auswählen

für jeden x_wert in x:
    solange x_wert außerhalb aktuellem Bereich:
        gehe einen Bereich weiter
    y_wert = Polynom des aktuellen Bereichs ausgewertet an der Stelle x_wert
Deine Funktion »evalSpine« sollte »eval_spline« heißen und alle Eingabevariablen, die sie benutzt, als Parameter bekommen und auch einen Wert zurückliefern. Meiner Meinung nach ist es eine schlechte Designentscheidung, die Werte von x zu sortieren. Der Aufrufer von »evalSpine« wählt ja die Reihenfolge seiner x-Werte aus einem bestimmten Grund so. Es gibt fast immer eine bessere Lösung, als über den Index einer Liste zu iterieren. Numpy kann auch mit Matrizen rechnen. »n« wird nirgends verwendet.
Julian Linne
User
Beiträge: 5
Registriert: Sonntag 19. Januar 2014, 18:27

Ah, jetzt verstehe ich, was du sagen wolltest! Vielen, vielen Dank für deine Hilfe - ich versuch morgen mal, das umzusetzen, ich wünsch dir noch nen schönen späten Sonntag Abend!

Viele Grüße,
Jul
Julian Linne
User
Beiträge: 5
Registriert: Sonntag 19. Januar 2014, 18:27

Die Frage ist geklärt, Den Thread kann man schließen.
Benutzeravatar
/me
User
Beiträge: 3554
Registriert: Donnerstag 25. Juni 2009, 14:40
Wohnort: Bonn

Julian Linne hat geschrieben:Die Frage ist geklärt, Den Thread kann man schließen.
Threads werden hier nicht geschlossen. Irgendwem fällt immer noch was dazu ein - und wenn es BlackJack mit einer Lösung in 65xx-Assembler ist. :D
BlackJack

@/me: Ich glaube bei diesem Thema passe ich. Und dieses Jahr wollte ich mich ausserdem mal mit Motorola's 68000 befassen. Hatte mich Weihnachten mal wieder mit dem Amiga 500 beschäftigt, den ich damals zu einem gebrauchten C64 kostenlos dazu bekam und nur mal eine kurze Zeit zum Spielen aufgebaut hatte.  Seit Weihnachten habe ich zusätzlich zu dem antiken Gerät einen auf FPGA-Basis. :-) Hätte ich damals doch nur einen Blick auf den Prozessor geworfen, wäre ich vielleicht erst viel später zum PC gekommen. Maschinensprache auf dem Teil sieht echt toll aus, verglichen mit x86-Maschinensprache. Man hat da 15 Register, 8 für Daten und 7 für Adressen (Pointer, das 8. Adressregister ist der Stapelzeiger) und man kann die Datenregister tatsächlich für alles mögliche benutzen. Nicht so wie die ”Allzweckregister” beim x86 wo man bestimmte Operationen immer nur mit bestimmten festen Registern durchführen kann (Division, CX für ``loop``, nur BX als Indexregister, …).
Julian Linne
User
Beiträge: 5
Registriert: Sonntag 19. Januar 2014, 18:27

Alles klar, dann weiß ich da jetzt auch Bescheid - danke für die Info :D
Antworten