Seite 1 von 1

Mit else den Block von vorne beginnen

Verfasst: Sonntag 19. Januar 2014, 19:54
von Julian Linne
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

Re: Mit else den Block von vorne beginnen

Verfasst: Sonntag 19. Januar 2014, 20:00
von Sirius3
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.

Re: Mit else den Block von vorne beginnen

Verfasst: Sonntag 19. Januar 2014, 20:12
von Julian Linne
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..

Re: Mit else den Block von vorne beginnen

Verfasst: Sonntag 19. Januar 2014, 23:27
von Sirius3
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.

Re: Mit else den Block von vorne beginnen

Verfasst: Sonntag 19. Januar 2014, 23:33
von Julian Linne
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

Re: Mit else den Block von vorne beginnen

Verfasst: Montag 20. Januar 2014, 12:26
von Julian Linne
Die Frage ist geklärt, Den Thread kann man schließen.

Re: Mit else den Block von vorne beginnen

Verfasst: Montag 20. Januar 2014, 12:39
von /me
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

Re: Mit else den Block von vorne beginnen

Verfasst: Montag 20. Januar 2014, 13:12
von 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, …).

Re: Mit else den Block von vorne beginnen

Verfasst: Montag 20. Januar 2014, 16:53
von Julian Linne
Alles klar, dann weiß ich da jetzt auch Bescheid - danke für die Info :D