For-Schleife mit zwei Variablen

Accy

Ensign
Registriert
Feb. 2014
Beiträge
244
Hallo,

ich bin noch recht neu im Gebiet des Programmierens. Habe mir dafür mittlerweile ein paar Tutorials in Python gegeben und hänge dort nun an einer Aufgabe, dessen Problem ich nicht gelöst bekomme.

Die Aufgabe lautet: " Wir wollen alle Paare von ganzen Zahlen (i,j) auflisten mit i^2 + j^2 < 10 "

Folgenden Code habe ich dafür jetzt geschrieben:
Python:
for i in range(-100, 100):          # >> 'i' wird in einer for-Schleife ausgeführ in einer Reichweite von -100 bis 100
    m = i**2 + i**2                 # >> 'm' wird berechnet
    if m < 10:                      # >> prüfe ob 'm' kleiner als 10 ist
        print(i)                    # >> falls wahr - gibt die Zahl aus
    continue                        # >> falls falsch - brich hier ab und setze die Schleife fort
print('finish')                     # >> ende der Schleife


Dieser Code funktioniert wie er soll, allerdings wird hier noch nur mit einer Variable gerechnet.

Stelle ich den Code um:
Python:
for i, j in range(-100, 100):       # >> 'i' wird in einer for-Schleife ausgeführ in einer Reichweite von -100 bis 100
    m = i**2 + j**2                 # >> 'm' wird berechnet
    if m < 10:                      # >> prüfe ob 'm' kleiner als 10 ist
        print(i, j)                 # >> falls wahr - gibt die Zahl aus
    continue                        # >> falls falsch - brich hier ab und setze die Schleife fort
print('finish')                     # >> ende der Schleife

erhalte ich eine Fehermeldung
Traceback (most recent call last):
File "C:/Users/...", line 12, in <module>
for i, j in range(-100, 100): # >> 'i' wird in einer for-Schleife ausgeführ in einer Reichweite von -100 bis 100
TypeError: cannot unpack non-iterable int object


Wie kann ich den Fehler beheben? Oder bin ich mit meinem Lösungsansatz vielleicht sogar auf dem ganz falschen Weg?

Vielen Dank.

Beste Grüße. :)
 
Muss man dafuer nicht einfach die Schleifen verschachteln?
Code:
For i in range (-100, 100):

     For j in range (-100, 100):

          m = ...

Ich muss gestehen, noch nie in Python programiert zu haben. Andere Sprachen sind auch schon eine Weile her.
 
gibt viele Wege, verschachtelte Schleifen
Python:
for i in range(-100,100):
    for j in range(-100,100):
oder
Python:
for i, j in zip(range(-100,100), range(-100,100)):
oder ...

EDIT: das mit dem zip macht keinen Sinn, man bekommt nur Paare mit gleicher Zahl. Vergiss das also, du willst ja alle Kombinationen.
 
Zuletzt bearbeitet:
  • Gefällt mir
Reaktionen: Accy, M@tze und JennyCB
Accy schrieb:
Wie kann ich den Fehler beheben?
Pro Tipp: Nach "Python + <fehlermeldung>" Googlen. Das was du geschrieben hast als zweite Variante for i, j in range(-100, 100): hat nicht die Semantik (= Bedeutung) die du vermutet hast.
Wieso beginnt deine Range bei -100 wenn du die Zahlen sowieso quadrierst?
 
Ich kenne kein Python aber müssten da nicht 2 Bedingungen stehen.
for i, j in range(-100, 100), range(-100, 100):
Mal abgesehen davon das man immer so einfach (lesbar) wie möglich programmieren sollte.
 
abcddcba schrieb:
Python:
Code:
for i in range(-100,100):
    for j in range(-100,100):
Danke, ich wusste nicht wonach ich googlen soll, beim Verschachteln mit "range". Hat mir schon geholfen. :)

BeBur schrieb:
Das was du geschrieben hast als zweite Variante for i, j in ... hat nicht die Semantik (= Bedeutung) die du vermutete hast.
Was genau meinst du?

BeBur schrieb:
Wieso beginnt deine Range bei -100 wenn du die Zahlen sowieso quadrierst?
Ich muss ja irgendeinen Zahlenbereich angeben und habe dann eben intuitiv |100| gewählt.
 
BeBur schrieb:
Wieso beginnt deine Range bei -100 wenn du die Zahlen sowieso quadrierst?
Negative Zahlen können ja auch Lösungen sein. Warum man allerdings hundert wählt, ist mir nicht klar. Ganzzahlige Quadrate sind immer kleiner gleich des Betrags der Zahl selbst. Also reicht sicherlich -10 bis 10
 
  • Gefällt mir
