几道位操作的题目思路与实现

来源:互联网 发布:怎样用手机注册淘宝店 编辑:程序博客网 时间:2024/05/21 17:25

1. 编写一个函数setbits(x,p,n,y),该函数返回对x执行下列操作后的结果值:将x中从第p位开始的n个二进制位设置为y中最右边n位的值,x的其余位保持不变。

这个问题,有如下两种思路:

1)最终&的形式:将x中从第p位开始的n位全部置1,其余位不变,而对于y,先将其最右边的n位移到第p位,这些位不变,其余位置1;最后将二者相与

  a).如何实现第一步?我们可以这样设置一个屏蔽码(让其与x相或):它的中间n位都是1,其余位都是0,然后与x相或,

       举例:设p=6,n=2,x和y都是8位,求掩码的推理过程如下

                  ~0=11111111

                  11111111<<2=11111100(左移的位数=n)

                  ~11111100=00000011

                 00000011<<5=01100000(左移的位数=p-n+1)

       结论:屏蔽码获取方式(~(~0<<n))<<p-n+1

       b).如何实现第二步?同样地,我们设计一个可以保持y移位之后,相应位不变而其余位置1的掩码:它的中间n位都是0,而其它位都是1,然后将掩码与y相或

       举例:设p=6,n=2,x和y都是8位,求掩码的推理过程如下

                   ~0=11111111

                  11111111<<2=11111100(左移的位数=n)

                   ~11111100=00000011

                   00000011<<5=01100000(左移的位数=p-n+1)

                  ~01100000=10011111

                 结论:屏蔽码获取方式~((~(~0<<n))<<p-n+1)

2)最终|的形式:将x中从第p位开始的n位全部清0,其余位不变,而对于y,先将其最右边的n位移到第p位,这些位不变,其余位清零;最后将二者相或

  同样地,根据最终选择相与还是相或,我们可以自己设置掩码。

       推理过程略。

        总结规律就是~0得到全为1的位,然后左移得到一定数目的0,然后在取反,移位以得到期望的掩码。


2. 编写一个函数invert(x,p,n),该函数返回对x执行下列操作后的结果值:将x中的第p位开始的n个二进制位求反(即,1变成0,0变成1),x的其余各位保持不变。

    利用性质:任何数与1异或等于其取反,任何数与0异或等于其本身。我们可以把中间的n位与1异或,剩下的位与0异或即可。掩码的求取方式仍遵循上述规律。


3.编写一个函数rightrot(x,p,n),该函数返回将x循环右移(即从最右端移出的位将从最左端移入)n(二进制)位后所得到的值。

   先截取x的低n位并保留,用作移位后的处理用。然后unsigned x右移n位,把截取的值左移到和x平行的高位处,将二者做异或处理。

   

  #include<stdio.h>  int main()  {        int x=150;printf("%x\n",x);int n=3;int y=((~0<<n)^x)<<(sizeof(int)*8-n);x=x>>n;x^=y;printf("%x",x);return 0;  }


4.表达式x&=(x-1)可以删除x中最右边值为1(即从右往左数第一个为1 的位)的一个二进制位:x-1最右端为0的位在x中变为1,也就是说x中最右边为1的位与x-1在最左端为0的位在相同的位置上对应着,显然他们相与就会使x最右边值为1的位清零,而高于它们的位不受影响。

以下代码统计x中二进制1 的个数

   for(b=0;x!=0;x&(x-1))         ++b;   return b;


0 0
原创粉丝点击