异或运算:二进制世界的神奇魔术

一、什么是异或运算?

异或(XOR,Exclusive OR)是计算机科学中最基础也最有趣的位运算之一。它的名字”异或”很贴切地描述了其含义:”异”表示不同,”或”表示逻辑或,合起来就是”当且仅当不同时为真”。

基本定义

对于两个二进制位:

  • 0 XOR 0 = 0
  • 0 XOR 1 = 1
  • 1 XOR 0 = 1
  • 1 XOR 1 = 0

用简单的话说:相同为0,不同为1

二、C++中的异或运算符

在C++中,异或运算使用符号 ^

int a = 5;    // 二进制:0101
int b = 3;    // 二进制:0011
int c = a ^ b; // 结果是 6,二进制:0110

基本用法示例

#include <iostream>
using namespace std;

int main() {
    int x = 12;  // 二进制:1100
    int y = 7;   // 二进制:0111
    
    cout << "x = " << x << " (" << bitset<4>(x) << ")" << endl;
    cout << "y = " << y << " (" << bitset<4>(y) << ")" << endl;
    cout << "x ^ y = " << (x ^ y) << " (" << bitset<4>(x ^ y) << ")" << endl;
    // 输出:x ^ y = 11 (1011),因为 1100 ^ 0111 = 1011
    
    return 0;
}

三、异或运算的五大神奇性质

1. 交换律

a ^ b = b ^ a

2. 结合律

(a ^ b) ^ c = a ^ (b ^ c)

3. 自反性(最重要的性质!)

a ^ a = 0
a ^ 0 = a

4. 可逆性

如果 a ^ b = c
那么 a ^ b ^ b = a = c ^ b

5. 与0的关系

a ^ 0 = a
0 ^ a = a

四、异或运算的经典应用

1. 不使用临时变量交换两个数

void swap(int &a, int &b) {
    a = a ^ b;  // 步骤1:a = a ^ b
    b = a ^ b;  // 步骤2:b = (a ^ b) ^ b = a ^ (b ^ b) = a ^ 0 = a
    a = a ^ b;  // 步骤3:a = (a ^ b) ^ a = (a ^ a) ^ b = 0 ^ b = b
}

2. 找出数组中唯一出现一次的数

int findSingleNumber(vector<int>& nums) {
    int result = 0;
    for (int num : nums) {
        result ^= num;  // 利用 a ^ a = 0
    }
    return result;
}
// 如果数组中只有一个数出现一次,其他都出现两次,这个函数能找出那个数

3. 奇偶校验

// 计算一个数的二进制表示中1的个数的奇偶性
bool parity(int x) {
    bool parity = false;
    while (x) {
        parity ^= (x & 1);  // 每次翻转奇偶性
        x >>= 1;
    }
    return parity;
}

4. 简单的加密和解密

string encryptDecrypt(const string& data, char key) {
    string result = data;
    for (int i = 0; i < data.length(); i++) {
        result[i] = data[i] ^ key;  // 加密
    }
    return result;
}
// 注意:同样的操作可以用于解密!

五、实际编程中的应用场景

1. 算法竞赛中的应用

// 前缀异或:计算子数组异或和
vector<int> prefixXor(const vector<int>& arr) {
    int n = arr.size();
    vector<int> prefix(n + 1, 0);
    for (int i = 0; i < n; i++) {
        prefix[i + 1] = prefix[i] ^ arr[i];
    }
    return prefix;
}

2. 游戏开发:棋盘状态判断

// 判断井字棋是否有玩家获胜
bool checkTicTacToe(const vector<vector<char>>& board) {
    const int winMasks[] = {7, 56, 448, 73, 146, 292, 273, 84};
    int player1 = 0, player2 = 0;
    
    // 将棋盘转换为位掩码
    for (int i = 0; i < 9; i++) {
        int bit = 1 << i;
        if (board[i/3][i%3] == 'X') player1 ^= bit;
        else if (board[i/3][i%3] == 'O') player2 ^= bit;
    }
    
    // 检查是否有获胜
    for (int mask : winMasks) {
        if ((player1 & mask) == mask) return true;  // 玩家1获胜
        if ((player2 & mask) == mask) return true;  // 玩家2获胜
    }
    return false;
}

3. 内存优化:用异或链表实现双向链表

class XORNode {
public:
    int data;
    XORNode* both;  // 存储prev ^ next的指针
    
    XORNode(int val) : data(val), both(nullptr) {}
};

六、注意事项和常见陷阱

1. 优先级问题

int a = 5, b = 3, c = 2;
int result1 = a ^ b & c;  // 错误:&优先级高于^
int result2 = (a ^ b) & c;  // 正确

2. 浮点数不能进行异或

// 错误!
float f1 = 3.14, f2 = 2.71;
// float f3 = f1 ^ f2;  // 编译错误!

3. 注意符号位

int x = -1;  // 二进制:111...111
int y = 1;   // 二进制:000...001
int z = x ^ y;  // 结果是 -2,因为符号位被改变

七、性能比较

异或运算是CPU中最快的操作之一,因为它只需要简单的硬件门电路:

操作时钟周期备注
XOR1最快
ADD1-3与XOR相当
MUL3-4较慢
DIV10-20最慢

八、练习题

  1. 基础题:交换两个变量的值,不使用临时变量
  2. 进阶题:找出数组中两个只出现一次的数字(其他数字都出现两次)
  3. 挑战题:实现一个函数,判断一个数的二进制表示是否是回文
  4. 实际应用:使用异或实现简单的校验和计算

九、总结

异或运算虽然看起来简单,但其应用却异常广泛:

  • 它是加密算法的基础
  • 在算法优化中经常使用
  • 可以高效处理二进制问题
  • 是许多巧妙算法的核心

掌握异或运算不仅仅是掌握一个运算符,更是理解了一种解决问题的思维方式。当你面对一个问题时,不妨想想:能不能用异或来解决?

记住这个魔法公式a ^ a = 0a ^ 0 = a,这两个简单的公式能解决无数复杂的问题!


学习建议:多写代码实践,从简单的例子开始,逐步尝试解决更复杂的问题。异或运算的魅力只有通过实际应用才能真正体会到。

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