Главное свойство XOR которое делает его полезным: a XOR a = 0 и a XOR 0 = a. То есть применить XOR дважды с одним и тем же числом - вернуть исходное. Это самообратная операция.
Три главных применения:
1. Найти одиночный элемент в массиве за O(n) и O(1) памяти
Классическая задача LeetCode: в массиве все числа встречаются дважды кроме одного. Найти его.
def single_number(nums):
result = 0
for n in nums:
result ^= n
return result
# [2, 3, 2, 1, 3] -> все пары уничтожают друг друга, остается 1
print(single_number([2, 3, 2, 1, 3])) # 1
Обычный OR тут не поможет - он не умеет "отменять" себя.
2. Swap двух переменных без временной переменной
a, b = 5, 9
a ^= b
b ^= a
a ^= b
# a = 9, b = 5
В Python это бесполезно (есть a, b = b, a), но в C/asm на embedded это реальная экономия регистра.
3. Простейшее шифрование (одноразовый блокнот)
key = 0b10110011
message = 0b01001010
encrypted = message ^ key # зашифровали
decrypted = encrypted ^ key # расшифровали тем же ключом
assert decrypted == message # True
XOR-шифр с действительно случайным ключом той же длины что и сообщение - единственный теоретически абсолютно стойкий шифр (one-time pad). На практике проблема в дистрибуции ключей.
Итого: XOR незаменим когда нужна обратимая битовая операция без потери информации.
Пример с single_number прямо щелкнуло в голове. Спасибо, теперь понял зачем это вообще нужно.