Funktionen

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
FunkyMonkey
User
Beiträge: 4
Registriert: Donnerstag 7. September 2017, 17:24

Moin ich hoffe das ist nicht zu viel Code für mein Frage aber ich schicke lieber mehr als zu wenig.

Es geht nur um den Teil ab dem comment "X-Koordinate". Der Code funktioniert, wenn ich nur den Teil mit "X-Koordinate" einkommentiere. Wenn ich den Teil mit "Y-Koordinate" und "Z-Koordinate" einkommentiere funktioniert er nicht mehr. Ich weiß nicht warum :K

Ich habe das Gefühl das hat was damit zu tun, dass Variablen unbemerkt überschrieben werden, was für Leute die neu in Python sind, wie ich, immer erstaunlich ist. So wie hier ganz unten: http://www.python-course.eu/sequential_data_types.php

Das Ziel des Codes ist, dass x_min, x_max etc. ausgerechnet werden. Ich wette der Rest verwirrt euch jetzt :? Der Rest ist aber nur das Auslesen von der asd.fem und das funktioniert auch.

Falls ich noch mehr erklären soll bitte sagen!

Code: Alles auswählen

n_max=[0.0,0.0]
n_min=[0.0,0.0]
x_max=[0.0,0.0]
x_min=[0.0,0.0]
y_max=[0.0,0.0]
y_min=[0.0,0.0]
z_max=[0.0,0.0]
z_min=[0.0,0.0]

p0=[]

text = open("asd.fem","r")
lines = (line.rstrip("\n") for line in text)
lines = (line for line in lines if line)
for line in lines:
    v=line.split()
    if v[0]=="GRID":
        #NUM_ELEM_X & NUM_ELEM_Y & NUM_ELEM_Z
        # X Koordinate
        if line[29:30]=="-":
            x = float(line[24:29] + "e" + line[29:32])
        else:
            x = float(line[24:32])
        find_max_min(x,x_max,x_min)
        x_max = n_max
        x_min = n_min
                
        # Y Koordinate
        if line[37:38]=="-":
            y = float(line[32:37] + "e" + line[37:40])
        else:
            y = float(line[32:40])
        find_max_min(y,y_max,y_min)
        y_max = n_max
        y_min = n_min
                
        # Z Koordinate
        if line[45:46]=="-":
            z = float(line[40:45] + "e" + line[45:48])
        else:
            z = float(line[40:48])
        find_max_min(z,z_max,z_min)
        z_max = n_max
        z_min = n_min
        
def find_max_min(n,n_max,n_min):
    if n > n_max[0]:
            n_max[1] = n_max[0]
            n_max[0] = n
    elif n > n_max[1] and n < n_max[0]:
            n_max[1] = n
    elif n < n_min[0]:
            n_min[1] = n_min[0]
            n_min[0] = n
    elif n < n_min[1] and n > n_min[0]:
            n_min[1] = n     
FunkyMonkey
User
Beiträge: 4
Registriert: Donnerstag 7. September 2017, 17:24

Hier vereinfachte Version:

Code: Alles auswählen

n_max=[0.0,0.0]
n_min=[0.0,0.0]
x_max=[0.0,0.0]
x_min=[0.0,0.0]
y_max=[0.0,0.0]
y_min=[0.0,0.0]
z_max=[0.0,0.0]
z_min=[0.0,0.0]

for n = range(-5,5)
        find_max_min(n,x_max,x_min)
        x_max = n_max
        x_min = n_min
        
        find_max_min(y,y_max,y_min)
        y_max = n_max
        y_min = n_min
        
        find_max_min(z,z_max,z_min)
        z_max = n_max
        z_min = n_min
        
def find_max_min(n,n_max,n_min):
    if n > n_max[0]:
            n_max[1] = n_max[0]
            n_max[0] = n
    elif n > n_max[1] and n < n_max[0]:
            n_max[1] = n
    elif n < n_min[0]:
            n_min[1] = n_min[0]
            n_min[0] = n
    elif n < n_min[1] and n > n_min[0]:
            n_min[1] = n
Sirius3
User
Beiträge: 17749
Registriert: Sonntag 21. Oktober 2012, 17:20

@FunkyMonkey: warum rechnest Du mit »x_min« und »x_max« wenn Du es gleich wieder mit »n_max« und »n_min« überschreibst? n_min und n_max wird eigentlich gar nicht gebraucht.

Das Dateiformat sieht auch komisch aus. Wie ist das Zahlenformat genau?

Allgemein solltest Du Dein Programm in Eingabe, Verarbeitung und irgendwann Ausgabe trennen. Ließ also erst Die Daten in Listen ein, um danach Maximum und Minimum zu bestimmen. Wenn ich das richtig verstehe willst Du die beiden kleinsten oder größten Werte haben?

