深入理解异或运算 xor 的含义——再探不使用加减乘除实现加法运算、不使用额外空间交换两个变量的值

    今天看到感知机,了解感知机无法解决异或问题。然后深入了解了一下异或,整理如下:

    直观上来说,异或运算就是如果两个数字(0或者1)相同,则输出为0; 如果两个数字(0或者1)不相同,就输出为1。数学上比较好理解,但是为什么会有异或这种运算呢?首先,咱们从哲学的角度理解:我们经常听到否定的否定是肯定,对的,如果将哲学中的肯定看成1,否定看成0,那么

                              肯定的肯定是肯定   ----->  1 xor 1 =0

                              否定的否定是肯定   ----->  0 xor 0 = 0

                              肯定的否定是否定   -----> 1 xor 0 = 1

                              否定的肯定是否定   ----->  0 xor 1 = 1

生理学角度来解释,如果男人代表1,女人代表0,那么,两个男人或者是两个女人,都是生不出孩子的。只有一个男人和一个女人,才能够繁衍后代。怎么繁衍的呢?通过 xor ,我这么解释,是不是 xor 这个符号一下子就记住了??

    那么,异或运算可以用来干啥?异或也叫“半加运算”,即不考虑进位的加法。不带进位的加法有啥用?先看一下我之前的一个博客:不使用加减乘除,实现加法运算

从计算机的角度看数据,都是二进制的。所以,我们可以利用位操作符,位与(&)、位或(|)、位异或(^)。而加法的实现,最主要的就是确定什么时候进位。

程序如下:

int add(int a, int b)  
{  
    if (a == 0)  
        return b;  
    if (b == 0)  
        return a;  
    int p1 = a&b;//位与。  
    p1 = p1 << 1;//这两句只考虑进位   
    int p2 = a^b;//位异或。不考虑进位   
    return add(p2, p1);    //结束的标志是a为0了,或者b为0了  
}  
int main()  
{  
    int x = 3, y = 2;  
    int sum = 0;  
    sum = add(x,y);  
    cout << sum << endl;     
      
}  

    我再详细解释一下这个程序:在add()函数中,p2 = a^b,如果有进位,就不用管它。比如 0+0=0, 0+1 = 1, 1+0  = 1, 1 +1 = 0。看到没,1+1 是等于0 的,那么进位呢?进位靠 & 运算来实现,p1 只考虑进位,也就是说,如果 1 + 1 结果是 1, 但是此时的这个1应该往前面进一位,变成 10, 所以,有了p1 = p1 << 1。 那么,到什么时候结束呢?只有一种可能,没有进位了,也就是说 p1 为0 了,那么此时的加法结果就是不考虑进位的p2 了。

    最后,解释一下为什么要递归 add()函数。实际上, 函数只需要执行两次就够了,执行到第二次的时候,我们就能保证P1 移位以后,为0. 此时,返回 p2 即可。所以,代码还可以这样优化:

()   

    突然想到了一题,拿来回顾一下,通过异或运算,还可以实现不使用额外空间,交换两个变量的值

    我们知道,异或运算有这个性质:a xor b xor a = b。举个例子,对于数值 A,B ,通过 A^B 可以得到 C。如果先把C 保存下来,这个C可以通过 A ,B 的任意一个值,还原另外一个值。也就是,C^A = B,  C^B = A。实现A和B 的值交换,可由下面三步骤实现

    1)  A = A ^ B   //  利用A存储了C,但是B还是存在的,原来的A,可以由现在的A和B 还原

    2) B = A ^ B  // 还原出了A ,赋值给B 。此时C 还是没有发生改变的。此时 B 存储的是原来的 A , 通过这个原来的A和现在的C,就可以还原原来的B

    3) A = A^ B  // 还原出原来的B ,赋值给A ,最终实现了A和B 的交换


知识点补充:

按位异或的3个特点:
(1) 0^0=0,0^1=1 0异或任何数=任何数
(2) 1^0=1,1^1=0 1异或任何数-任何数取反
(3) 任何数异或自己=把自己置0
按位异或的几个常见用途:
(1) 使某些特定的位翻转
例如对数10100001的第2位和第3位翻转,则可以将该数与00000110进行按位异或运算。
      10100001^00000110 = 10100111

  • 16
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值