Stecke fest bei einem Elemente Vergleich

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
DrewTimes
User
Beiträge: 4
Registriert: Mittwoch 25. August 2021, 20:15

Moin, hoffe das mir Jemand helfen und mir meinen Fehler auch erklären kann. Der Code ist folgender:

import numpy as np
import math

data = list()
file = open(input("Was ist der Roboterpfad?"), "r")
for line in file:
line = line.strip("\n")
line_list = line.split("\t")
data.append(line_list)
file.close()
path = np.array(data)
size = np.shape(path)
cols = size[1]

if cols == 7:
print("Hier ist das gewünschte Array:", path)
else:
calc = np.array_split(path, 2)
pi = 2*math.pi
if all(a << pi for a in calc[1]):
print("Hier ist das gewünschte Array:", path)
else:
degrees = np.array(math.degrees(calc[1]))
path = np.append([calc[0]], [[degrees]])
print("Hier ist das gewünschte Array:", path)

und der Fehler kommt in dieser Zeile:
if all(a << pi for a in calc[1]):
Vielen Dank schonmal im Voraus für alle die sich das anschauen :)
LukeNukem
User
Beiträge: 232
Registriert: Mittwoch 19. Mai 2021, 03:40

DrewTimes hat geschrieben: Mittwoch 25. August 2021, 20:19 Moin, hoffe das mir Jemand helfen und mir meinen Fehler auch erklären kann. Der Code ist folgender:

Code: Alles auswählen

    # ...
    pi = 2*math.pi
    if all(a << pi for a in calc[1]):
    # ...
und der Fehler kommt in dieser Zeile:
if all(a << pi for a in calc[1]):
Vielen Dank schonmal im Voraus für alle die sich das anschauen :)
Deine Variable "pi" ist eine Fließkommazahl (float), der Bitshift-Operator arbeitet aber nicht mit Fließkommazahlen. Um wieviele Bits möchtest Du denn shiften, 6,283...? ;-) Mich deucht, Du möchtest den Vergleichsoperator < (kleiner als) anstelle des Bitshift-Operators << (um n Bits nach links schieben) benutzen, kann das sein?
Sirius3
User
Beiträge: 17761
Registriert: Sonntag 21. Oktober 2012, 17:20

Dateien öffnet man mit dem with-Statement. Wenn man zum Schluss eh ein numpy-Array will benutzt man aber gleich eine passende numpy-Funktion zum Lesen.
Man benutzt die Methoden von Arrays direkt

Code: Alles auswählen

number_of_columns = path.shape[1]
2π `pi` zu nennen ist sehr verwirrend. Wenn man ein Array hat, dann ist es meist ein Fehler for zu benutzen:

Code: Alles auswählen

(calc[1] > 2*pi).all()
Man sollte keine Funktionen aus math mit numpy-Arrays benutzen.
Die Logik, was Du da mit Deinem path machst, scheint mir suspekt. Was willst Du erreichen?
Benutzeravatar
__blackjack__
User
Beiträge: 13123
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@DrewTimes: Zum einlesen: Man muss nicht jedes kleine Zwischenergebnis an einen Namen binden:

Code: Alles auswählen

    with open(input("Was ist der Roboterpfad?"), encoding="utf-8") as file:
        data = []
        for line in file:
            data.append(line.strip("\n").split("\t"))
Jetzt ist die Schleife so einfach, dass man das als „list comprehension“ schreiben kann:

Code: Alles auswählen

    with open(input("Was ist der Roboterpfad?"), encoding="utf-8") as file:
        data = [line.strip("\n").split("\t") for line in file]
Was allerdings noch fehlt, ist das die einzelnen Elemente in Zahlen umgewandelt werden, denn sonst kann man die gar nicht mit 2π vergleichen:

Code: Alles auswählen

In [21]: "42" < 2*np.pi                                                         
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-21-e91c8c0ad4db> in <module>
----> 1 "42" < 2*np.pi

TypeError: '<' not supported between instances of 'str' and 'float'
Also:

Code: Alles auswählen

    with open(input("Was ist der Roboterpfad?"), encoding="utf-8") as file:
        data = [list(map(float, line.split("\t"))) for line in file]
Aber wie Sirius3 schon geschrieben hat: Nimm gleich die passende Numpy-Funktion.

