长沙做企业网站,wordpress如何添加商桥,国际英文网站,wifi网络管理异或运算相当与mod 2运算#xff1a; 1^1 0, 1^0 1, 0^1 1, 0 ^ 0 0 (11)%2 0, (10)%2 1, (01)%2 1, (00)%2 0 Single Number II 这题从所有出现3次的数组中找只出现一次的数#xff0c;相当于mod 3运算 以下部分为转载#xff1a; 转载#xff1a;http://blog.csdn…异或运算相当与mod 2运算 1^1 0, 1^0 1, 0^1 1, 0 ^ 0 0 (11)%2 0, (10)%2 1, (01)%2 1, (00)%2 0 Single Number II 这题从所有出现3次的数组中找只出现一次的数相当于mod 3运算 以下部分为转载 转载http://blog.csdn.net/kingoverlord/article/details/8825721 不使用第三方变量交换两个变量的值这需要进行位操作,必较麻烦的, 在学习程序语言和进行程序设计的时候交换两个变量的值是经常要使用的。通常我们的做法是尤其是在学习阶段定义一个新的变量借助它完成交换。代码如下 int a,b; a10; b15; int t; ta; ab; bt; 这种算法易于理解特别适合帮助初学者了解计算机程序的特点是赋值语句的经典应用。在实际软件开发当中此算法简单明了不会产生歧义便于程序员之间的交流一般情况下碰到交换变量值的问题都应采用此算法以下称为标准算法。上面的算法最大的缺点就是需要借助一个临时变量。那么不借助临时变量可以实现交换吗答案是肯定的这里我们可以用三种算法来实现1算术运算2指针地址操作3位运算。1 算术运算 简单来说就是通过普通的和-运算来实现。代码如下 int a,b; a10;b12; ab-a; //a2;b12 bb-a; //a2;b10 aba; //a10;b10 通过以上运算a和b中的值就进行了交换。表面上看起来很简单但是不容易想到尤其是在习惯标准算法之后。 它的原理是把a、b看做数轴上的点围绕两点间的距离来进行计算。 具体过程第一句“ab-a”求出ab两点的距离并且将其保存在a中第二句“bb-a”求出a到原点的距离b到原点的距离与ab两点距离之差并且将其保存在b中第三句“aba”求出b到原点的距离a到原点距离与ab两点距离之和并且将其保存在a中。完成交换。此算法与标准算法相比多了三个计算的过程但是没有借助临时变量。以下称为算术算法 2 指针地址操作 因为对地址的操作实际上进行的是整数运算比如两个地址相减得到一个整数表示两个变量在内存中的储存位置隔了多少个字节地址和一个整数相加即“a10”表示以a为基地址的在a后10个a类数据单元的地址。所以理论上可以通过和算术算法类似的运算来完成地址的交换从而达到交换变量的目的。即int *a,*b; //假设 *anew int(10); *bnew int(20); //a0x00001000h,b0x00001200h a(int*)(b-a); //a0x00000200h,b0x00001200h b(int*)(b-a); //a0x00000200h,b0x00001000h a(int*)(bint(a)); //a0x00001200h,b0x00001000h 通过以上运算a、b的地址真的已经完成了交换且a指向了原先b指向的值b指向原先a指向的值了吗上面的代码可以通过编译但是执行结果却令人匪夷所思原因何在 首先必须了解操作系统把内存分为几个区域系统代码/数据区、应用程序代码/数据区、堆栈区、全局数据区等等。在编译源程序时常量、全局变量等都放入全局数据区局部变量、动态变量则放入堆栈区。这样当算法执行到“a(int*)(b-a)”时a的值并不是0x00000200h而是要加上变量a所在内存区的基地址实际的结果是0x008f0200h其中0x008f即为基地址0200即为a在该内存区的位移。它是由编译器自动添加的。因此导致以后的地址计算均不正确使得a,b指向所在区的其他内存单元。再次地址运算不能出现负数即当a的地址大于b的地址时b-a0系统自动采用补码的形式表示负的位移由此会产生错误导致与前面同样的结果。有办法解决吗当然以下是改进的算法 if(ab) { a(int*)(b-a); b(int*)(b-(int(a)0x0000ffff)); a(int*)(b(int(a)0x0000ffff)); } else { b(int*)(a-b); a(int*)(a-(int(b)0x0000ffff)); b(int*)(a(int(b)0x0000ffff)); } 算法做的最大改进就是采用位运算中的与运算“int(a)0x0000ffff”因为地址中高16位为段地址后16位为位移地址将它和0x0000ffff进行与运算后段地址被屏蔽只保留位移地址。这样就原始算法吻合从而得到正确的结果。此算法同样没有使用第三变量就完成了值的交换与算术算法比较它显得不好理解但是它有它的优点即在交换很大的数据类型时它的执行速度比算术算法快。因为它交换的时地址而变量值在内存中是没有移动过的。以下称为地址算法3 位运算 通过异或运算也能实现变量的交换这也许是最为神奇的请看以下代码 int a10,b12; //a1010^b1100; aa^b; //a0110^b1100; ba^b; //a0110^b1010; aa^b; //a110012;b1010; 此算法能够实现是由异或运算的特点决定的通过异或运算能够使数据中的某些位翻转其他位不变。这就意味着任意一个数与任意一个给定的值连续异或两次值不变。 即a^b^ba。将aa^b代入ba^b则得ba^b^ba;同理可以得到ab^a^ab;轻松完成交换。 以上三个算法均实现了不借助其他变量来完成两个变量值的交换相比较而言算术算法和位算法计算量相当地址算法中计算较复杂却可以很轻松的实现大类型比如自定义的类或结构的交换而前两种只能进行整形数据的交换理论上重载“^”运算符也可以实现任意结构的交换。 介绍这三种算法并不是要应用到实践当中而是为了探讨技术展示程序设计的魅力。从中可以看出数学中的小技巧对程序设计而言具有相当的影响力运用得当会有意想不到的神奇效果。而从实际的软件开发看标准算法无疑是最好的能够解决任意类型的交换问题。 深入理解按位异或运算符 2009-02-10 17:25:14 标签休闲 按位异或运算符 职场 原创作品允许转载转载时请务必以超链接形式标明文章 原始出处 、作者信息和本声明。否则将追究法律责任。http://kapok.blog.51cto.com/517862/129941 参与运算的两个值如果两个相应bit位相同则结果为0否则为1。即 0^0 0 1^0 1 0^1 1 1^1 0例如10100001^0001000110110000按位异或的3个特点:(1) 0^00,0^11 0异或任何数任何数(2) 1^01,1^10 1异或任何数任何数取反(3) 任何数异或自己把自己置0 按位异或的几个常见用途:(1) 使某些特定的位翻转 例如对数10100001的第2位和第3位翻转则可以将该数与00000110进行按位异或运算。 10100001^00000110 10100111(2) 实现两个值的交换而不必使用临时变量。 例如交换两个整数a10100001b00000110的值可通过下列语句实现 a a^b //a10100111 b b^a //b10100001 a a^b //a00000110(3) 在汇编语言中经常用于将变量置零 xor aa(4) 快速判断两个值是否相等 举例1: 判断两个整数ab是否相等则可通过下列语句实现 return ((a ^ b) 0) 举例2: Linux中最初的ipv6_addr_equal()函数的实现如下: static inline int ipv6_addr_equal(const struct in6_addr *a1, const struct in6_addr *a2) { return (a1-s6_addr32[0] a2-s6_addr32[0] a1-s6_addr32[1] a2-s6_addr32[1] a1-s6_addr32[2] a2-s6_addr32[2] a1-s6_addr32[3] a2-s6_addr32[3]); } 可以利用按位异或实现快速比较, 最新的实现已经修改为: static inline int ipv6_addr_equal(const struct in6_addr *a1, const struct in6_addr *a2) { return (((a1-s6_addr32[0] ^ a2-s6_addr32[0]) | (a1-s6_addr32[1] ^ a2-s6_addr32[1]) | (a1-s6_addr32[2] ^ a2-s6_addr32[2]) | (a1-s6_addr32[3] ^ a2-s6_addr32[3])) 0); } 本文出自 “kapu” 博客请务必保留此出处http://kapok.blog.51cto.com/517862/129941