本文共 3305 字,大约阅读时间需要 11 分钟。
清零取位要用与,某位置1要用或,取反和交换用异或
1.他们都是双目运算符,两个运算分量都是整形,结果也是整形。
2.“<<”左移:右边空出的位上补0,左边的位将从字头挤掉,其值相当于乘2; 3“>>”右移:右边的位被挤掉了,对于左边移出的空位,如果是正数则空位补0,若为负数,可能补0或1,这取决于不同的计算系统。 4“>>>”运算符:右边的位被挤掉,对于左边移出的空位一概补上0;(1)按位与&
1.清除某特定位(b中特定位置0,其余位为1,a=a&b) 2.取某数中指定位(b中特定位置1,其余位为0,a=a&b) (2)按位或--| 常用来将源操作数某些位置1,其它位置不变。(b中特定位置1,其余位为0,a=a|b) (3)位异或--^ 相同为0,不同为1 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.快速判断两个值是否相等 举例1: 判断两个整数a,b是否相等,则可通过下列语句实现: 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);}
4.基于按位异或的加密解密算法
class E { public static void main(String args[ ]) { char a1='十' , a2='点' , a3='进' , a4='攻' ; char secret='8' ; a1=(char) (a1^secret); a2=(char) (a2^secret); a3=(char) (a3^secret); a4=(char) (a4^secret); System.out.println("密文:"+a1+a2+a3+a4); a1=(char) (a1^secret); a2=(char) (a2^secret); a3=(char) (a3^secret); a4=(char) (a4^secret); System.out.println("原文:"+a1+a2+a3+a4); } } 如果两个数相应的位上一样,结果就是0,不一样就是1 所以111^101=010 那加密的过程就是逐个字符跟那个secret字符异或运算. 解密的过程就是密文再跟同一个字符异或运算 010^101=111-x = ~x + 1 = ~(x-1)
~x = -x- -(~x) = x+ ~(-x) = x- x+y = x - ~y - 1 = (x|y)+(x&y) x-y = x + ~y + 1 = (x|~y)-(~x&y) x^y = (x|y)-(x&y) x|y = (x&~y)+y x&y = (~x|y)-~x x==y: ~(x-y|y-x) x!=y: x-y|y-x x< y: (x-y)^((x^y)&((x-y)^x)) x<=y: (x|~y)&((x^y)|~(y-x)) x< y: (~x&y)|((~x|y)&(x-y))//无符号x,y比较 x<=y: (~x|y)&((x^y)|~(y-x))//无符号x,y比较(1) 判断int型变量a是奇数还是偶数
a&1 = 0 偶数 a&1 = 1 奇数 (2) 取int型变量a的第k位 (k=0,1,2……sizeof(int)),即a>>k& (3) 将int型变量a的第k位清0,即a=a&~(1< (4) 将int型变量a的第k位置1, 即a=a|(1< (5) int型变量循环左移k次,即a=a<>16-k (设sizeof(int)=16) (6) int型变量a循环右移k次,即a=a>>k|a<<16-k (设sizeof(int)=16) (7)整数的平均值 对于两个整数x,y,如果用 (x+y)/2 求平均值,会产生溢出,因为 x+y 可能会大于INT_MAX,但是我们知道它们的平均值是肯定不会溢出的,我们用如下算法:int average(int x, int y) //返回X,Y 的平均值{ return (x&y)+((x^y)>>1); }
(8)判断一个整数是不是2的幂,对于一个数 x >= 0,判断他是不是2的幂
boolean power2(int x)
{ return ((x&(x-1))==0)&&(x!=0); }(9)计算绝对值
int abs( int x )
{ int y ; y = x >> 31 ; return (x^y)-y ; //or: (x+y)^y } (10)取模运算转化成位运算 (在不产生溢出的情况下):a % (2^n) 等价于 a & (2^n - 1) (11)乘法运算转化成位运算 (在不产生溢出的情况下):a * (2^n) 等价于 a<< n 右边空出的位上补0,左边的位将从字头挤掉,其值相当于乘2; (12)除法运算转化成位运算 (在不产生溢出的情况下):a / (2^n) 等价于 a>> n 右边的位被挤掉。对于左边移出的空位,补零,其值相当于除2; 例: 12/8 == 12>>3 (13) a % 2 等价于 a & 1 (14) if (x == a) x= b; else x= a; 等价于 x= a ^ b ^ x; (15) x 的 相反数表示为 (~x+1) (16) 实现最低n位为1,其余位为0的位串信息:~(~0 << n) (17)截取变量x自p位开始的右边n位的信息:(x >> (1+p-n)) & ~(~0 << n) (1)截取old变量第row位,并将该位信息装配到变量new的第15-k位:new |= ((old >> row) & 1) << (15 – k) (19)设s不等于全0,代码寻找最右边为1的位的序号j: for(j = 0; ((1 << j) & s) == 0; j++) ; return j;//由于1每次左移过程中只要遇到1此时相与为1,返回此时的位置J转载地址:http://zvomb.baihongyu.com/