Bei der Verarbeitung der Daten fällt auf, dass jeder Zweig in dem verschachtelten ``if``/``else``-Konstrukt mit der selben Code-Zeile endet. Die gehört da nicht drei mal in den Code, sondern *einmal* hinter den Code der die Entscheidungen trifft und die Daten verarbeitet.

Wenn man diese Zeile dort heraus zieht, fällt auf, dass in zwei Zweigen überhaupt gar nichts gemacht wird und man ein ``pass`` hinschreiben muss:

Code: Alles auswählen

    if path.shape[1] == 7:
        pass
    else:
        calc = np.array_split(path, 2)
        if (calc[1] < 2 * np.pi).all():
            pass
        else:
            degrees = np.array(math.degrees(calc[1]))
            path = np.append([calc[0]], [[degrees]])
        
    print("Hier ist das gewünschte Array:", path)
Hier kann man den Code vereinfachen in dem man die Bedingungen umkehrt und den jeweils nutzlosen Zweig weg lässt:

Code: Alles auswählen

    if path.shape[1] != 7:
        calc = np.array_split(path, 2)
        if (calc[1] >= 2 * np.pi).any():
            degrees = np.array(math.degrees(calc[1]))
            path = np.append([calc[0]], [[degrees]])
Jetzt noch der Hinweis von Sirius3 bezüglich `math`-Funktionen umgesetzt, und wir landen hier (ungetestet):

Code: Alles auswählen

#!/usr/bin/env python3
import numpy as np


def main():
    path = np.loadtxt(
        input("Was ist der Roboterpfad?"), delimiter="\t", encoding="utf-8"
    )
    if path.shape[1] != 7:
        calc = np.array_split(path, 2)
        if (calc[1] >= 2 * np.pi).any():
            path = np.append([calc[0]], [[np.degrees(calc[1])]])

    print("Hier ist das gewünschte Array:", path)


if __name__ == "__main__":
    main()
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
DrewTimes
User
Beiträge: 4
Registriert: Mittwoch 25. August 2021, 20:15

Vielen Dank schonmal für die ganzen Antworten :)
Hatte sogar einen kleinen Fehler drin habe ich gerade bemerkt, also was ich wollte war:
Alle Elemente in dem array überprüfen ob diese größer als 2*pi sind um sicher zu stellen, dass es sich um degrees handelt.
Wenn dies der fall ist normal ausgeben und wenn nicht halt alle Werte von Bogenmaß in Rad umwandeln.
Der Code ist noch nicht optimiert, weil ich noch dabei bin Python zu lernen :)
Bin aber sehr begeistert von der Hilfe hier!
Vielen Dank schon mal @LukeNukem, @Sirius3, @_blackjack_!!!
DrewTimes
User
Beiträge: 4
Registriert: Mittwoch 25. August 2021, 20:15

Das Einlesen hatte ich auf die Art und Weise gelöst, weil es txt und csv Dateien einlesen soll
Benutzeravatar
__blackjack__
User
Beiträge: 13123
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@DrewTimes: Aber Gradzahlen gehen doch von 0 bis 360, das heisst auch Werte zwischen 0 und 2π können Gradzahlen sein. So eine komische Magie mit raten was der Aufrufer gemeint haben könnte, würde ich nicht machen. Irgendwann rennt man dann mal in den Fall wo falsch geraten wird, und dann kann man die Funktion nicht benutzen, weil die einfach ungefragt was umwandelt.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
DrewTimes
User
Beiträge: 4
Registriert: Mittwoch 25. August 2021, 20:15

@_blackjack_ klar aber da ich alle Werte des Arrays überprüfe und das in der Praxis dann immer mehr als 100 Zeilen sind, ist es sehr unwahrscheinlich das alle 300 Werte kleiner 2 pi sind und es trotzdem Grad ist.
Benutzeravatar
kbr
User
Beiträge: 1487
Registriert: Mittwoch 15. Oktober 2008, 09:27

Das ist die Sorte von subtilen Fehlern, die in seltenen Fällen zu Fehlverhalten führen können. Ob die Folgen dann schwerwiegend sind, hängt von der Anwendung ab. Die Funktion sollte nur mit Grad oder Bogenmaß arbeiten und eine mögliche Konvertierung explizit an anderer Stelle erfolgen.
Antworten