为什么三次异或操作可以交换两个数

a和b是两个整数,经过以下三次异或操作,可以达到交换目的:
a = a ^ b;
b = a ^ b;
a = a ^ b;

首先要理解,什么是^(异或)操作:
  二进制两数运算结果:
  0 ^ 0 = 0
  0 ^ 1 = 1
  1 ^ 0 = 1
  1 ^ 1 = 0
相同为0,不同为1

假设:
 a = 10 , 其二进制数为: 1010
 b = 12 , 其二进制数为: 1100
如果a和b交换,在二进制数看来,因为第一位和最后一位数相同,所以中间两位数只要交换一下就行了
这个交换的过程,因为二制进中只有两个数值(0和1),所以实际上只是0变1,1变0
所以总结出来就是,交换两个数,就是它们的二进制数不一样的位数,只要各自取反(0变1,1变0)就行了
如果两个数转换为二进制数的位数不一样,只要短的那个前面补0即可。

第一次  a = a ^ b 
其结果a的值为: 0110,去掉前面的0,即110,仔细观察,此时的a其实是一个差异值(位数上的值是1的表示有差异),它找到了原来a和b的二进制数不相同的位数,1表示不相同,0表示相同
110表示,原来a和b在二进制里中间两位数是不一样的,这样就找到了在二进制中哪些位数是a和b不相同的。

第二次  b = a ^ b 
此时a是一个差异值,b还是原来的数,它是如何变成a的原值呢
异或运算可以从另一个角度去理解:
当左边的数为0时,其结果就和右边的数一样
当左边的数为1时,其结果就和右边的数取反
所以此时的a ^ b就是:
左边的a,如果位数为0,表示原值a和b的这个位数是一样的,那么b的这个位数就不需要改
左边的a,如果位数为1,表示原值a和b的这个位数是不一样的,那么b的这个位数就需要取反
所以b原来的值1100,前后两位数不变,中间两位数取反,其结果就是1010,这就符合上面交换两个数的结论。

第三次  a = a ^ b 

此时a还是差异值110,b已经变成原来a的值了,那么a ^ b还是像上面那样,对于b(现在已经是原来a的值),相同的位数不变,不同的位数取反,其结果就是原来b的值。

简单结论:

异或操作找出二进制数不相同的位数,然后各自取反

原文地址:https://www.cnblogs.com/bsc2012/p/9260436.html

时间: 2024-11-09 01:40:11

为什么三次异或操作可以交换两个数的相关文章

异或交换两个数的陷阱【转】

前面我们谈到了,可用通过异或运算交换两个数,而不需要任何的中间变量. 如下面: void exchange(int &a, int &b) { a ^= b; b ^= a; a ^= b; } 然而,这里面却存在着一个非常隐蔽的陷阱. 通常我们在对数组进行操作的时候,会交换数组中的两个元素,如exchang(&a[i], &b[j]), 这儿如果i==j了(这种情况是很可能发生的),得到的结果就并非我们所期望的. void main() { int a[2] = {1, 

最简单的交换两个数

最简单的交换两个数: 用到了异或运算符: 1 void A(int &a, int &b){ 2 a = a^b; 3 b = a^b; 4 a = a^b; 5 } 第二行 a=a^b; 第三行 b=a^b相当于b=a^b^b相当于b=a,将第二行算式代入; 第四行 a=a^b相当于a=a^b^a相当于a=b,将第二行第三行代入; 这样不用借助第三个辅助变量就能交换两个数的值; 用到的是:一个数与自身按位异或运算等于0:一个数与0按位异或运算是本身;

如何不使用第三个变量来交换两个数的值

最近在看<c++从入门到精通>自学c++,里面有一道课后题是如何做到不适用第三个变量来交换两个数的值,以下是我在网上查找到的资料,记录下并作为笔记. 题目:a=10,b=15,将a / b的值互换. 通常我们的做法是(尤其是在学习阶段):定义一个新的变量,借助它完成交换.代码如下:      int a,b;      a=10; b=15;      int t;      t=a; a=b; b=t;      这种算法易于理解,特别适合帮助初学者了解计算机程序的特点,是赋值语句的经典应用

交换两个数的值,不适用第三个变量

交换两个数的值,不适用第三个变量 一.源代码:SwapTwoNumber.java 1 package cn.com.zfc.help; 2 3 /** 4 * 不适用中间变量交换两个数 5 * 6 * @author zfc 7 * 8 */ 9 public class SwapTwoNumber { 10 public static void main(String[] args) { 11 12 /* 1.第一种交换方式,位运算:^(异或) */ 13 System.out.printl

【编程题】不引入第三个变量,而交换两个变量的值

不引入第三个变量,而交换两个变量的值 方法一:算术运算 1 int a,b; 2 a=10;b=12; 3 a=b-a; //a=2;b=12 4 b=b-a; //a=2;b=10 5 a=a+b; //a=12;b=10 它的原理:把a,b看做数轴上的两个点. 第一句"a=b-a"求出了ab两点之间的距离,并且将其保存在a中: 第二句"b=b-a"求出了a到原点的距离(b到原点的距离减去ab两点距离),并且将其保存在b中: 第三句"a=b+a"

异或交换两个数;实现pow(int x, int y) ,即x的y次方

问题1:异或交换两个数 假设x=2:y=3,我们的目标是(没有蛀牙!!)交换x,y的值: 利用异或的特殊性:x^x=0 即两个相同数字异或后值为0: 解决: 令x=x^y=2^3 令y=x^y=x^y^y=2^3^3=2(此时x=x^y) 令x=x^y=x^y^2=2^3^2=3(此时x=x^y:y=2) 问题2:实现pow(int x, int y) ,即x的y次方 x的y次方就是有y个x连续乘机,代码如下: #include <stdio.h> #include <stdlib.h&

三种传值方式遇上两个数的交换

最近在学习数据结构的时候发现以前学的C++的有些东西都忘了,特别是老师提到的三种传值的方式——单向值传递,地址传递,双向引用传递:为此,我这里用如何交换两个数的例子来说明一下三种传值方式的机制. 先看看源代码: 1 #include<iostream> 2 using namespace std; 3 int swap1(int m1,int m2)//单向值传递 4 { 5 int temp = m1; 6 m1 = m2; 7 m2 = temp; 8 cout<<m1<

交换两个数的C语言程序

今天是第一次接触C语言,之前有一点C++的基础,所以学习起来还挺顺手的.下来分享一下写的一个关于交换两个数的C语言代码.可能这些还存在很大的问题,希望大家可以指正. 方法一:允许创建第三个变量 #include<stdio.h> int main() { int a=10; int b=20; int tmp=a; a=b; b=tmp; printf("%d\n",a); printf("%d\n",b); return 0; } 方法二:不创建新的变

不使用中间变量交换两个数. 求平均数考虑溢出

#define _CRT_SECURE_NO_WARNINGS 1 #include<stdio.h> #include<stdlib.h> //不使用中间变量交换两个数的值 void exchange_num(int *a, int *b) { ①* a =*a + *b;    //适用范围广 * b = *a -* b; * a =* a - *b; ②* a = (*a )*(*b); * b = (*a )/(*b); * a = (*a ) / (*b);//当两个数有