Ist die Prüfung auf gerade und ungerade Zahlen mit dem niedrigsten Bit effizienter als mit dem Modulo-Prinzip?
>>> def isodd(num):
return num & 1 and True or False
>>> isodd(10)
False
>>> isodd(9)
True
Ist die Prüfung auf gerade und ungerade Zahlen mit dem niedrigsten Bit effizienter als mit dem Modulo-Prinzip?
>>> def isodd(num):
return num & 1 and True or False
>>> isodd(10)
False
>>> isodd(9)
True
Jepp. Die timeit
Modul in der Standardbibliothek können Sie diese Dinge überprüfen. z.B:
$ python -m timeit -s 'def isodd(x): x & 1' 'isodd(9)'
1000000 loops, best of 3: 0.446 usec per loop
$ python -m timeit -s 'def isodd(x): x & 1' 'isodd(10)'
1000000 loops, best of 3: 0.443 usec per loop
$ python -m timeit -s 'def isodd(x): x % 2' 'isodd(9)'
1000000 loops, best of 3: 0.461 usec per loop
$ python -m timeit -s 'def isodd(x): x % 2' 'isodd(10)'
1000000 loops, best of 3: 0.453 usec per loop
Wie Sie sehen, ist auf meinem (erst einen Tag alten==langsamen;-) Macbook Air, die &
Lösung ist wiederholbar zwischen 7 und 18 Nanosekunden schneller als die %
Lösung.
timeit
sagt Ihnen nicht nur, was schneller ist, sondern auch, um wie viel (führen Sie die Tests einfach ein paar Mal durch), was in der Regel zeigt, wie äußerst unwichtig es ist (haben Sie wirklich sich um 10 Nanosekunden Unterschied kümmern, wenn der Overhead des Funktionsaufrufs bei 400 liegt?!)
Programmierer davon zu überzeugen, dass Mikro-Optimierungen im Grunde genommen irrelevant sind, hat sich als unmögliche Aufgabe erwiesen - obwohl es 35 Jahre her ist (in denen Computer um Größenordnungen schneller geworden sind!), seit Knuth schrieb
Wir sollten die kleinen Dinge vergessen Wirkungsgrade, sagen wir etwa 97% der der Zeit: Verfrühte Optimierung ist die Wurzel allen Übels.
was, wie er erklärte, ein Zitat aus einer noch älteren Erklärung von Hoare ist. Ich schätze, alle sind davon überzeugt, dass IHR Fall zu den verbleibenden 3 % gehört!
Anstatt also endlos zu wiederholen "es ist egal", haben wir (insbesondere Tim Peters gebührt hier die Ehre) das Standardmodul der Python-Bibliothek eingebaut timeit
die es trivial einfach macht, solche Mikro-Benchmarks zu messen und damit zumindest die einige Programmierer überzeugen sich selbst davon, dass dieser Fall in die 97 %-Gruppe fällt;-)
Der Compiler wird diese nicht auf dieselbe(n) Anweisung(en) optimieren? Entschuldigen Sie meine Python-Unkenntnis, falls sie auffällt.
Nein, der Python-Compiler ist selbst optimiert, um maximal einfach, zuverlässig und schnell zu sein - er nimmt keine Optimierungen vor, wie z. B. die Änderung der verwendeten Operation (für die er ableiten müsste, dass x
ist z. B. immer ganzzahlig). Versuchen Sie psyco, wenn Sie diese Art von Low-Level-Optimierung benötigen (d.h. wenn jede Nanosekunde zählt).
Ich danke Ihnen für den Hinweis auf die Unwichtigkeit eines so kleinen Unterschieds. Selbst wenn man die Berechnung hunderte oder sogar tausende Male durchführt, ist dies wahrscheinlich eine der schlechtesten "Optimierungen", die man vornehmen kann - es schadet nicht nur der Lesbarkeit (IMO), sondern man bekommt auch nicht so viel zurück. Ich möchte nie mehr bezahlen als das, was ich bekomme.
Um ganz ehrlich zu sein, Ich glaube nicht, dass es darauf ankommt.
Das erste Problem ist die Lesbarkeit. Was macht für andere Entwickler mehr Sinn? Ich persönlich würde ein Modulo erwarten, wenn ich die Geradheit/Ungeradheit einer Zahl prüfe. Ich gehe davon aus, dass die meisten anderen Entwickler dasselbe erwarten würden. Durch die Einführung einer anderen und unerwarteten Methode könnten Sie das Lesen des Codes und damit die Wartung erschweren.
Der zweite Grund ist die Tatsache, dass Sie bei beiden Vorgängen wahrscheinlich nie einen Engpass haben werden. Ich bin für Optimierung, aber frühe Optimierung ist das Schlimmste, was man in jeder Sprache oder Umgebung tun kann. Wenn aus irgendeinem Grund die Feststellung, ob eine Zahl gerade oder ungerade ist, einen Engpass darstellt, dann finden Sie den schnellsten Weg, das Problem zu lösen. Dies bringt mich jedoch zu meinem ersten Punkt zurück - wenn Sie zum ersten Mal eine Routine schreiben, sollte sie so lesbar wie möglich sein.
Ich rechne schon halb damit, dass dieser Punkt abgelehnt wird, aber ich denke, dass er für jeden, der sich diese (oder eine ähnliche) Frage stellt, wichtig ist, also bleibt er bestehen.
Das ist keine Ablehnung... Aber es ist die pythonische Lösung in Fällen wie diesem, ein Profil der "offensichtlichen" Optionen zu erstellen und die schnellste vorzuziehen.
Halblos: Ich lerne immer noch Python, aber ich persönlich denke, dass der Modulo-Operator pythonischer wäre, einfach weil man das tut, was erwartet wird. Es ist, zumindest für mich, viel offensichtlicher und klarer.
Die beste Optimierung, die Sie erreichen können, ist no den Test in eine Funktion einbauen. ' number % 2
' und 'Zahl & 1' sind sehr gebräuchliche Methoden, um ungerade/ungerade zu prüfen. Erfahrene Programmierer werden das Muster sofort erkennen, und Sie können immer einen Kommentar wie '# if number is odd, then blah blah blah' einfügen, wenn es wirklich offensichtlich sein soll.
# state whether number is odd or even
if number & 1:
print "Your number is odd"
else:
print "Your number is even"
John spricht einen guten Punkt an. Der eigentliche Overhead liegt im Funktionsaufruf:
me@localhost ~> python -mtimeit -s'9 % 2'
10000000 loops, best of 3: 0.0271 usec per loop
me@localhost ~> python -mtimeit -s'10 % 2'
10000000 loops, best of 3: 0.0271 usec per loop
me@localhost ~> python -mtimeit -s'9 & 1'
10000000 loops, best of 3: 0.0271 usec per loop
me@localhost ~> python -mtimeit -s'9 & 1'
10000000 loops, best of 3: 0.0271 usec per loop
me@localhost ~> python -mtimeit -s'def isodd(x): x % 2' 'isodd(10)'
1000000 loops, best of 3: 0.334 usec per loop
me@localhost ~> python -mtimeit -s'def isodd(x): x % 2' 'isodd(9)'
1000000 loops, best of 3: 0.358 usec per loop
me@localhost ~> python -mtimeit -s'def isodd(x): x & 1' 'isodd(10)'
1000000 loops, best of 3: 0.317 usec per loop
me@localhost ~> python -mtimeit -s'def isodd(x): x & 1' 'isodd(9)'
1000000 loops, best of 3: 0.319 usec per loop
Interessant ist, dass beide Methoden ohne den Funktionsaufruf die gleiche Zeit wiederholen.
CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.
2 Stimmen
Was ist mit "und Wahr oder Falsch"?
16 Stimmen
Wenn Sie ein boolesches Ergebnis erhalten möchten, tun Sie einfach bool(num & 1)
3 Stimmen
"0 ist wahr und 1 ist falsch"?! Nun, DAS wäre in der Tat eine interessante Sprache zum Programmieren...!!!
2 Stimmen
Ich habe es vermasselt. In Python ist 0 FALSCH und 1 WAHR (aber in *nix zeigen Exit-Codes von 0 Erfolg an. bash ist wirklich interessant).
0 Stimmen
Ja, ich erinnere mich, wie ich einmal ein Programm (auf einem IBM Instruments-Minicomputer zur Laborsteuerung) mit "return 0" beendete und 16 erschreckende Fehlermeldungen auf der Druckerkonsole erhielt (wie sich herausstellte, wurde der Return-Code bitweise so interpretiert, dass er für jede der 16 möglichen Klassen von Systemfehlern 1=Erfolg, 0=Versagen bedeutete;-) -- deshalb hat ANSI C, glaube ich, EXIT_SUCCESS statt dieser 0 spezifiziert (obwohl ich glaube, dass das niemand benutzt;-).
0 Stimmen
@Selinap: warum dies als python3.1 tag? AFAIK alle der Probleme angefochten werden, sind versionsunabhängig den ganzen Weg zurück zu, wenn True/False eingeführt wurden (2.2?).
0 Stimmen
Wenn Ihnen das wirklich wichtig ist, ist Python nicht die richtige Sprache für Sie.