Я пытаюсь воспроизвести в Python два примера (изначально написанных на Java), которые я нашел в книге.Бит-вектор против списка значений логических значений
Две функции проверяют, содержит ли строка повторяющиеся символы. Первая функция использует целое число (checker
) в качестве битового вектора, а вторая функция просто использует список логических элементов. Я ожидал лучшей производительности, используя функцию с битами, но на самом деле она хуже работает.
Почему? Я написал что-то неправильно во время «перевода» с Java на Python?
Примечание: для простоты мы используем только строчные буквы ( к г), особенно для функции битового вектора.
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))
Результаты:
[1.732477278999795, 1.7263494359995093, 1.7404333820004467]
[0.6785205180003686, 0.6759967380003218, 0.675434408000001]
Оригинальные Java функции являются следующие:
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;
}
Благодарим вас за предоставление дополнительного метода: я не рассматривал его, так как я только переводил два вышеперечисленных Java-метода, но он может быть полезен для справки. Вы сказали, что * «мутация массива не выделяет объекты вообще» *; не могли бы вы дать некоторую ссылку об этом? Вы говорите о массивах вообще или просто о конкретном списке (в котором мы изменяем только значения True/False)? Кроме того: предполагается ли это, что на Java существует противоположная производительность? –
@KurtBourbaki (Тем временем я пытался запустить по очереди профайлер, но это не удалось). Я говорил о списках вообще, и я имел в виду назначение элемента. ('[].append' может привести к распределению памяти, но это скрыто самим объектом списка) –
Итак, это быстрее, потому что мы присваиваем значения «True» или «False» вместо выделения новых целых чисел, правильно? Вы знаете что-то о Java? Например: бы вектор бит был более эффективным, чем логический массив? –