Sto cercando di riprodurre in Python due esempi (originariamente scritti in Java) che ho trovato in un libro.Bit vettoriale vs elenco di valori booleani prestazioni
Le due funzioni verificano se una stringa contiene caratteri ripetuti. La prima funzione utilizza un numero intero (checker
) come vettore di bit, mentre la seconda funzione utilizza semplicemente un elenco di valori booleani. Mi aspettavo di ottenere prestazioni migliori usando la funzione con i bit, ma in realtà peggiora.
Perché è quello? Ho scritto qualcosa di sbagliato mentre "traducevo" da Java a Python?
Nota: per semplicità usiamo solo lettere minuscole (un per z), soprattutto per la funzione di vettore di bit.
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))
Risultati:
[1.732477278999795, 1.7263494359995093, 1.7404333820004467]
[0.6785205180003686, 0.6759967380003218, 0.675434408000001]
Le funzioni Java originali sono i seguenti:
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;
}
Grazie per aver fornito un metodo aggiuntivo: non l'ho considerato poiché stavo solo traducendo i due metodi Java sopra, ma potrebbe essere utile per riferimento. Hai detto che * "la mutazione di un array non assegna affatto" *; potresti per favore dare qualche riferimento a questo? Stai parlando di array in generale o solo di questo elenco specifico (in cui cambiamo solo i valori True/False)? Inoltre: questo dovrebbe produrre prestazioni opposte in Java? –
@KurtBourbaki (Nel frattempo stavo cercando di lanciare un profiler riga per riga, ma non ci sono riuscito.) Stavo parlando di elenchi in generale, e intendevo l'assegnazione degli articoli. ('[].append' può risultare nell'assegnazione della memoria, ma è nascosta dall'oggetto list stesso) –
Quindi questo è più veloce perché assegniamo i valori 'True' o' False' invece di allocare i nuovi numeri interi, giusto? Sai qualcosa su Java? E.g .: il vettore bit sarebbe più efficiente dell'array booleano? –