位运算符总结

来源:互联网 发布:淘宝怎么查看我的评价 编辑:程序博客网 时间:2024/04/30 04:05
一、在做位运算题目的时候应该牢记下面的规则:
1、任何数与1做&运算,结果等于本身;任何数与0做&运算,结果等于0;(&符号有变成0的作用)
2、任何数与1做|运算,结果等于1;任何数与0做|运算,结果等于本身;(|符号有变成1的作用)
3、任何数与1做^运算,结果等于本身取反;任何数与0做^运算,结果等于本身;(^符号有取反的作用)
4、<<,标准规定在右边补0;>>,正数则左边补0,负数标准没有规定在左边补充的数字,分为逻辑右移和算术右移,具体由编译器决定,windows平台和gcc采取算术右移即负数补1;
重点:5、题目要求变化某一位,则考虑用1构造数字再操作,例如题目要求取反,考虑^1;题目要求变1,考虑|1;题目要求变0,考虑&0。题目要求取右数第k位,先右移k-1位,把要得到的位移到右边第一个,再利用&1得到右边的一位。题目要求得到右边连续的0变1,还是要用|,考虑要构造一个与右边连续的0对应位上有连续的1的数,这样|一下,连续的0会变成1,其余等于它本身,不变化,x|(x-1)就可以解决,发生借位也不用担心,因为借位之后减去变成0,与原x|还是原来的数,把右边连续的1变成0也是同样的道理。
二、常见的二进制位的变换操作
下面列举了一些常见的二进制位的变换操作。

功能 | 示例 | 位运算
----------------------+---------------------------+--------------------
1、去掉最后一位 | (101101->10110) | x >> 1
2、在最后加一个0 | (101101->1011010) | x << 1
3、在最后加一个1 | (101101->1011011) | (x << 1)|1
4、把最后一位变成1 | (101100->101101) | x | 1
5、把最后一位变成0 | (101101->101100) | x&(~1)
6、最后一位取反 | (101101->101100) | x ^ 1
7、把右数第k位变成1 | (101001->101101,k=3) | x | (1 << (k-1))(注:|上1有变1的功能)
8、把右数第k位变成0 | (101101->101001,k=3) | x & ~(1 << (k-1))(注:&上0有变0的功能)
9、右数第k位取反 | (101001->101101,k=3) | x ^ (1 << (k-1))(注:^上1有取反的功能)
10、取末三位 | (1101101->101) | x & 7
11、取末k位 | (1101101->1101,k=4) | x & ((1 << k)-1)
(注意:&右边这样操作之后右边k位全为1,则与原值一与,就只能取到后k位了,其余变成0了)
12、取右数第k位 | (1101101->1,k=4) | (x >> (k-1)) & 1
13、把右边连续的1变成0 | (100101111->100100000) | x & (x+1)
14、把右起第一个0变成1 | (100101111->100111111) | x | (x+1)
15、把右边连续的0变成1 | (11011000->11011111) | x | (x-1)
16、判断一个数为奇数或偶数
原理解释:因为在二进制中除了最右边第一位的权值为1(奇数)外,其他更高位权重都为2的倍数,所以要测试一个数是奇数还是偶数只要测试右边第一位是奇数还是偶数。所以核心代码实现只需要一行代码:
                                              return  (x&=1);

17、统计一个字节中的1和0的个数:
核心代码实现:
int bits(unsigned char n)
{
   int s=0;
   for(int i=0;i<8;i++)
{
   if(n&1) s++;//记录的是1的个数
   n>>=1;  
}
return s;
}

18、把一个数字的二进制位逆序
原理解释:用一个int变量记录逆置后的值;用一个变量记录右边第一位,好构造tmp|的数据,始终把右边第一位作为处理位,处理一个右移一个;要想把对应的位置的数字始终变成右边第一位的需要用到|=符号了,因为在tmp中你没处理的位置的数始终是0,|上它还等于本身,如果右边第一位为0,构造的数移完还是0,不会变,如果右边第一位为1,则你构造的数,除了需要交换的位数上为1,其他都为0,则与tmp|只会让对应的位变成1,其他位还是本身。
核心代码实现:;
int reverse_bit(int n)
{
     int a;//记录右边第一位;
     int tmp=0;//储存数字逆置后的结果;
     for(int i=0;i<32;i++)
    {
        a=n&1;
        tmp|=(a<<(32-i));
        n>>1;
    }
    return tmp;
}
原创粉丝点击