Kann mir jemand hierbei helfen?

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.
nezzcarth
User
Beiträge: 1752
Registriert: Samstag 16. April 2011, 12:47

@Sirius3:
Stimmt. Das habe ich nicht bedacht. Allerdings sind bei mir die Zahlen für die Modulo-Variante noch immer besser (wenn auch nicht mehr so drastisch):

Code: Alles auswählen

#!/usr/bin/env python3
from time import time
from random import randint, shuffle
from statistics import mean, stdev
N = 10_000
REPETITIONS = 100
LOWER = 1
UPPER = 1_000_000_000


def string_based(s):
    return s[-1] in ('0', '5') and len(s) > 2


def modulo_based(n):
    return n % 5 == 0 and n > 99


def decimal_based(n):
    if n % 10 not in (0, 5):
        return False
    i = 0
    k = n
    while k > 0:
        i += 1
        k //= 10
        if i > 2:
            return False
    return True


ALGORITHMS = [
        ('string comparison', string_based),
        ('modulo calculation', modulo_based),
        ('decimal position', decimal_based)
        ]


def random_numbers(n, lower, upper):
    divisible = set()
    indivisible = set()
    while len(divisible) < n or len(indivisible) < n:
        x = randint(lower, upper)
        if len(divisible) < n and x % 5 in (0, 5):
            divisible.add(x)
        elif len(indivisible) < n:
            indivisible.add(x)
    return tuple(divisible), tuple(indivisible)


def main():
    print('N:', N)
    print('Range:', LOWER, UPPER)
    print('Repetitions:', REPETITIONS)
    results = dict()
    algorithms = ALGORITHMS
    for _ in range(REPETITIONS):
        divisible, indivisible = random_numbers(N, LOWER, UPPER)
        for label, function in ALGORITHMS:
            if label == 'string comparison':
                divisible_temp = [str(i) for i in divisible]
                indivisible_temp = [str(i) for i in indivisible]
            else:
                divisible_temp = divisible
                indivisible_temp = indivisible
            t1 = time()
            for group in (divisible_temp, indivisible_temp):
                for number in group:
                    result = function(number)
            t2 = time()
            results.setdefault(label, [])
            results[label].append(t2 - t1)
        # shuffle last, so order is mainted in modern python
        shuffle(algorithms)
       
    print()       
    for label, durations in results.items():
        print(label, '(mean):', mean(durations))
        print(label, '(sd):', stdev(durations))
        print(label, '(sum):', sum(durations))
        print()


if __name__ == '__main__':
    main()

Code: Alles auswählen

$ ./fives.py                                     :(
N: 10000
Range: 1 1000000000
Repetitions: 100

string comparison (mean): 0.0033177709579467773
string comparison (sd): 0.00032582172245825377
string comparison (sum): 0.33177709579467773

modulo calculation (mean): 0.002630734443664551
modulo calculation (sd): 0.0005114850119894751
modulo calculation (sum): 0.2630734443664551

decimal position (mean): 0.0063778114318847655
decimal position (sd): 0.0006249521611702232
decimal position (sum): 0.6377811431884766
Habe ich da noch etwas übersehen?
Zuletzt geändert von nezzcarth am Samstag 19. Oktober 2019, 13:04, insgesamt 1-mal geändert.
nezzcarth
User
Beiträge: 1752
Registriert: Samstag 16. April 2011, 12:47

nezzcarth hat geschrieben: Samstag 19. Oktober 2019, 12:56 Habe ich da noch etwas übersehen?
..., dass man die Zahlen in Strings umwandeln muss, weil die Eingabe der Ausgangsfrage per 'input()' kommt und so vorliegt. :) Das Result meiner letzten Messung ist ja nun, dass es besser ist, Zahlen als Zahlen vorliegen zu haben. Also kann man festhalten, Modulo ist für Zahlen absolut gesehen schneller als die String-Variante für Strings. Allerdings ist das eigentliche Bottleneck die Konvertierung und der Fragsteller sollte die String-Variante nehmen.
Neiqi
User
Beiträge: 26
Registriert: Freitag 18. Oktober 2019, 15:10

Ich check gerade gar nichts :D
nezzcarth
User
Beiträge: 1752
Registriert: Samstag 16. April 2011, 12:47

