Вопрос с собеседования · Основы
Какие битовые операции вы знаете и где они применяются?
JuniorЧисла в компьютере
Ещё спрашивают так:
- Как проверить, что число — степень двойки?
- Как хранить набор флагов в одном числе?
- Почему размер HashMap — степень двойки?
Коротко
AND &, OR |, XOR ^, NOT ~, сдвиги << и >> работают с каждым битом отдельно и стоят один такт.
- Флаги: поставить
x | f, снятьx & ~f, проверитьx & f != 0 - Степень двойки:
x > 0 and x & (x − 1) == 0 - Остаток от деления на 2ᵏ:
x & (2ᵏ − 1)— так HashMap выбирает корзину
А ещё XOR: a ^ a = 0 — поиск непарного элемента, контрольные суммы
Подробно
Операции:
a & b— бит 1, если он 1 в обоих (пересечение, маскирование);a | b— бит 1, если он 1 хотя бы в одном (объединение);a ^ b— бит 1, если биты различаются. Свойства:a ^ a = 0,a ^ 0 = a, операция обратима;~a— инверсия всех бит; в дополнительном коде~a = −a − 1;a << k— умножение на 2ᵏ,a >> k— деление на 2ᵏ с округлением вниз (для знаковых — арифметический сдвиг), в Java ещё>>>— логический.
Где применяют:
- флаги и права — набор булевых признаков в одном числе: права файла
rwxв Unix (chmod 754),EnumSetв Java хранит множество как биты; - маска вместо остатка — если ёмкость степень двойки,
hash % nравноhash & (n − 1), а это быстрее деления. ПоэтомуHashMapдержит размер степенью двойки, а перед маской перемешивает старшие биты хеша (h ^ (h >>> 16)), иначе младшие биты плохого хеша дали бы коллизии; - приёмы —
x & (x − 1)убирает младшую единицу (степень двойки, подсчёт единиц),x & −xоставляет только младшую единицу (дерево Фенвика),x >> 31— знак; - XOR — найти единственный непарный элемент массива за O(n) и O(1) памяти; чётность и RAID-5; простейшее шифрование «одноразовым блокнотом»;
- битовые множества и фильтры —
BitSet, битовые карты в индексах баз, фильтр Блума; - сети — маска подсети:
ip & maskдаёт адрес сети.
Порядок байтов (endianness) — отдельный вопрос: битовые операции работают со значением, а не с его раскладкой в памяти, поэтому от него не зависят.
Пример
READ, WRITE, EXEC = 4, 2, 1
perm = READ | WRITE # 6
perm & EXEC != 0 # False — нет права на запуск
perm &= ~WRITE # 4 — сняли запись
def is_pow2(x): return x > 0 and x & (x - 1) == 0
def single(nums): # каждый встречается дважды, кроме одного
r = 0
for x in nums: r ^= x
return r
single([4, 1, 2, 1, 2]) # 4Что хотят услышать
- Таблица операций и смысл сдвигов как умножения и деления на 2ᵏ.
- Флаги в маске: поставить, снять, проверить.
- Приём
x & (x − 1)и проверка степени двойки. - Пример из реального кода: HashMap, права Unix, маска подсети.
Частые ошибки
- Путать
&и&&,|и||— логические операторы с ленивым вычислением. - Забывать про приоритет: в Java и Python
x & 1 == 0разбирается не так, как кажется.
Проверьте себя
Несколько верных вариантов. Подумайте, потом откройте ответ.
Показать варианты и ответ
- ✓x | f — поставить флаг, x & ~f — снять
- ✓x & (x − 1) == 0 при x > 0 — проверка степени двойки
- ✗a ^ a всегда равно a
- ✓x & (2ᵏ − 1) — остаток от деления на 2ᵏ
Что спросят дальше
- Как устроена хеш-таблица? Junior
Связанные вопросы
Партнёр платформы
Разбор собеседования
Разбор собеседования с sotto
После собеседования sotto разбирает разговор: оценка, каждый вопрос — хорошо, частично или слабо, чего не хватило в ответе и над чем поработать к следующему разу. Первые 30 минут бесплатно.