C++语言中位运算符在计算中的实际运用

来源:互联网 发布:c语言区间内素数 编辑:程序博客网 时间:2024/05/02 05:02

位运算符:


1.表达式:X&(X-1)

            解释:每执行一次x = x&(x-1),会将x用二进制表示时最右边的一个1变为0,因为x-1将会将该位(x用二进制表示时最右边的那个1)变为0。(假设该位为第k位,减1后,该位后面全部变成1,但是由于该位是最右边的1了,所以x的第k位后面全是0,而x-1的第k位是0,从1到k-1位全是1,按位与的结果自然就是第k位和1~k-1位都变成0。

       实际应用1:将一个数变成二进制代码后统计其中含有的1的位数,代码如下:

int func(int x){    int countx = 0;    while(x)   {       countx++;       x = x&(x-1);   //每次将x最右边的1变成0   }   return countx;} 假定x = 999910011100001111

      实际应用2:当x为奇数的时候,x=x&(x-1)它的值相当于x=x-1;同样,当x为2的N次幂时,结果为0,这可以用来快速判断一个数是否为2的n次方,代码如下:

int func(int x){   if( (x&(x-1)) == 0 )     //2的n次方有个很明显的特点是其转换成2进制后只有一位为1,其他位都为0;       return 1;   else       return 0;}


2.表达式:(x&y) + ((x^y)>>1) 

       解释:该表达式真是目的是运用位运算求取平均值,代码如下:

int  average(int x,int y){      return ( (x&y) + ( (x^y)>>1 ) );}
                  我们可以这样来考虑,将x和y的值分别拆成两部分进行相加,有如下两种情况:

      1:x和y对应位相同:这种情况下,x和y的值相等,x&y的值等于x或y,也等于(x+y)/2;

      2:x和y对应位不同:这种情况下,x和y其中一个为0,一个为1,(x^y)>>1就等于二者相加的结果去平均值,如0010和0000,(x^y)>>1= 0001,等于(2+0)/2。


3.表达式:(x^y)+((x&y)<<1)

       解释:通过该表达式可以实现利用位运算实现加法运算,代码如下:

int Add(int a,int b){    if(b == 0)                   //b等于0,说明不会有进位,直接等于areturn a;    int sum,carry;     sum = a ^ b;                 //第一步<span style="font-family: Arial;">完成</span><span style="font-family: Arial;">没有进位的加法运算</span>    carry = (a & b) << 1;        //第二步完成有进位的加法运算    return Add(sum,carry);       //迭代,直到没有进位}
      举个简单的例子,完成10+6的运算,有以下几个步骤:

      第一次迭代:sum = 10^6 = 12; carry = (10&6)<<1 = 4。

      第二次迭代:sum = 12^4 = 8; carry = (12&4)<<1 = 8。

      第三次迭代:sum = 8^8 = 0; carry = (8&8)<<1 = 16。

      第四次迭代:sum = 0^16 = 16; carry = (0&16)<<1 = 0;

      结束(有几位二进制数即需要迭代几次)。

      这里详细的内容可参考博客:http://blog.csdn.net/zhongjiekangping/article/details/6855864


4.需要注意的一个例子:

int _tmain(int argc, _TCHAR* argv[]){unsigned char a = 0xa5;unsigned char b = ~a >> 4+1;printf("b=%d\n",b);        return 0;}
      这里输出的结果是250,而不是我所想的2,其原因是在计算这个表达式的时候,编译器会先把a和4的值转换成int类型(即所谓的整数提升),然后再进行计算,当计算结果出来后,再把结果转换成unsigned char 赋值给b.

      本题的运算顺序如下:a = 0000 0000 1010 0101,由于按位取反运算符优先级大于加运算符大于移位运算符,所以先对a进行按位取反操作,然后执行4+1,再将a按位取反的值向右移动5位,得出结果。


附录运算符优先级表格:





0 0