Ich versuche, in Python zwei Beispiele zu reproduzieren (ursprünglich in Java geschrieben), die ich in einem Buch gefunden habe.Bit Vektor vs Liste der booleschen Werte Leistung
Die zwei Funktionen prüfen, ob eine Zeichenfolge wiederholte Zeichen enthält. Die erste Funktion verwendet eine Ganzzahl (checker
) als einen Bitvektor, während die zweite Funktion einfach eine Liste von Booleschen Werten verwendet. Ich hatte erwartet, eine bessere Leistung mit der Funktion mit Bits zu haben, aber eigentlich ist es schlechter.
Warum ist das? Habe ich beim "Übersetzen" von Java nach Python etwas falsch geschrieben?
Hinweis: der Einfachheit halber nur wir Kleinbuchstaben (ein zu z), insbesondere für die Bit-Vektorfunktion.
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))
Ergebnisse:
[1.732477278999795, 1.7263494359995093, 1.7404333820004467]
[0.6785205180003686, 0.6759967380003218, 0.675434408000001]
Die ursprünglichen Java-Funktionen sind die folgenden:
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;
}
Vielen Dank für die Bereitstellung einer zusätzlichen Methode: Ich habe es nicht berücksichtigt, da ich nur die zwei Java-Methoden oben übersetzte, aber es könnte als Referenz nützlich sein. Du hast gesagt, dass * "ein Array mutiert, Objekte überhaupt nicht zuweist" *; Könnten Sie bitte einen Hinweis darauf geben? Sprechen Sie über Arrays im Allgemeinen oder nur diese spezielle Liste (in der wir nur True/False-Werte ändern)? Außerdem: soll das in Java gegensätzliche Leistung bringen? –
@KurtBourbaki (In der Zwischenzeit habe ich versucht, einen Line-by-Line-Profiler zu starten, aber es ist mir nicht gelungen.) Ich habe über Listen im Allgemeinen gesprochen, und ich meinte die Item-Zuweisung. ('[].append 'kann zu einer Speicherzuordnung führen, die aber durch das Listenobjekt selbst verdeckt wird.) –
Das ist also schneller, weil wir' True' oder 'False' Werte zuweisen, anstatt neue ganze Zahlen zu vergeben, oder? Kennst du etwas über Java? ZB: wäre der Bitvektor effizienter als das boolesche Array? –