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
Mit Python 3.6 lautet die Antwort keine . Die Verwendung des unten stehenden Codes auf einem MBP 2017 zeigt, dass die Verwendung von Modulo schneller ist.
# odd.py
from datetime import datetime
iterations = 100_000_000
def is_even_modulo(n):
return not n % 2
def is_even_and(n):
return not n & 1
def time(fn):
start = datetime.now()
for i in range(iterations, iterations * 2):
fn(i)
print(f'{fn.__name__}:', datetime.now() - start)
time(is_even_modulo)
time(is_even_and)
Ergibt dieses Ergebnis:
$ python3 -m odd
is_even_modulo: 0:00:14.347631
is_even_and: 0:00:17.476522
$ python3 --version
Python 3.6.1
Wie in anderen Antworten angedeutet, sind die Funktionsaufrufe ein großer Overhead, jedoch zeigt das Entfernen, dass modulo immer noch schneller ist als bitweise und in Python 3.6.1:
# odd.py
from datetime import datetime
iterations = 100_000_000
def time_and():
start = datetime.now()
for i in range(iterations):
i & 1
print('&:', datetime.now() - start)
def time_modulo():
start = datetime.now()
for i in range(iterations):
i % 2
print('%:', datetime.now() - start)
time_modulo()
time_and()
Ergebnisse:
$ python3 -m odd
%: 0:00:05.134051
&: 0:00:07.250571
Bonus: Es stellt sich heraus, dass die Ausführung in Python 2.7 etwa doppelt so lange dauert.
$ time python2 -m odd
('&:', '0:00:20.169402')
('%:', '0:00:19.837755')
real 0m41.198s
user 0m39.091s
sys 0m1.899s
$ time python3 -m odd
&: 0:00:11.375059
%: 0:00:08.010738
real 0m19.452s
user 0m19.354s
sys 0m0.042s
Abgesehen von der bösen Optimierung nimmt es das sehr idiomatische "var % 2 == 0" weg, das jeder Programmierer versteht, ohne zweimal hinzusehen. Dies ist also ein Verstoß gegen Pythons Zen für einen sehr geringen Gewinn.
Außerdem wurde a = b und True or False zur besseren Lesbarkeit ersetzt durch
return True if num & 1 else False
Ich war wirklich überrascht, dass keine der obigen Antworten sowohl das Einrichten von Variablen (wörtliches Timing ist eine andere Geschichte) als auch keinen Funktionsaufruf (der offensichtlich "niedrigere Terme" ausblendet) berücksichtigt hat. Ich habe mich an das Timing von ipython's timeit gehalten, wo ich einen klaren Gewinner x&1 hatte - besser für ~18% mit python2.6 (~12% mit python3.1).
Auf meinem sehr alten Rechner:
$ python -mtimeit -s 'x = 777' 'x&1'
10000000 loops, best of 3: 0.18 usec per loop
$ python -mtimeit -s 'x = 777' 'x%2'
1000000 loops, best of 3: 0.219 usec per loop
$ python3 -mtimeit -s 'x = 777' 'x&1'
1000000 loops, best of 3: 0.282 usec per loop
$ python3 -mtimeit -s 'x = 777' 'x%2'
1000000 loops, best of 3: 0.323 usec per loop
Aktualisieren der Ergebnisse für die neueste Python-Version, % ist schneller als &
python -m timeit -s 'def isodd(x): x & 1' 'isodd(9)'
5000000 loops, best of 5: 78.4 nsec per loop
python -m timeit -s 'def isodd(x): x & 1' 'isodd(10)'
5000000 loops, best of 5: 79.6 nsec per loop
python -m timeit -s 'def isodd(x): x % 2' 'isodd(9)'
5000000 loops, best of 5: 65.8 nsec per loop
python -m timeit -s 'def isodd(x): x % 2' 'isodd(10)'
5000000 loops, best of 5: 68.5 nsec per loop
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.