一次性搞懂异或^

异或(XOR) 是一种基础的位运算,符号为 ^。它针对二进制位进行操作,具有独特的逻辑特性,在算法优化、数据处理、加密等场景中应用广泛。

异或的核心原理

异或是对两个操作数的每一位二进制位进行独立运算,运算规则为:相同为 0,不同为 1

(即:0 ^ 0 = 00 ^ 1 = 11 ^ 0 = 11 ^ 1 = 0)。

示例:

以整数 3(二进制 011)和 5(二进制 101)的异或运算为例:

  011  (3)
^ 101  (5)
--------
  110  (6)

结果为 6(二进制 110),每一位均遵循 “相同为 0,不同为 1” 的规则。

异或的关键性质

异或的实用价值源于其独特的数学性质,这些性质是解决问题的核心工具:

  1. 自反性x ^ x = 0任何数与自身异或,结果为 0(二进制每一位都相同,均变为 0)。

  2. 恒等性x ^ 0 = x任何数与 0 异或,结果为其自身(二进制每一位与 0 运算,保持原数不变)。

  3. 交换律a ^ b = b ^ a异或运算的顺序不影响结果。

  4. 结合律(a ^ b) ^ c = a ^ (b ^ c)异或运算的分组不影响结果。

  5. 还原律a ^ b ^ b = a一个数连续异或同一个数两次,结果为原数(利用 b ^ b = 0 和 a ^ 0 = a 推导)。

实用价值

不使用临时变量交换两个变量的值

传统交换两个变量需要临时变量(如 int temp = a; a = b; b = temp;),而异或可通过性质 5 实现无临时变量交换:

 a ^= b;  // a = a ^ b(此时 a 存储两数异或结果)
 b ^= a;  // b = b ^ (a ^ b) = a(利用结合律和 b^b=0,还原出 a)
 a ^= b;  // a = (a ^ b) ^ a = b(利用 a^a=0,还原出 b)

明确规定a != b 的时候才行,如果a=b就都清零了。

 查找数组中 “只出现一次的数字”

        若数组中除一个元素外,其余元素均出现两次,可利用异或的 x ^ x = 0 和 x ^ 0 = x 性质快速找到唯一元素:所有元素异或的结果 = 唯一出现一次的元素(因为成对的元素异或后为 0,0 与唯一元素异或后为其本身)。

leetcode例题

class Solution {
public:
    int singleNumber(vector<int>& nums) {
        int n = nums.size();
        int t = 0;
        for(auto x:nums){ t^=x;}
        return t;
    }
};
翻转二进制中的特定位

若需翻转一个整数的某几位(0 变 1,1 变 0),可利用异或与 “掩码(mask)” 结合:

  • 掩码中需翻转的位设为 1,其余位设为 0;
  • 原数与掩码异或后,目标位被翻转,其余位不变(因 x ^ 0 = x)。

示例:翻转 num 的第 k 位(从 0 开始计数):

#include <iostream>
using namespace std;

int flipBit(int num, int k) {
    return num ^ (1 << k);  // 1 << k 生成第 k 位为 1 的掩码
}

int main() {
    int num = 5;  // 二进制 101
    int flipped = flipBit(num, 1);  // 翻转第 1 位(0 基)
    cout << flipped << endl;  // 二进制 111(7),第 1 位从 0 变为 1
    return 0;
}
 判断两个整数是否同号

整数的最高位(符号位):正数为 0,负数为 1。

  • 若两数同号,符号位异或结果为 0(0^0=0 或 1^1=0);
  • 若两数异号,符号位异或结果为 1(0^1=1)。

利用这一特性可快速判断同号性:

(a ^ b) >= 0;

>=0就是同号,反之异号。

简单加密与解密

利用异或的 “还原律”(a ^ key ^ key = a),可实现轻量字符加密:

  • 加密:密文 = 明文 ^ 密钥
  • 解密:明文 = 密文 ^ 密钥
#include <iostream>
#include <string>
using namespace std;

// 加密/解密函数(同一函数,因异或两次密钥还原)
string xorEncryptDecrypt(const string& data, char key) {
    string result = data;
    for (char& c : result) {
        c ^= key;  // 异或密钥
    }
    return result;
}

int main() {
    string plaintext = "Hello, XOR!";
    char key = 'k';  // 密钥(任意字符)

    string ciphertext = xorEncryptDecrypt(plaintext, key);
    cout << "加密后:" << ciphertext << endl;  // 乱码

    string decrypted = xorEncryptDecrypt(ciphertext, key);
    cout << "解密后:" << decrypted << endl;  // 输出 Hello, XOR!
    return 0;
}
加密后:#GK3$9J
解密后:Hello, XOR!
计算汉明距离

        汉明距离是指两个等长字符串(通常是二进制字符串或二进制数)中,对应位置上字符不同的数量

int hammingDistance(int x, int y) {
    int xorResult = x ^ y; // 不同的位为1
    int distance = 0;
    // 统计1的个数(汉明重量)
    while (xorResult) {
        xorResult &= xorResult - 1; // Brian Kernighan算法
        distance++;
    }
    return distance;
}

点击学习Brian Kernighan算法 

总结

异或运算高效简洁,并且有多种妙手

posted @ 2025-09-28 18:13  mc12356  阅读(497)  评论(0)    收藏  举报  来源