Próbuję odtworzyć w Pythonie dwa przykłady (pierwotnie napisane w Javie), które znalazłem w książce.Wektor bitowy vs lista wartości boolean wydajność
Obie funkcje sprawdzają, czy ciąg zawiera powtarzające się znaki. Pierwsza funkcja używa liczby całkowitej (checker
) jako wektora bitowego, podczas gdy druga funkcja po prostu używa listy wartości logicznych. Spodziewałem się lepszej wydajności przy użyciu funkcji z bitami, ale w rzeczywistości działa gorzej.
Dlaczego tak jest? Czy napisałem coś nie tak podczas "tłumaczenia" z Java na Python?
Uwaga: dla uproszczenia używamy tylko małe litery ( do oo), zwłaszcza w przypadku funkcja nieco wektorowych.
import sys
import timeit
def is_unique_chars_bit(my_str):
checker = 0
for char in my_str:
val = ord(char) - ord('a')
if ((checker & (1 << val)) > 0):
return False
checker |= (1 << val)
return True
def is_unique_chars_list(my_str):
if len(my_str) > 128:
# Supposing we use ASCII, which only has 128 chars
return False
char_list = [False] * 128
for char in my_str:
val = ord(char)
if char_list[val]:
return False
char_list[val] = True
return True
if __name__ == '__main__':
alphabet = "abcdefghijklmnopqrstuvwxyz"
t_bit = timeit.Timer("is_unique_chars_bit('"+ alphabet +"')", "from __main__ import is_unique_chars_bit")
t_list = timeit.Timer("is_unique_chars_list('"+ alphabet +"')", "from __main__ import is_unique_chars_list")
print(t_bit.repeat(3, 200000))
print(t_list.repeat(3, 200000))
Wyniki:
[1.732477278999795, 1.7263494359995093, 1.7404333820004467]
[0.6785205180003686, 0.6759967380003218, 0.675434408000001]
Oryginalne funkcje Java są następujące:
boolean isUniqueCharsBoolArray(String str) {
if (str.length() > 128) return false;
boolean[] char_set = new boolean[128];
for (int i = 0; i < str.length(); i++) {
int val = str.charAt(i);
if (char_set[val]) {
return false;
}
char_set[val] = true;
}
return true;
}
boolean isUniqueCharsBits(String str) {
for (int i = 0; i < str.length(); i++) {
int val = str.charAt(i) -'a';
if ((checker & (1 << val)) > 0) {
return false;
}
checker |= (1 << val);
}
return true;
}
Dziękujemy za udostępnienie dodatkowej metody: nie brałem pod uwagę tego, ponieważ tłumaczyłem tylko dwie powyższe metody Java, ale może to być przydatne w celach informacyjnych. Powiedziałeś, że * "mutacja tablicy nie przydziela obiektów w ogóle" *; Czy mógłbyś podać jakieś odniesienie na ten temat? Czy mówisz ogólnie o tablicach, czy tylko o tej konkretnej liście (w której zmieniamy tylko wartości True/False)? Co więcej: czy ma to spowodować odwrotną wydajność w Javie? –
@KurtBourbaki (W międzyczasie próbowałem uruchomić profilera wiersz po wierszu, ale nie udało mi się.) Mówiłem ogólnie o listach i miałem na myśli przypisanie elementu. ('[].append' może spowodować alokację pamięci, ale jest to ukryte przez sam obiekt listy) –
A więc jest to szybsze, ponieważ przypisujemy wartości "True" lub "False" zamiast przydzielania nowych liczb całkowitych, prawda? Czy wiesz coś o Javie? Np .: czy wektor bitowy byłby bardziej wydajny niż tablica boolowska? –