标签:
两篇非常好的文章:
http://blog.csdn.net/zouliping123/article/details/8995373
http://www.cnblogs.com/flying_bat/archive/2008/06/17/1224178.html
预备知识
对于位运算,大家都很熟悉,基本的位操作有与、或、非、异或等等。在面试中经常会出现位运算相关的题,所以我就做了简单的整理,参考了很多写的很好的博客及书籍。
现在简单说一下,移位运算。
左移运算:x << y。将x左移y位,将x最左边的y位丢弃,在右边补y个0。
右移运算:x >> y。将x右移y位,这需要区分x是有符号数还是无符号数。在x是无符号数时,只需将x的最右边的y位丢弃,在左边补上y个0。在x是有符号数时,又分为x是正数还是负数。正数时,同无符号数的处理相同;负数时,将将x的最右边的y位丢弃,在左边补上y个1。
位运算技巧
计算一个数的二进制中1的个数
通过与初始值为1的标志位进行与运算,判断最低位是否为1;然后将标志位左移,判断次低位是否为1;一直这样计算,直到将每一位都判断完毕。
-
-
-
- int countOf1(int num)
- {
- int count = 0;
- unsigned int flag = 1;
-
- while(flag)
- {
- if(num & flag)
- {
- count++;
- }
-
- flag = flag << 1;
- }
- return count;
- }
还有一种方法,一个整数减一,可以得到该整数的最右边的1变为0,这个1右边的0变为1。对这个整数和整数减一进行与运算,将该整数的最右边的1变为0,其余位保持不变。直到该整数变为0,进行的与运算的次数即为整数中1的个数。
-
-
-
- int countOf1_2(int num)
- {
- int count = 0;
-
- while(num)
- {
- num = num & (num - 1);
- count++;
- }
- return count;
- }
判断一个数是否是2的n次方
一个数是2的n次方,则这个数的最高位是1,其余位为0。根据上一题的第二种解法可以很容易得到解决方案。将这个整数与整数减一进行与运算,如果得到的结果为零,可证明该数为2的n次方。
-
-
-
- bool is2Power(int num)
- {
- bool flag = true;
-
- num = num & (num - 1);
- if(num)
- {
- flag = false;
- }
-
- return flag;
- }
整数n经过多少步可以变为整数m
n和m的异或结果可以得知两数不同位的个数,再调用计算一个数中1的个数的方法,即可得到结果。
-
-
-
- int countChange(int n,int m)
- {
- n = n ^ m;
- return countOf1_2(n);
- }
获得最大的int值
-
-
-
-
- int getMaxInt()
- {
- return (1 << 31) - 1;
- }
-
-
-
-
- int getMaxInt_2()
- {
- return (1 << -1) - 1;
- }
-
- int getMaxInt_3()
- {
- return ~(1 << 31);
- }
-
-
-
-
- int getMaxInt_4()
- {
- return ((unsigned int) -1) >> 1;
- }
获得最小的int值
与获得最大的int方法类似。
-
-
-
-
- int getMinInt()
- {
- return 1 << 31;
- }
-
-
-
-
- int getMinInt_2()
- {
- return 1 << -1;
- }
获得最大的long
-
-
-
-
- long getMaxLong()
- {
- return ((unsigned long) -1) >> 1;
- }
判断一个数的奇偶性
判断奇偶性,实质是判断最后一位是否是1.
-
-
-
- bool isOdd(int num)
- {
- return num & 1 == 1;
- }
交换两个数(不借助第三变量)
不用第三个变量交换两个数的方法也有几种,例如a = a + b; b = a - b; a = a - b。下面这种方法可以实现的基础是一个数m与另一个数n异或,再与n异或,得到的结果是m.
-
-
-
-
-
-
- void mySwap(int* a,int* b)
- {
- (*a) ^= (*b) ^= (*a) ^= (*b);
- }
求一个数的绝对值
下面的方法实现的基础是将n右移31位,可以获得n的符号。
-
-
-
-
-
- int myAbs(int n){
- return (n ^ n >> 31) - (n >> 31);
- }
求两个数的平均值
第一种方法较为普遍且简单,不多说了。第二种方法,需要知道的是,( m ^ n ) >> 1得到的结果是m和n其中一个数的有些位为1的值的一半,m & n得到的结果是m 和n都为1的那些位,两个结果相加得到m和n的平均数。
-
-
-
- int getAverage(int m,int n){
- return (m + n) >> 1;
- }
-
-
-
-
-
-
- int getAverage_2(int m,int n){
- return ((m ^ n) >> 1) + (m & n);
- }
求解倒数第m位相关问题
-
-
-
- int getMthByTail(int n,int m){
- return (n >> (m - 1)) & 1;
- }
-
-
-
-
- int setMthByTail21(int n,int m)
- {
- return n | (1 << (m - 1));
- }
-
-
-
-
- int setMthByTail20(int n,int m)
- {
- return n & ~(1 << (m - 1));
- }
位运算
标签:
原文地址:http://www.cnblogs.com/qlky/p/5020646.html