Neiqi hat geschrieben: Samstag 19. Oktober 2019, 13:11 Ich check gerade gar nichts :D
Na ja, das Ergebnis meiner Abschweifungen ist, dass ich mich teilweise korrigieren muss: Da du die Zahl per 'input()' einließt, liegt sie als String vor und dann ist es tatsächlich schneller, mit Zeichenkettenoperationen zu arbeiten.
Zudem habe ich da mal eine letzte Frage, in richtig großen Projekten ist es nicht sogar besser wenn man den Computer sowenig wie möglich rechnen lässt wenn es auch anders geht wie in meinem Code zum Beispiel. In meinem Code schaut sich das Programm doch nur 1 Zahlengruppe an undzwar die welche als letztes in dem String aufgeführt wurde müsste doch schneller sein als die Zahl zu berechnen oder sehe ich da was Falsch?
Diese Aussagen sind meiner Meinung so aber nicht haltbar. Denn absolut gesehen ist die Modulo-Berechnung in Python (zumindest laut meiner Messung) schneller. In deinem Fall würde sie dadurch verlangsamt, dass die Eingabe als String vorliegt und die Konvertierung in eine Zahl Zeit kostet. Kann man es sich aussuchen, ob man Strings oder Zahlen hat, wären in dem Beispiel Zahlen aber zu bevorzugen.
Benutzeravatar
__blackjack__
User
Beiträge: 14021
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Neiqi: Am wichtigsten ist in aller Regel immer erst einmal ob der Quelltext leicht verständlich und *fehlerfrei* ist. Das leicht verständlich hilft dabei ihn fehlerfrei zu schreiben oder zumindest zu machen wenn man einen Fehler gefunden hat. Schnelle aber falsche Ergebnisse braucht keiner.

Was zu fehlerfrei auch dazu gehört ist die Validierung von Eingaben und das berücksichtigen von Sonderfällen. Wenn man die Eingabe in eine Zahl umwandelt, dann fällt sofort auf wenn der Benutzer keine Zahl eingeben hat, sondern beispielsweise "Hallo". Und glaub mir Benutzer tun so etwas. Auch wenn die Aufforderung war eine Zahl einzugeben.

Selbst wenn der Benutzer ein Zahl eingibt, kann das ja auch -4711 oder 23.5 sein. Oder 0000000042. Auch gegen so etwas muss man sein Programm absichern, so das es entweder schon die Eingabe zurückweist, oder auch für diese Fälle ein korrektes Ergebnis ausgibt.

Edit: Da es ja mittlerweile einige Zeitmessungen gab: IMHO sollten Anfänger `pytest` vor `timeit` als Werkzeug in die Finger bekommen. Erst korrekt, dann schnell.
Zuletzt geändert von __blackjack__ am Samstag 19. Oktober 2019, 13:43, insgesamt 1-mal geändert.
„A life is like a garden. Perfect moments can be had, but not preserved, except in memory. LLAP” — Leonard Nimoy's last tweet.
Neiqi
User
Beiträge: 26
Registriert: Freitag 18. Oktober 2019, 15:10

Ahh verstehe okay,
Zu dem Problem mit der 000 und der 100 habe ich eine Lösung gefunden.
bei 101 hatte ich jetzt kein Fehler entdeckt hier der neue Code. Ich muss echt sagen, dass das richtig spaß macht :D

Code: Alles auswählen

import sys

Zahl = str(input("Bitte gebe hier deine Zahl ein die größer 0 ist"))
Zahl1 = int(Zahl)
if Zahl1 == 0:
    print("Gebe eine korrekte Zahl ein")
    sys.exit(0)
elif Zahl[-1] in ('0', '5'):
    print("deine Zahl ist durch 5 Teilbar ohne Rest")
else:
    print("Deine Zahl ist nicht durch 5 Teilbar ohne Rest")
if Zahl1 == 100:
    print("Deine Zahl ist gleich 100")
elif len(Zahl) > 3:
    print("Deine Zahl ist größer als 100")
else:
    print("Deine Zahl ist kleiner als 100")
