异或运算原理及使用

异或,英文为exclusive OR,缩写成xor。异或(xor)是一个数学运算符。它应用于逻辑运算。异或的数学符号为“⊕”,计算机符号为“xor”。其运算法则为:

a⊕b = (¬a ∧ b) ∨ (a ∧¬b)(¬为非)

异或也叫半加运算,其运算法则相当于不带进位的二进制加法:二进制下用1表示真,0表示假,则异或的运算法则为:0⊕0=0,1⊕0=1,0⊕1=1,1⊕1=0(同为0,异为1),这些法则与加法是相同的,只是不带进位,所以异或常被认作不进位加法。

运算法则:

1. a ⊕ a = 0

2. a ⊕ b = b ⊕ a

3. a ⊕b ⊕ c = a ⊕ (b ⊕ c) = (a ⊕ b) ⊕ c;

4. d = a ⊕ b ⊕ c 可以推出 a = d ⊕ b ⊕ c.

5. a ⊕ b ⊕ a = b.(可由3推出)

按位异或的几个常见用途:

c语言中使用^来表示异或运算(很多语言^表示乘方)

我们先来计算一下这个问题,5^3=?

5和3转为二进制分别为:0101 、0011,所以0101^0011=0110,换为十进制即为6。

6^3=0110^0011=0101,化为10进制即为5,也验证了上面第4条运算法则

(1) 使某些特定的位翻转

例如对数10100001的第2位和第3位翻转,则可以将该数与00000110进行按位异或运算。

10100001^00000110 = 10100111

(2) 实现两个值的交换,而不必使用临时变量。

例如交换两个整数a=10100001,b=00000110的值,可通过下列语句实现:

a = a^b;   //a=10100111

b = b^a;   //b=10100001

a = a^b;   //a=00000110

(3)最后举一个小例子,leetcode上的习题:

给定一个包含 0, 1, 2, ..., n 中 n 个数的序列,找出 0 .. n 中没有出现在序列中的那个数。

例如:输入: [3,0,1] 输出: 2

           输入: [9,6,4,2,3,5,7,0,1] 输出: 8

这道题方法较多,比如们可以求出 [0..n]的和,减去数组中所有数的和,就得到了缺失的数字。

    int missingNumber(vector<int>& nums) {
        int n=nums.size();
        int sum=n*(n+1)/2;
        for(int i=0;i<n;i++)sum-=nums[i];
        return sum;
    }

我们还可以使用位运算的方法,由于异或运算(XOR)满足结合律,并且对一个数进行两次完全相同的异或运算会得到原来的数,因此我们可以通过异或运算找到缺失的数字。

我们知道数组中有 n 个数,并且缺失的数在 [0..n]中。因此我们可以先得到 [0..n] 的异或值,再将结果对数组中的每一个数进行一次异或运算。未缺失的数在 [0..n] 和数组中各出现一次,因此异或后得到 0。而缺失的数字只在 [0..n]中出现了一次,在数组中没有出现,因此最终的异或结果即为这个缺失的数字。代码如下:

int missingNumber(vector<int>& nums) {
    int ans =nums.size(), i;
    for(i = 0; i < nums.size(); i++){
        ans ^= i ^ nums[i];
    }
    return ans;
发布了33 篇原创文章 · 获赞 148 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/qq_40692109/article/details/104223131