Reaktionen: Accy
abcddcba schrieb:
Python:
for i, j in zip(range(-100,100), range(-100,100)):

Nein, das wird nicht funktionieren, da das Programm pro Durchlauf immer nur die selben Elemente aus den Iteratoren nimmt. Also aus dem ersten Iterator das erste Element und aus dem zweiten Iterator nur das erste Element usw.

Bei den verschachtelten Schleifen wird aus dem ersten Iterator das erste Element mit allen Elementen aus dem zweiten Iterator berechnet. Dann das zweite Element aus dem ersten Iterator usw.

PS: Habe gerade gesehen, dass Du es schon selber korrigiert hast... ;)
 
TheOneofAll schrieb:
Negative Zahlen können ja auch Lösungen sein. Warum man allerdings hundert wählt, ist mir nicht klar. Ganzzahlige Quadrate sind immer kleiner gleich des Betrags der Zahl selbst. Also reicht sicherlich -10 bis 10
Da hast du wohl recht :D.
 
Da 3.16^2 ungefähr 10 ist reicht als bereich 0 - 3.
Es kann also kein Paar geben bei dem i oder j > 3 sind


Wenn ich keinen Denkfehler hab sollte sowas funktionieren .
Also deutlich weniger Iteration als vorher - ist zwar bei dem Beispiel egal aber bei je größer der Bereich desto größer der Performancevorteil ( also statt <10 kleiner 100.000.000 z.b )


Python:
import math
maxval = int(math.sqrt(10))  ##
for i in range(0,maxval+1):
    ## Kombination mit j=0 ist immer ok also brauchen wir hier nicht rechnen
    for j in range(0,maxval+1):
       
        if (i*i) + (j*j) < 10: 
            print ( i,j)
            ## Da das quadrat immer postiv also brauchen wir negative Zahlen gar nicht in der Range
            if i != 0:
                print (-i,j)
            if j != 0:
                print (i,-j)
            if i != 0 and j != 0:
                print (-i,-j)
 
Zuletzt bearbeitet:
cloudman schrieb:
desto größer der Performancevorteil
Ich weiß nicht, willst du das nicht lieber in C implementieren und von Python aus aufrufen, sicherlich kriegt man es damit noch performanter und noch schlechter lesbar.
Man kann auch weder die max_value angeben und der Operator < ist auch noch unnötigerweise fix und aktuell funktioniert das ganze auch nur mit Int weder mit Vektoren noch mit z.b. Quaternionen. Man könnte auch einen Parser schreiben, welcher für eine gegebene Grammatik eine Lösung in einer beliebigen Programmiersprache schreibt, denn die aktuelle Lösung funktioniert ja nur mit CPython (was ist mit PyPy oder Cython?)
scnr ;)
 
Zuletzt bearbeitet:
Ich wollte nur zeigen, dass man sich einiges Sparen kann und so schlecht ist die python Performance gar nicht.

Es macht eben einen Unterschied ob man eine Schleife n mal ausführt oder nur Wurzel aus n mal.

Was ist denn daran schwer lesbar.? Übrigens würde der Code in C fast genauso aussehen
 
Ja, so schrecklich wie mein Beitrag nahe legt ist es nicht, da hast du recht. Man würde sich bei Bedarf womöglich überlegen wollen, wie man die Spezialfälle != 0 aus dem Code raus bekommt.
 
Ja das geht sicher noch schöner aber wir wollen hier ja nicht alles für ihn lösen 🙂
Ohne die Bedingungen werden die Kombination mit null sonst doppelt angezeigt.

Nur um den performance Gewinn zu verdeutlichen.

Mit - 10.. 10 wird die innere Schleife 400 mal ausgeführt
Mit meiner Variante 9 mal

Bei 100 statt 10 wäre es 40000 mal vs 100 mal wenn ich mich jetzt auf die Schnelle nicht verrechnet hab
 
  • Gefällt mir
Reaktionen: BeBur
Für lediglich identische Zahlenpaare (i = j) kannst du deinen Ursprungscode aus Posting #1 sehr leicht anpassen:
Python:
for i in range(-100, 100):          #
    j = i                           # NEU
    m = i**2 + i**2                 #
    if m < 10:                      #
        print(i, j)                 # , j ergänzt
    continue                        # continue könnte gestrichen werden, funktioniert auch so, glaube ich
print('finish')                     #


Dann fehlen allerdings noch alle weiteren Kombinationen. Hierzu ein Zweizweiler:
Python:
for zahl_1 in list(range(-100, 100)):
    [print("Ergebnis für Zahlenpaar", zahl_1, "und", zahl_2, "ist", zahl_1**2 + zahl_2**2, "(< 10)") for zahl_2 in list(range(-100, 100)) if zahl_1**2 + zahl_2**2 < 10]

