异或运算原理及使用

异或运算在编程中有着广泛应用,包括位操作、数据交换和问题解决。本文介绍了异或的基本运算法则,如a⊕a=0、a⊕b=b⊕a,以及异或的性质。并列举了按位异或的常见用途,如翻转特定位、无临时变量的数值交换。还通过举例说明如何利用异或解决寻找序列中缺失数字的问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

异或,英文为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;

 

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值