Die verlinkte Seite ist nicht wirklich zum Lernen geeignet. Da steht so viel Quatsch, der mehr kaputt macht als hilft. Da steht zum Beispiel, dass Listen so was ähnliches wie Arrays sind, was nicht stimmt. Da steht auch, das Tuple schneller sind als Listen. Die wirklich wichtigen Dinge stehen da nicht.

Was Du Dir merken solltest ist, dass alles in Python Objekte sind. Variablen verweisen nur auf diese Objekte. Bei "x_min = n_min" verweisen danach beide Variablen auf die selbe Liste, die vorher nur von n_min referenziert wurde. Änderungen in der Liste sind also sowohl über x_min als auch n_min erreichbar.
FunkyMonkey
User
Beiträge: 4
Registriert: Donnerstag 7. September 2017, 17:24

Danke für Deine Antwort! :)

Genau das was Du gesagt hast, dass x_min und n_min auf das gleiche Objekt verweisen und von mir unerkannt und ungewollt überschrieben werden habe ich vermutet, was da passiert! Aber so ganz weiß ich doch noch nicht was das Problem ist und wie ich es genau beheben kann.

Vielleicht hilft es Dir mir zu helfen, wenn ich Dir sage, dass ich von MATLAB komme. Vielleicht erkennst Du dann meinen Denkfehler dabei besser :D Aber ich beschreibe mal was ich mit dem Code vorhatte:

-> Die if-Bedingung definiert wie x aussieht
-> find_max_min wird aufgerufen und sortiert x richtig in die Liste x_max als größten oder zweitgrößten Wert ein bzw. in x_min als kleinsten oder zweitkleinsten Wert ein
-> x_max und x_min werden erneuert auf die gerade ausgerechneten Liste von n_max und n_min, damit im nächsten Durchlauf auch mit den richtigen Größen verglichen wird. x soll ja mit x_max verglichen werden und nicht mit der Liste y_max
-> jetzt geschieht das gleiche mit der y-Koordinate. find_max_min rechnet ja jetzt neue Listen aus für n_max und n_min. Damit diese separiert werden von der x-Koordinate werden diese Listen in y_max und y_min erneuert (Ich vermute hier liegt mein Denkfehler)
-> das gleiche für z
-> 2. Durchlauf: neues x wird definiert. und nun mit dem x_max und x_min von Durchlauf 1 verglichen.
-> find_max_min sichert die neuen Listen in x_max und x_min damit gleich y separat arbeiten kann
-> usw.

Na? Denkfehler entdeckt? ():) Ich hoffe ich konnte klarmachen, wie ich mir das vorgestellt habe.Zur noch besseren Verdeutlichung hier einmal der Code den ich zu erst hatte der viel zu umständlich ist, aber so funktioniert und den ich mit der Funktion find_max_min vereinfachen wollte:

Code: Alles auswählen

x_max=[0.0,0.0]
x_min=[0.0,0.0]
y_max=[0.0,0.0]
y_min=[0.0,0.0]
z_max=[0.0,0.0]
z_min=[0.0,0.0]

p0=[]
p_iter = [0.0,0.0,0.0]
i=0
j=0
k=0
node_map=[]

#NUM_ELEM_X & NUM_ELEM_Y & NUM_ELEM_Z
text = open("asd.fem","r")
lines = (line.rstrip("\n") for line in text)
lines = (line for line in lines if line)
for line in lines:
    v=line.split()
    if v[0]=="GRID":
        # X Koordinate
        if line[29:30]=="-":
            x = float(line[24:29] + "e" + line[29:32])
            if x > x_max[0]:
                x_max[1] = x_max[0]
                x_max[0] = x
            elif x > x_max[1] and x < x_max[0]:
                x_max[1] = x
            elif x < x_min[0]:
                x_min[1] = x_min[0]
                x_min[0] = x
            elif x < x_min[1] and x > x_min[0]:
                x_min[1] = x
            
        else:
            x = float(line[24:32])
            if x > x_max[0]:
                x_max[1] = x_max[0]
                x_max[0] = x
            elif x > x_max[1] and x < x_max[0]:
                x_max[1] = x
            elif x < x_min[0]:
                x_min[1] = x_min[0]
                x_min[0] = x
            elif x < x_min[1] and x > x_min[0]:
                x_min[1] = x
                
        # Y Koordinate
        if line[37:38]=="-":
            y = float(line[32:37] + "e" + line[37:40])
            if y > y_max[0]:
                y_max[1] = y_max[0]
                y_max[0] = y
            elif y > y_max[1] and y < y_max[0]:
                y_max[1] = y
            elif y < y_min[0]:
                y_min[1] = y_min[0]
                y_min[0] = y
            elif y < y_min[1] and y > y_min[0]:
                y_min[1] = y
        else:
            y = float(line[32:40])
            if y > y_max[0]:
                y_max[1] = y_max[0]
                y_max[0] = y
            elif y > y_max[1] and y < y_max[0]:
                y_max[1] = y
            elif y < y_min[0]:
                y_min[1] = y_min[0]
                y_min[0] = y
            elif y < y_min[1] and y > y_min[0]:
                y_min[1] = y
                
        # Z Koordinate
        if line[45:46]=="-":
            z = float(line[40:45] + "e" + line[45:48])
            if z > z_max[0]:
                z_max[1] = z_max[0]
                z_max[0] = z
            elif z > z_max[1] and z < z_max[0]:
                z_max[1] = z
            elif z < z_min[0]:
                z_min[1] = z_min[0]
                z_min[0] = z
            elif z < z_min[1] and z > z_min[0]:
                z_min[1] = z            
        else:
            z = float(line[40:48])
            if z > z_max[0]:
                z_max[1] = z_max[0]
                z_max[0] = z
            elif z > z_max[1] and z < z_max[0]:
                z_max[1] = z
            elif z < z_min[0]:
                z_min[1] = z_min[0]
                z_min[0] = z
            elif z < z_min[1] and z > z_min[0]:
                z_min[1] = z