Benutzeravatar
__blackjack__
User
Beiträge: 14021
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Neiqi: `input()` liefert bereits eine Zeichenkette — es ist überflüssig da noch mal `str()` drauf anzuwenden. Und vielleicht solltest Du das dann auch nicht `zahl` und `zahl1` nennen, sondern `text` oder `ziffern` und `zahl`. Und klein geschrieben. Und bitte nicht irgendwelche Nummern an Namen hängen. Gewöhn Dir so etwas gar nicht erst an!
„A life is like a garden. Perfect moments can be had, but not preserved, except in memory. LLAP” — Leonard Nimoy's last tweet.
Benutzeravatar
__blackjack__
User
Beiträge: 14021
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Neiqi: Vergiss am besten `sys.exit()` als Mittel der Steuerung des Programmflusses gleich wieder. Mach das ordentlich, ohne solche Abkürzungen, so das der Programmfluss ganz normal am Ende des Codes ankommen kann.

Code: Alles auswählen

#!/usr/bin/env python3


def main():
    ziffern = input("Bitte gebe hier deine Zahl ein die größer 0 ist")
    zahl = int(ziffern)
    if zahl == 0:
        print("Gebe eine korrekte Zahl ein")
    else:
        if ziffern[-1] in ('0', '5'):
            print("deine Zahl ist durch 5 Teilbar ohne Rest")
        else:
            print("Deine Zahl ist nicht durch 5 Teilbar ohne Rest")
        
        if zahl == 100:
            print("Deine Zahl ist gleich 100")
        elif len(ziffern) > 3:
            print("Deine Zahl ist größer als 100")
        else:
            print("Deine Zahl ist kleiner als 100")


if __name__ == "__main__":
    main()
Und nun gib mal -1000 ein. Das ist laut diesem Programm grösser als 100.

Edit: Warum schliesst Du eigentlich die 0 überhaupt aus?
„A life is like a garden. Perfect moments can be had, but not preserved, except in memory. LLAP” — Leonard Nimoy's last tweet.
Neiqi
User
Beiträge: 26
Registriert: Freitag 18. Oktober 2019, 15:10

Das mit dem Zahl und Zahl1 kam von unserem Professor er meinte, dass es besser ist...
Ja stimmt aber -1000 ist ja nicht größer 0^^
Aber du hast recht, hatte gerade das mit der - auch im sinn^^
Naja weil die 0 nur probleme macht und man eine 0 ja eh nicht teilen kann...^^
und das Problem ist wenn ich das Programm nicht nach der Fehlerhaften eingabe schließe läuft es weiter und spuckt müll aus
Sirius3
User
Beiträge: 18261
Registriert: Sonntag 21. Oktober 2012, 17:20

@Neiqi: Zahl und Zahl1 sind besser als was?
0043 ist immer noch nicht größer als 100.
nezzcarth
User
Beiträge: 1752
Registriert: Samstag 16. April 2011, 12:47

__blackjack__ hat geschrieben: Samstag 19. Oktober 2019, 13:39 Edit: Da es ja mittlerweile einige Zeitmessungen gab: IMHO sollten Anfänger `pytest` vor `timeit` als Werkzeug in die Finger bekommen. Erst korrekt, dann schnell.
Na ja, aus meiner Sicht wäre die 'korrektere' Lösung, die Eingabe in einen Integer zu verwandeln und das Ergebnis zu berechnen. Zahlen wie Strings zu behandeln ist meiner Meinung nach grenzwertig. Und hier zum Beispiel auch an das Dezimalsystem gebunden. Und du hattest ja sogar noch weitere Gründe geliefert. Die Messungen sollten einerseits der Überzeugung dienen (das ging nach hinten los :) ), andererseits hat er ja im zitierten Post nach Performanceaspekten gefragt. Persönlich finde ich immer noch, dass man das Ergebnis von 'input()' einfach in einen Integer umwandeln und damit rechnen sollte; auch wenn es 'langsamer' ist (es geht ja trotzdem noch schnell genug).
Zuletzt geändert von nezzcarth am Samstag 19. Oktober 2019, 14:29, insgesamt 1-mal geändert.
Neiqi
User
Beiträge: 26
Registriert: Freitag 18. Oktober 2019, 15:10

habe import sys rausgenommen und die Variablen namen auch verändert und das problem mit der -1000 auch gelöst

