Получить доступ

Какие битовые операции вы знаете и где они применяются?

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 — поиск непарного элемента, контрольные суммы

Так подсказку видит пользователь sotto на живом собеседовании — за пару секунд, пока вы думаете вслух.

Попробуйте сами

Число изнутри: дополнительный код и плавающая точка

Подробно

Операции:

  • 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 разбирается не так, как кажется.

Что спросят дальше

Связанные вопросы

Закрытая бета

Подсказки на собеседовании — в реальном времени

sotto слышит вопрос интервьюера и показывает короткий ответ и план, как в блоке «Коротко». Оставьте контакт — пришлём доступ и промокод.

  • Промокод на 2 часа — сверх пробных 30 минут
  • Программа для Windows — скачать сразу, войти — через Яндекс ID или VK ID
  • Прямая связь с разработчиком: что улучшить — сделаем