Verständnisfrage Schleifen und Binäroperator

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
DrRocket
User
Beiträge: 30
Registriert: Freitag 11. Mai 2018, 15:11

Hallo zusammen,

ich arbeite zurzeit paar Übungsaaufgaben durch und hänge seit nunmehr einem Tag an einem ansich trivialen Problem.

Aufgabe:
- String mit Zahlen wobei es immer eine Zahl gibt, die gerade (Rest ist dann ungrade) ist oder umgekehrt
- Ich soll die Stelle der Liste ausgeben, wo diese "Ausnahme" vorkommt (also der Key +1 für die einzige gerade oder ungerade Zahl in der Liste)

Vorgehen:
- String wird mit strip und split in eine Liste umgewandelt
- Liste in einer for Schleife durchlaufen und bestimmt, was die Ausnahme ist (gerade oder ungrade Zahl)
- Ausnahme wird mit neuer for Schleife herausgesucht und soll entsprechend ausgegeben werden
- Hierzu verwende ich den Bitoperator "&" mit Verbinung mit 1 oder 0, um zu prüfen, ob es sich um eine gerade oder ungerade Zahl handelt
- Die einzige gerade Zahl mit Index 1 (an der zweiten Stelle) wird nicht wie erwartet gefunden und ausgegeben.
- Obwohl also die Bedingung " if int(value) & 0:" true ist, wird der relevante Programmabschnitt dieser Bedingung im Fall der gerade Zahl in dem Beispiel nicht durchlaufen

hier mein Code:

Code: Alles auswählen

def test_werte(numbers):
    input_as_list = numbers.strip().split(" ")
    odd = 0
    even = 0
    intermediate_even = 0
    intermediate_odd = 0

    for element in input_as_list:
        if int(element) & 1:
            odd += 1
        else:
            even += 1

    print(odd, even)

    if odd > even:
        for key, value in enumerate(input_as_list):
            if int(value) & 0:
                intermediate_even = int(key) + 1
                print(intermediate_even)
    else:
        for key, value in enumerate(input_as_list):
            if int(value) & 1:
                intermediate_odd = int(key) + 1
                print(intermediate_odd)

test_werte("3 28 25 9 5 23 51 15 25 13 41 5 49 21 19 9 35 19 27")
Kann mir einer einen Tipp geben, was hier nicht stimmt?
DrRocket
User
Beiträge: 30
Registriert: Freitag 11. Mai 2018, 15:11

Konkret:

Warum wird die Bedingung "if int(value) & 0:" für value = "28" nicht erfüllt? Wenn ich das außerhalb der if Bedingung aufrufe, steht da ein true.
Benutzeravatar
sls
User
Beiträge: 480
Registriert: Mittwoch 13. Mai 2015, 23:52
Wohnort: Country country = new Zealand();

Gibt es einen Grund, warum du den Modulo-Operator nicht verwendest?

Eine Lösung könnte folgende sein, vorausgesetzt es gibt immer nur eine gerade oder ungerade Zahl:

Code: Alles auswählen

def test_werte(numbers):
    input_as_list = [int(i) for i in numbers.split(" ")]
    odd = even = 0
    for i in input_as_list:
        if i % 2 != 0:
            odd += i
        else:
            even += i

    if even > odd:
        print("Mehr gerade Zahlen vorhanden. Ausnahme {} an Position {}.".format(odd, input_as_list.index(odd) + 1))
    else:
        print("Mehr ungerade Zahlen vorhanden. Ausnahme {} an Position {}.".format(even, input_as_list.index(even) + 1))


test_werte("3 28 25 9 5 23 51 15 25 13 41 5 49 21 19 9 35 19 27")
test_werte("28 24 22 18 8 10 6 12 14 34 7 42 44 66 88 84 70 8 2")
When we say computer, we mean the electronic computer.
Benutzeravatar
ThomasL
User
Beiträge: 1366
Registriert: Montag 14. Mai 2018, 14:44
Wohnort: Kreis Unna NRW

