按位异或运算
俗称: xor 运算
1 、 xor 的基本知识
我们来看看 xor 运算的机理:
1 001 01 100101 1---- à a
xor 1 011 01 000111 0---- à b
-------------------------
0 010 00 100010 1--- à c
看了上面的式子,体会到异或运算的原理了吧,就是: 0 和 1 异或 0 都不变,异或 1 则取反。很容易理解,如果 b 中的某位为 1 ,那么 a xor b 的作用是在 a 相应的位进行取反操作。用通俗易懂的语言来讲就是 xor 运算通常用于对二进制的特定一位进行取反操作。
我们再看到上面那个计算式子,如果得到的结果 c 再与 b 做异或运算即:
0 010 00 100010 1--- à c
xor 1 011 01 000111 0--- à b
----------------------------------
1 001 01 100101 1--- à d
注意到了吧, a == d 是成立的!那么我们可以得到一个结论: (a xor b) xor b = a 。
同时我们还可以得到一个很诡异的 swap 操作:
a ^= b; b ^= a; a ^= b;
自己拿起笔来模拟一下就很清楚的了。
2 、 xor 和 not (按位否)操作之间的关系
事实上很简单, nor 操作是 xor 操作的一个特例。取反实质上就是同 1 做异或操作
~x = x^0x FFFFFFFF
3 、两个比较有趣的式子: (n ^(n+1)) 和 ((n ^(n-1))+1)>>1
( 1 )首先来看 (n ^(n+1)) 这个式子,假设 n = 10011010 , n+1 = 10011011 ,则:
10011010--- à n
xor 1 0011 011 --- à n+1
------------------------------------
00000001 --- à ans
如果还不能看出什么的话,再来一个例子: n = 11111111 , n+1 = 100000000 ,则:
11110111--- à n
xor 11111 000--- à n+1
-------------------------
000001111 --- à ans
得到的结果为 n 的倒数出现第一个 0 的位以及后面所有的 1 全部变成 1 ,其它位都为 0 的数。
( 2 )再来看看 ((n ^(n-1))+1)>>1 这个式子
假设 n = 10011010 , n-1 = 10011001 ,则:
10011010--- à n
xor 1 0011 001 --- à n-1
-----------------------------------------
00000011 --- à ans
ans+1 >> 1 = 000000100 >> 1 = 000000010
看出来了吧,也就是取出 n 出现倒数第一个 1 的位及该位后面的 0 组成的数
4 、统计 n 中 1 的奇偶性
思路:我们在按位与运算的时候学过了怎么计算一个整数中 1 的个数,但是我们现在用 xor 来解决吧:
x = x ^ (x >> 2 );
x = x ^ (x >> 4 );
x = x ^ (x >> 8 );
x = x ^ (x >> 16 );
return x & 1 ;
说道这里,顺便提一下怎么求解一个数 n 的前导 0 的个数,下面的代码来自 Hacker's Delight
int n;
if (x == 0 ) return ( 32 );
n = 1 ;
if ((x >> 16 ) == 0 ) {n = n + 16 ; x = x << 16 ;}
if ((x >> 24 ) == 0 ) {n = n + 8 ; x = x << 8 ;}
if ((x >> 28 ) == 0 ) {n = n + 4 ; x = x << 4 ;}
if ((x >> 30 ) == 0 ) {n = n + 2 ; x = x << 2 ;}
n = n - (x >> 31 );
return n;
} // 代码自己慢慢理解吧