Code: Alles auswählen

ziffer = str(input("Bitte gebe hier deine Zahl ein die größer 0 ist"))
zahl = int(ziffer)

if zahl == 0:
    print("Gebe eine korrekte Zahl ein")
else:
    if ziffer[-1] in ('0', '5'):
        print("deine Zahl ist durch 5 Teilbar ohne Rest")
    else:
        print("Deine Zahl ist nicht durch 5 Teilbar ohne Rest")
    if zahl == 100:
        print("Deine Zahl ist gleich 100")
    elif zahl < 0:
        print("Deine Zahl ist kleiner als 100")
    elif len(ziffer) > 3:
        print("Deine Zahl ist größer als 100")
    else:
        print("Deine Zahl ist kleiner als 100")
Neiqi
User
Beiträge: 26
Registriert: Freitag 18. Oktober 2019, 15:10

Ja es macht auch mehr Sinn das rechnerisch zu lösen, durch meinen Denkansatz werde ich immer mit neuen Problemen wie jetzt z.B. 0034 konfrontiert wo ich immer mehr dazulerne indem ich versuche die Probleme zu lösen. Es macht auch zudem extrem viel Spaß. ^^
Neiqi
User
Beiträge: 26
Registriert: Freitag 18. Oktober 2019, 15:10

Noch eine Frage dazu, wie kann ich denn in einem String ein gewisses Zeichen ignorieren die aber von einem Input stammen und und nur bis zu einem gewissen Zeichen gehen.
Also z.B : 0003 die ersten drei Zeichen werden ignoriert, oder 0120 das erste Zeichen wird ignoriert.
1000 kein zeichen wird ignoriert. ^^
Sirius3
User
Beiträge: 18261
Registriert: Sonntag 21. Oktober 2012, 17:20

Es ist sehr inkonsequent, für Vergleiche == 100 und < 0 die Zahl zu nehmen, für > 100 aber die Ziffern.
`ziffer` ist der falsche Name für mehreren Ziffern.

Code: Alles auswählen

ziffern = input("Bitte gebe hier deine Zahl ein die größer 0 ist")
ziffern = ziffern.strip().lstrip('0') # führende 0en entfernen
if not ziffern or not ziffern.isdigit():
    print("Gebe eine korrekte Zahl ein")
else:
    if ziffern[-1] in ['0', '5']:
        print("deine Zahl ist durch 5 Teilbar ohne Rest")
    else:
        print("Deine Zahl ist nicht durch 5 Teilbar ohne Rest")
    if ziffern == '100':
        print("Deine Zahl ist gleich 100")
    elif len(ziffern) > 3:
        print("Deine Zahl ist größer als 100")
    else:
        print("Deine Zahl ist kleiner als 100")
Benutzeravatar
snafu
User
Beiträge: 6858
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Einfach die int()-Funktion benutzen. Damit werden führende Nullen automatisch abgeschnitten. Mich wundert, dass du das nicht einfach ausprobiert hast...
Benutzeravatar
snafu
User
Beiträge: 6858
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Neiqi hat geschrieben: Samstag 19. Oktober 2019, 14:32 Ja es macht auch mehr Sinn das rechnerisch zu lösen, durch meinen Denkansatz werde ich immer mit neuen Problemen wie jetzt z.B. 0034 konfrontiert wo ich immer mehr dazulerne indem ich versuche die Probleme zu lösen. Es macht auch zudem extrem viel Spaß. ^^
Volle Zustimmung. Als Lerneffekt ist es ganz nett, das mal selber zu machen mit Stringoperationen. Aber int() kann das schon alles und sollte daher bevorzugt werden. Nachfolgende Prüfungen dann auch besser auf der "echten" Zahl und nicht auf dem String. "ziffern" für den String finde ich übrigens nicht so gut, da es ja auch in dem Moment schon als Zahl gemeint ist. Warum nicht "eingabe" für den String und "zahl" nach der Umwandlung in einen Integer?
Neiqi
User
Beiträge: 26
Registriert: Freitag 18. Oktober 2019, 15:10