https://wiki.python.org/moin/BitwiseOperators

x & y " Does a "bitwise and". Each bit of the output is 1 if the corresponding bit of x AND of y is 1, otherwise it's 0."

Also int(irgendwas) & 0 liefert immer 0 zurück und 0 kann man als False interpretieren
Warum wird die Bedingung "if int(value) & 0:" für value = "28" nicht erfüllt? Wenn ich das außerhalb der if Bedingung aufrufe, steht da ein true.
Das kann imho nicht stimmen, s.o.
Ich bin Pazifist und greife niemanden an, auch nicht mit Worten.
Für alle meine Code Beispiele gilt: "There is always a better way."
https://projecteuler.net/profile/Brotherluii.png
Benutzeravatar
sls
User
Beiträge: 480
Registriert: Mittwoch 13. Mai 2015, 23:52
Wohnort: Country country = new Zealand();

@DrRocket:

Probier's mal damit:

Code: Alles auswählen

    if odd > even:
        for key, value in enumerate(input_as_list):
            if int(value) & 1 == 0:
                intermediate_even = int(key) + 1
                print(intermediate_even)
    else:
        for key, value in enumerate(input_as_list):
            if int(value) & 1 == 1:
                intermediate_odd = int(key) + 1
                print(intermediate_odd)
When we say computer, we mean the electronic computer.
Sirius3
User
Beiträge: 17749
Registriert: Sonntag 21. Oktober 2012, 17:20

@DrRocket: Zum Vorgehen
- strip ist bei einem split ohne Argument überflüssig und hier solltest Du kein Argument verwenden, damit an beliebigem Leerraum gesplittet wird.
- es reicht ein Durchgang der Liste, wo Du einfach jeweils das erste Vorkommen der geraden und ungeraden Zahlen Dir merkst und außerdem, ob es mehrere davon gab.
- es ist immer die erste Bitstelle ›a & 1‹ die entscheidet ob eine Zahl gerade oder ungerade ist, je nachdem ob diese Operation 0 oder 1 ergibt.

Zum Code:
- Variablen sollten immer erst dann initialisiert werden, wenn sie auch gebraucht werden, eines von intermediate_even oder intermediate_odd wird z.B. nie gebraucht.
- `key` ist schon ein Int, die Umwandlung also unnötig.
- Funktionen, die etwas ausgeben, sind schlecht weiterzuverwenden, üblicherweise hat eine Funktion einen Rückgabewert.
- die zwei for-Schleifen sind fast identisch und könnten zu einer zusammengefasst werden.

Code: Alles auswählen

def test_werte(numbers):
    numbers = numbers.split()
    count = [0,0]
    position = [None, None]
    for index, value in enumerate(numbers):
        i = int(value) & 1  # 0 is odd, 1 is even
        count[i] += 1
        position[i] = index
    if count[0] == 1:
        # only one even number
        return position[0]
    elif count[1] == 1:
        # only one odd number
        return position[1]
    raise ValueError("not only one odd or even number found")
DrRocket
User
Beiträge: 30
Registriert: Freitag 11. Mai 2018, 15:11

Wow, danke für die vielen Rückmeldungen und Tipps! Die Anwendung der Bitoperatoren unterscheidet sich etwas von der Art, wie ich sie bis dato kenne.

@Sirius93: Danke für die ausgezeichnete Erklärung und die ganzen Tipps. Bin das Skript Schritt für Schritt durchgegangen und habe es jetzt auch vestanden :) Funktioniert einwandfrei. Musste nur bei dem Rückgabewert eine 1 addieren, um die tatsächliche Position zu erhalten und nicht den Index.
narpfel
User
Beiträge: 645
Registriert: Freitag 20. Oktober 2017, 16:10

@DrRocket: Die Bitoperatoren funktionieren in Python wie in jeder anderen Sprache auch. Ich hab’ zumindest noch nichts anderes gesehen. Wo testet denn ein `& 0` eine Zahl darauf, dass sie gerade ist?
Antworten