Test Spójrzmy prawdzie w oczy:
import collections
import math
import timeit
def power_bit_length(x):
return 2**(x-1).bit_length()
def shift_bit_length(x):
return 1<<(x-1).bit_length()
def power_log(x):
return 2**(math.ceil(math.log(x, 2)))
def test(f):
collections.deque((f(i) for i in range(1, 1000001)), maxlen=0)
def timetest(f):
print('{}: {}'.format(timeit.timeit(lambda: test(f), number=10),
f.__name__))
timetest(power_bit_length)
timetest(shift_bit_length)
timetest(power_log)
Powodem Używam range(1, 1000001)
zamiast tylko range(1000000)
jest to, że wersja power_log
zawiedzie na 0
. Powodem, dla którego używam małej liczby powtórzeń w szerokim zakresie zamiast wielu powtórzeń w małym zakresie, jest to, że oczekuję, że różne wersje będą miały różną wydajność w różnych domenach. (Jeżeli spodziewają się nazywając to z ogromnymi liczbami tysiąc-bitowych, oczywiście, chcesz testu, który używa tych).
z jabłkiem Python 2.7.2:
4.38817000389: power_bit_length
3.69475698471: shift_bit_length
7.91623902321: power_log
Z Python.org Pythonie 3.3.0:
6.566169916652143: power_bit_length
3.098236607853323: shift_bit_length
9.982460380066186: power_log
Z pypy 1.9.0/2.7.2:
2.8580930233: power_bit_length
2.49524712563: shift_bit_length
3.4371240139: power_log
wierzę, że to pokazuje, że 2**
to powolna część; używanie bit_length
zamiast log
przyspiesza działanie, ale ważniejsze jest używanie 1<<
zamiast 2**
.
Sądzę, że jest jaśniejszy. Wersja OP wymaga mentalnego przełączenia kontekstu z logarytmów na bity, a następnie z powrotem do wykładników. Pozostań w bitach przez cały czas (shift_bit_length
) lub pozostań w dziennikach i wykładnikach (power_log
).
Należy pamiętać, że wynik jest ** niepoprawny ** dla' x == 0' , ponieważ '(-1) .bit_length() == 1' w języku Python. –
Zadbaj o dokładność. 'math.log (2 ** 29,2)' to 29.000000000000004, więc 'power_log (2 ** 29)' daje niepoprawną odpowiedź 30. –
@ColonelPanic Napotkany problem nie istnieje, jeśli 'math.log2' jest użyte, jak powinno być. Problem występuje od 29 tylko wtedy, gdy użyto 'math.log'. –