Also ich habe das jetzt auch mal einfach rechnerisch gemacht, und wäre ich da am Anfang drauf gekommen wäre es wirklich super leicht. Dadurch, dass ich mich jetzt aber die ganze Zeit damit beschäftigt habe das mit dem String zu lösen und die Probleme dort zu beheben, hat es einfach mein Verständnis schon einmal enorm nach vorne gebracht weshalb die Lösung gerade einmal eine Minute gedauert hat rechnerisch jetzt.
Danke aufjedenfall an alle, die mich hier so toll unterstützt haben!

Code: Alles auswählen

zahl = float(input("Bitte gebe hier deine Zahl ein"))


if zahl == 0:
    print("Gebe eine korrekte Zahl ein")
else:
    if zahl % 5 == 0:
        print("deine Zahl ist durch 5 Teilbar ohne Rest")
    else:
        print("deine Zahl ist nicht durch 5 Teilbar ohne Rest")
    if zahl > 100:
        print("Deine Zahl ist größer als 100")
    elif zahl == 100:
        print("Deine Zahl ist gleich 100")
    else:
        print("deine Zahl ist kleiner als 100")
Eine sache wäre da noch, ich war mir jetzt nicht ganz einig welche IDE ich benutze, ich habe mich jetzt für PyCharm entschieden, da bekomme ich sogar die Pro Version kostenlos komme damit ganz gut klar wollte nur Fragen was die Community von der IDE hält. LG
Zuletzt geändert von Neiqi am Samstag 19. Oktober 2019, 16:27, insgesamt 1-mal geändert.
Benutzeravatar
__blackjack__
User
Beiträge: 14021
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@snafu: Ich finde `ziffern` eigentlich passender, weil dann der Code so ziemlich genau dem entspricht wie man den Algorithmus der Teilbarkeit durch 5 in Worten beschreibt: Die letzte Ziffer ist "0" oder "5" → ``ziffern[-1] in ["0", "5"]``. Das Problem ist vielleicht das man den Rückgabewert von `input()` tatsächlich erst einmal `eingabe` nennen sollte; `ziffern` erst nach dem man die Eingabe validiert und bereinigt hat.

@Neiqi: Führende "0"en könntest Du mit der `lstrip()`-Methode beseitigen. Dann darf da aber natürlich kein "-" davor stehen, das müsste man noch einmal extra behandeln oder verbieten:

Code: Alles auswählen

In [124]: "00030".lstrip("0")                                                   
Out[124]: '30'
„A life is like a garden. Perfect moments can be had, but not preserved, except in memory. LLAP” — Leonard Nimoy's last tweet.
Benutzeravatar
DeaD_EyE
User
Beiträge: 1231
Registriert: Sonntag 19. September 2010, 13:45
Wohnort: Hagen
Kontaktdaten:

Meine Aufgabe ist es, ein Programm zu schreiben, welches sagt, ob die eingegebene Zahl durch 5 Teilbar ist ohne Rest und ob sie größer ist als 100.
  1. Prüfen ob eine Zahl durch 5 teilbar ist:
    https://de.wikipedia.org/wiki/Division_ ... che_Zahlen
    Der Operator % liefert den Rest. Wenn 0 übrig bleibt, ist die Zahl teilbar.

    Code: Alles auswählen

    zahl % 5 == 0
    
  2. Prüfen ob sie größer ist als 100:
    Hier einfach zahl ist größer als

    Code: Alles auswählen

    zahl > 100
Die beiden Ausdrücke mit and verknüpfen:

Code: Alles auswählen

(zahl % 5 == 0) and (zahl > 100)
# die Klammern sind nur für die Optik. Normal lässt man die weg.
Die Variable zahl muss dann natürlich auch ein integer oder float sein.
Die Funktion input liefert strings zurück. Stings muss man erst nach integer umwandeln.

Mach daraus eine Funktion:

Code: Alles auswählen

def my_condition(number):
    return number % 5 == 0 and number > 100
Die Abfrage der Zahl machst du in einer anderen Funktion.
Wenn my_condition True zurückliefert, dann ist die Bedingung erfüllt,
bei False ist die Bedingung nicht erfüllt.

Code: Alles auswählen

my_number = 105
if my_condition(my_number):
    print("Bedingung erfüllt")
sourceserver.info - sourceserver.info/wiki/ - ausgestorbener Support für HL2-Server
Antworten