Benutzeravatar
pillmuncher
User
Beiträge: 1484
Registriert: Samstag 21. März 2009, 22:59
Wohnort: Pfaffenwinkel

@FunkyMonkey: Bei einer Zuweisung werden in Python nie Objekte kopiert, sondern immer nur Referenzen auf Objekte. Das äußert sich dann zB. so:

Code: Alles auswählen

>>> xs = [1, 2, 3]
>>> ys = xs
>>> xs
[1, 2, 3]
>>> ys
[1, 2, 3]
>>> xs.append(4)
>>> xs
[1, 2, 3, 4]
>>> ys
[1, 2, 3, 4]
>>> id(xs)
140581191817840
>>> id(ys)
140581191817840
>>> id(xs) == id(ys)
True
Vergleiche:

Code: Alles auswählen

>>> xs = [1, 2, 3]
>>> ys = [1, 2, 3]
>>> xs
[1, 2, 3]
>>> ys
[1, 2, 3]
>>> xs.append(4)
>>> xs
[1, 2, 3, 4]
>>> ys
[1, 2, 3]
>>> id(xs)
140581191954232
>>> id(ys)
140581191954304
>>> id(xs) == id(ys)
False
Zur id() Funktion bitte hier nachlesen: https://docs.python.org/2.7/library/functions.html#id
In specifications, Murphy's Law supersedes Ohm's.
Sirius3
User
Beiträge: 17749
Registriert: Sonntag 21. Oktober 2012, 17:20

@FunkyMonkey: Denkfehler ist, dass Funktionen lokale Namensräume sind. Das n_max in der find_min_max-Funktion hat nichts mit dem globalen n_max zu tun. Wenn Du die Funktion mit find_min_max(x, xmin, xmax) aufrufst, dann ist innerhalb der Funktion n_min das selbe wie außerhalb x_min. Wie ich schon geschrieben habe, ist n_min damit außerhalb der Funktion absolut überflüssig und kann ersatzlos gestrichen werden.

Genauso solltest Du eine Funktion schreiben, die das komische Zahlenformat interpretiert, wobei ich immer noch nicht verstehe, wie jemand auf die Idee kommen kann, Zahlen so zu speichern??

Die einfachste Methode an die Min- und Max-Werte zu kommen, ist, die Zahlen in Listen zu speichern und danach zu sortieren. Erst wenn das zu langsam ist, könnte man sich eine optimalere Lösung suchen:

Code: Alles auswählen

def parse_float(text):
    if line[5] == '-':
        line = '{}e{}'.format(line[:5],line[5:])
    return float(line)

def read_fem(filename):
    x_coords, y_coords, z_coords = [], [], []
    with open(filename, "r"):
        lines = (line.rstrip() for line in text)
        lines = (line for line in lines if line)
        for line in lines:
            v=line.split()
            if v[0] == "GRID":
                x_coords.append(parse_float(line[24:32]))
                y_coords.append(parse_float(line[32:40]))
                z_coords.append(parse_float(line[40:48]))
    return x_coords, y_coords, z_coords

def find_min_max(numbers):
    numbers = sorted(numbers)
    return numbers[:2], numbers[-2:]

x_coords, y_coords, z_coords = read_fem("asd.fem")
x_min, x_max = find_min_max(x_coords)
y_min, y_max = find_min_max(x_coords)
z_min, z_max = find_min_max(x_coords)
FunkyMonkey
User
Beiträge: 4
Registriert: Donnerstag 7. September 2017, 17:24

Danke das hat geholfen. Musste zwar in der min max funktion noch mit set() eine menge draus machen damit er keine doppelten nimmt aber das wusstet ihr ja nicht. Ist damit gesolved
Antworten