<span class="lnum" style="color: rgb(96, 96, 96);"> 1: </span><span class="rem" style="color: rgb(0, 128, 0);">//不使用临时变量交换两个数</span>
2: void swap(int *a, int *b)
<span class="lnum" style="color: rgb(96, 96, 96);"> 3: </span>{
4: *a = *a ^ *b;
<span class="lnum" style="color: rgb(96, 96, 96);"> 5: </span> *b = *b ^ *a;
6: *a = *a ^ *b;
<span class="lnum" style="color: rgb(96, 96, 96);"> 7: </span>}
8: //获取低8位
<span class="lnum" style="color: rgb(96, 96, 96);"> 9: </span><span class="kwrd" style="color: rgb(0, 0, 255);">short</span> getLow8(<span class="kwrd" style="color: rgb(0, 0, 255);">short</span> number)
10: {
<span class="lnum" style="color: rgb(96, 96, 96);"> 11: </span> <span class="kwrd" style="color: rgb(0, 0, 255);">return</span> (number & 0XFF);
12: }
<span class="lnum" style="color: rgb(96, 96, 96);"> 13: </span><span class="rem" style="color: rgb(0, 128, 0);">//获取高8位</span>
14: short getHeight8(short number)
<span class="lnum" style="color: rgb(96, 96, 96);"> 15: </span>{
16: return ((number & 0XFF00) >> 8);
<span class="lnum" style="color: rgb(96, 96, 96);"> 17: </span>}
18: //检查一个无符号整数是否为2的幂
<span class="lnum" style="color: rgb(96, 96, 96);"> 19: </span><span class="rem" style="color: rgb(0, 128, 0);">//将一个最右侧为1的位改为0</span>
20: bool checkPowerOf2 (unsigned short x)
<span class="lnum" style="color: rgb(96, 96, 96);"> 21: </span>{
22: return !(x & (x - 1));
<span class="lnum" style="color: rgb(96, 96, 96);"> 23: </span>}
24: //检查一个无符号整数是否为(2的n次方 - 1)
<span class="lnum" style="color: rgb(96, 96, 96);"> 25: </span><span class="kwrd" style="color: rgb(0, 0, 255);">bool</span> checkPowerOf2Sub1(unsigned <span class="kwrd" style="color: rgb(0, 0, 255);">short</span> x)
26: {
<span class="lnum" style="color: rgb(96, 96, 96);"> 27: </span> <span class="kwrd" style="color: rgb(0, 0, 255);">return</span> !(x & (x + 1));
28: }
<span class="lnum" style="color: rgb(96, 96, 96);"> 29: </span><span class="rem" style="color: rgb(0, 128, 0);">//析出(isolate)最右侧为1的位</span>
30: short isolate1(short x)
<span class="lnum" style="color: rgb(96, 96, 96);"> 31: </span>{
32: return x & (-x);
<span class="lnum" style="color: rgb(96, 96, 96);"> 33: </span>}
34: //析出(isolate)最右侧为0的位
<span class="lnum" style="color: rgb(96, 96, 96);"> 35: </span><span class="kwrd" style="color: rgb(0, 0, 255);">short</span> isolate0(<span class="kwrd" style="color: rgb(0, 0, 255);">short</span> x)
36: {
<span class="lnum" style="color: rgb(96, 96, 96);"> 37: </span> <span class="kwrd" style="color: rgb(0, 0, 255);">return</span> (~x & (x + 1));
38: }
<span class="lnum" style="color: rgb(96, 96, 96);"> 39: </span><span class="rem" style="color: rgb(0, 128, 0);">//乘以32</span>
40: short mul32(short x)
<span class="lnum" style="color: rgb(96, 96, 96);"> 41: </span>{
42: //32 = 2 ^ 5
<span class="lnum" style="color: rgb(96, 96, 96);"> 43: </span> <span class="kwrd" style="color: rgb(0, 0, 255);">return</span> x << 5;
44: }
<span class="lnum" style="color: rgb(96, 96, 96);"> 45: </span><span class="rem" style="color: rgb(0, 128, 0);">//乘以20</span>
46: short mul20(short x)
<span class="lnum" style="color: rgb(96, 96, 96);"> 47: </span>{
48: //20=2^4+2^2
<span class="lnum" style="color: rgb(96, 96, 96);"> 49: </span> <span class="kwrd" style="color: rgb(0, 0, 255);">return</span> (x << 4) + (x << 2);
50: }
<span class="lnum" style="color: rgb(96, 96, 96);"> 51: </span><span class="rem" style="color: rgb(0, 128, 0);">//判断是否为奇数</span>
52: bool isOdd(int x)
<span class="lnum" style="color: rgb(96, 96, 96);"> 53: </span>{
54: return !(x & 1);
<span class="lnum" style="color: rgb(96, 96, 96);"> 55: </span>}
56: //比较
<span class="lnum" style="color: rgb(96, 96, 96);"> 57: </span><span class="kwrd" style="color: rgb(0, 0, 255);">int</span> min(<span class="kwrd" style="color: rgb(0, 0, 255);">int</span> x, <span class="kwrd" style="color: rgb(0, 0, 255);">int</span> y)
58: {
<span class="lnum" style="color: rgb(96, 96, 96);"> 59: </span> <span class="kwrd" style="color: rgb(0, 0, 255);">return</span> ((x |~y)&((x^y) |~(y-x))) ? x : y;
60: }
三、
1. 变量交换
首先说个好玩的——诡异的变量交换。
交换两个int变量平时写程序会经常用到,当时,常规方法都要用三个变量,但是位运算里不需要第三个变量,仅仅需做三次异或运算:
a ^= b;
b ^= a;
a ^= b;
经过这样的三次异或运算后, a、b两个变量的值就交换过来了,原理?
原因是异或运算的逆运算就是自己,也就是一个数对一个数异或运算两次就是其本身。
2. 位运算实现int型快速乘法运算
判断奇偶性(对2取余):
a&1 == 0 偶数
a&1 == 1 奇数
计算2^n
1 << n
对2^n做乘法或除法:
a << n 等价于 a * (2 ^ n)
a >> n 等价于 a / (2 ^ n)
看到这里,也许大家会很纳闷,好好的乘法除法为什么要写成位运算呢?
其实,位运算的操作单元是bit,运算效率能提高60%。
在平时写程序的过程中,适当应用这些运算,可以大大提高程序的运行速度,下面以经典的二分求幂做一个例子:
int Power(int a, int n, int mod) // cal (a^n)%mod
{
int ans = 1;
while (n > 0) {
if (n & 1) {
ans *= a;
n--;
} else {
a *= a;
n >>= 1;
}
ans %= mod;
}
return ans;
}
3. 位运算的其他应用
(1) 取int型变量a的第k位 (k=0,1,2……sizeof(int))
a>>k&1
(2) 将int型变量a的第k位清0
a=a&~(1<<k)
(3) 将int型变量a的第k位置1
a=a|(1<<k)
(4) int型变量循环左移k次
a=a<<k|a>>16-k (设sizeof(int)=16)
(5) int型变量a循环右移k次
a=a>>k|a<<16-k (设sizeof(int)=16)
(6) 实现最低n位为1,其余位为0的位串信息:
~(~0 << n)
(7)截取变量x自p位开始的右边n位的信息:
(x >> (1+p-n)) & ~(~0 << n)
(8)截取old变量第row位,并将该位信息装配到变量new的第15-k位
new |= ((old >> row) & 1) << (15 – k)
(9)设s不等于全0,代码寻找最右边为1的位的序号j:
for(j = 0; ((1 << j) & s) == 0; j++) ;