[转]位运算

原文:http://www.cnblogs.com/c2303191/articles/914074.html?login=1#commentform

5.按位逻辑运算的应用
例3-8:设 int x=7,求y=~x
        y=~x=~7=~(0000,0000,0000,0111)=1111,1111,1111,1000=-8
    可见,对x的值(7)按位求反结果恰为-8的补码表示,其原因是计算机中有:
    整数求负=整数求补=按位求反+1 
    所以:按位求反=整数求负-1。
    请注意求反运算与单目减和逻辑非运算的区别:
      y=-x;  结果为:y=-7, 
        y=!x; 结果为:y=0。

例3-9:用按位与运算屏蔽特定位(将指定位清为0)。
    设 n=051652(八进制数),计算m=n&0177,则:m=052。
         n: 0,101,001,110,101,010
    & 0177: 0,000,000,001,111,111
         m: 0,000,000,000,101,010
    经过位与运算,将n前9位屏蔽掉,即截取n的后7位。

例3-10:用按位与运算保留特定位。
    要想将一个变量n的特定位保留下来,只要设一个数,使该数的某些位为1,这些位是与要保留的n的特定位相对应的位,再将n与该数按位与。
    设 n=011050(为八进制数。对应的二进制为:0,001,001,000,101,000),要将n的右起第2、4、6、8、10位保留下来,只要 n=n&01252,则有:
           n: 0,001,001,000,101,000
     & 01252: 0,000,001,010,101,010
           n: 0,000,001,000,101,000 (n=01050)
    注意,按位与的"&"功能与取地址运算的"&"不同,尽管两者采用了相同的符号。

例3-11:用按位或运算将指定的位置为1。
    设:x=061,y=016,则z=a|b为:
        x: 0000,0000,0011,0001
        | y: 0000,0000,0000,1110
          z: 0000,0000,0011,1111
    即将x或y中为1的位的相应位置成1,其结果是z中的后6位为1。

例3-12:用按位异或运算将某个量的特定位翻转。
    要将变量n的特定位翻转,即原来为1的变0,为0的变1,只要设一个数,使该数的某些位为1,这些位是与n中要翻转的相对应的位,然后将n与该数进行按位异或运算。
    设:a=015,要将后四位翻转,只要a=a^017,则:
          a: 0000,0000,0011,1101
      ^ 017: 0000,0000,0011,1111
          a: 0000,0000,0000,0010

3.5.3 移位运算

C语言提供了两个移位运算:左移和右移,它们是把整数作为二进制位序列,求出把这个序列左移若干位或者右移若干位所得到的序列。左移和右移都是双目运算, 运算符左边的运算对象是被左移或右移的数据,而运算符右边的运算对象是指明移动的位数。数据左移或右移后空出来的位置补0。 
左移、右移运算表达式的一般形式为:
x << n 或 x >> n
其中x为移位运算对象,是要被移位的量;n是要移动的位数。
左移运算的规则是将x的二进制位全部向左移动n位,将左边移出的高位舍弃,右边空出的位补0。右移是将x的各二进制位全部向右移动n位,将右边移出的低位 舍弃,左边高位空出要根据原来量符号位的情况进行补充,对无符号数则补0;对有符号数,若为正数则补0,若为负数则补1。

例如,设a=7,则:
b=a<<2  即:b=0000,0111<<2=0001,1100=28
c=a>>2  即:c=0000,0111>>2=0000,0001=1
左移的一个特殊用途是将整数值乘以2的幂,例如:左移运算表达式1<<4的计算结果是16,右移可以用于将整数值除乘2的幂。

3.5.4 位运算赋值运算符

位运算符与赋值运算符可以组成以下5种位运算赋值运算符:
&=、 |=、 >>=、 <<=、 ^=
由这些位运算赋值运算符可以构成位运算赋值表达式。例如:
x&=y 相当于:x=x&y
x<<=2 相当于:x=x<<2
x>>=3 相当于:x=x>>3
x^=5 相当于:x=x^5


原码、补码和反码 
 

(1)原码表示法 
    原码表示法是机器数的一种简单的表示法。其符号位用0表示正号,用:表示负号,数值一般用二进制形式表示。设有一数为x,则原码表示可记作[x]原。

    例如,X1= +1010110

          X2= 一1001010

    其原码记作:

            [X1]原=[+1010110]原=01010110

            [X2]原=[-1001010]原=11001010

    原码表示数的范围与二进制位数有关。当用8位二进制来表示小数原码时,其表示范围:

      最大值为0.1111111,其真值约为(0.99)10

      最小值为1.1111111,其真值约为(一0.99)10

当用8位二进制来表示整数原码时,其表示范围:

      最大值为01111111,其真值为(127)10

      最小值为11111111,其真值为(-127)10

      在原码表示法中,对0有两种表示形式:

          [+0]原=00000000

           [-0] 原=10000000


 
(2)补码表示法 
    机器数的补码可由原码得到。如果机器数是正数,则该机器数的补码与原码一样;如果机器数是负数,则该机器数的补码是对它的原码(除符号位外)各位取反,并在未位加1而得到的。设有一数X,则X的补码表示记作[X]补。

      例如,[X1]=+1010110

            [X2]= 一1001010

            [X1]原=01010110

            [X1]补=01010110

    即      [X1]原=[X1]补=01010110

            [X2] 原= 11001010

            [X2] 补=10110101+1=10110110

    补码表示数的范围与二进制位数有关。当采用8位二进制表示时,小数补码的表示范围:

      最大为0.1111111,其真值为(0.99)10

      最小为1.0000000,其真值为(一1)10

采用8位二进制表示时,整数补码的表示范围:

      最大为01111111,其真值为(127)10

      最小为10000000,其真值为(一128)10

      在补码表示法中,0只有一种表示形式:

        [+0]补=00000000

        [+0]补=11111111+1=00000000(由于受设备字长的限制,最后的进位丢失)

所以有[+0]补=[+0]补=00000000




 
(3)反码表示法 
    机器数的反码可由原码得到。如果机器数是正数,则该机器数的反码与原码一样;如果机器数是负数,则该机器数的反码是对它的原码(符号位除外)各位取反而得到的。设有一数X,则X的反码表示记作[X]反。

    例如:X1= +1010110

          X2= 一1001010

        [X1]原=01010110

         [X1]反=[X1]原=01010110

         [X2]原=11001010

         [X2]反=10110101

    反码通常作为求补过程的中间形式,即在一个负数的反码的未位上加1,就得到了该负数的补码。

例1. 已知[X]原=10011010,求[X]补。

分析如下:

由[X]原求[X]补的原则是:若机器数为正数,则[X]原=[X]补;若机器数为负数,则该机器数的补码可对它的原码(符号位除外)所有位求反,再在未位加1而得到。现给定的机器数为负数,故有[X]补=[X]原十1,即

          [X]原=10011010

          [X]反=11100101

     十)         1      



          [X]补=11100110

  



例2. 已知[X]补=11100110,求[X]原。

         分析如下:

     对于机器数为正数,则[X]原=[X]补

     对于机器数为负数,则有[X]原=[[X]补]补

现给定的为负数,故有:

            [X]补=11100110

        [[X]补]反=10011001

              十)         1    



        [[X]补]补=10011010=[X]原
  

posted @ 2011-03-06 16:25  NewSea  阅读(375)  评论(0编辑  收藏  举报