Viel Spaß beim Üben, bin auch erst seit ein paar Monaten dabei... :)
 
  • Gefällt mir
Reaktionen: BeBur
Accy schrieb:
Ich komme von Perl her, daher sieht so eine Lösung in Python für mich so aus:
Python:
from itertools import permutations

def testsum(t): return  t[0]**2 + t[1]**2 <= 10

maxnum, factors  = 20, 2
mynums = [num for num in filter(testsum, permutations(range(-maxnum,maxnum), factors))]

print(mynums)
 
  • Gefällt mir
Reaktionen: XCatenaccioX und BeBur
@blöderidiot, sah kompliziert aus, aber nach ein bisschen Rumgooglen und 2 x Aha-Effekt, echt cool, like a boss! :D Selbst wenn man zu Übungszwecken auf dieses importierte Modul verzichten wollte/müsste, könnte man an den Filter auch ein zuvor selbstgebasteltes Permutationstupel oder -liste übergeben. Und aus der Berechnung eine Funktion zu bauen, sowieso sinnvoll, da Teilaufgabe segmentiert. Top.
 
XCatenaccioX schrieb:
@blöderidiot,2 x Aha-Effekt, echt cool, like a boss
Vooorsicht!

ich habe auch erst seit kurzem mit Python angefangen (bzw. komplett von Perl auf Python umgestiegen) und neige zu unüberlegter Verwendung von Perl-Idiomen. Ein weiterer Blick auf meinen Code ergab: wenn die Range-Erstellung aus dem itertools/permutations-Aufruf herausgenommen wird, steigt die Performanz erheblich. Ausserdem kann man die Testfunktion hier günstigerweise als anonyme Funktion (Lambda) direkt in den Filter schreiben:

Python:
from itertools import permutations

Rge = range(-100, 100)
Nmb = [ n for n in filter(lambda t: t[0]**2 + t[1]**2 <= 10, permutations(Rge, 2)) ]

print(Nmb)
Dadurch reduziert sich die eigentliche Problemlösung auf einen Zweizeiler.
 
Zuletzt bearbeitet:
  • Gefällt mir
Reaktionen: XCatenaccioX
Und mit Rge = range(-3, 3) oder - 4, 4 sollte es nochmal deutlich schneller werden ohne am Ergebnis etwas zu ändern
Ich bin auch kein python crack und nicht ganz sicher ob range(0,3) die 3 noch enthält oder nicht

Wenn die Mathematik dahinter so simpel ist das selbst ich damit keine Probleme habe sollte man so eine simple Optimierung immer mitnehmen 🙂

Wie gesagt hier vollkommen unwichtig.
 
Accy schrieb:
ich bin noch recht neu im Gebiet des Programmierens. Habe mir dafür mittlerweile ein paar Tutorials in Python gegeben und hänge dort nun an einer Aufgabe, dessen Problem ich nicht gelöst bekomme.

Gut, bist also noch nicht tief genug drin. Kannst daher fast mühelos zu einer richtigen Sprache wechseln.
https://www.computerbase.de/forum/threads/welche-programmiersprache-wofuer.1965055/#post-24530932

Nachtrag zu dem Post, weil mir das @new Account() mal nahegebracht hat: Es gibt eine IDE mit Debugger, PyCharm, habe ich gestern die ganze Nacht verwendet, ist so lala, besser als nichts. Ändert aber leider nichts an den anderen Problemen, die Python hat. Es ist wohl möglich bei Parametern streng zu typisieren, wenn man will, ändert aber nichts daran, dass es normalerweise nicht gemacht wird, und sowas erst zur Laufzeit als Fehler geworfen wird. Kombiniert damit, dass Python 50-100mal langsamer als C# oder Java ist, ist es als Sprache, wenn man viel Debuggen muss (was man immer machen muss), einfach ungeeignet. Gibt noch genug andere Punkte (es fehlen Designmöglichkeiten wie Enums elegant umzusetzen, oder einfach mal sinnvolle Prinzipien wie Kapselung).

@new Account(): Dein Name ist echt scheiße um dir mal nebenbei Respekt zu erweisen. Das Leerzeichen macht die Autovervollständigung kaputt.

EDIT:

Oh Gott, der Arme ist ja gebannt worden. Möge er in Frieden ruhen, und @DerDichter meine Grüße bestellen.
 
Zuletzt bearbeitet:
  • Gefällt mir
Reaktionen: blöderidiot
Zurück
Oben