Discussion:Bit Operation(& ,| ,~,<<,>>,^)

什么是位?

简单来说,位就是1和0,在电脑中做的每一件事都是由它们组成的。电脑中所有的数据使用的是位。一个字节由8个位组成;一个字由两个字节组成,即16个位;而一个双字由四个字节组成,即32个位。由于位运算直接对内存数据进行操作,不需要转成十进制,因此处理速度非常快


位运算有哪些操作符?

& | <<>>^

(补充,逻辑运算符是 ||   , &&  ,  !这些和位运算符大大不同)

它们分别的意思是:

& 与运算符   | 或运算符  ~ 取反运算符   >> 右移运算符   << 左移运算符    ^ 异或运算符  
 

下面我们看看这些操作符是怎么操作的:

&:

(1).运算规则:有0变0,无0为1

(2).判断奇偶性

a&1  = 0 偶数 

a&1 =  1 奇数

(3).可以用来取位操作

如:一个数 and 1的结果就是取二进制的最末位 

(4).判断一个数的二进制第n位是否为1的方法是:把一个n位为1,其它位为0与待判断的数进行与运算

我们看下例子(看是否存在D盘,主要是根据与运算是否存在1000):

DWORD d = GetLogicalDrives();
if((d&8)>0)   //是否存在D盘
{
    SetDlgItemText(hwnd,IDC_EDTNAME4,TEXT("存在D盘"));
}
else
{
    SetDlgItemText(hwnd,IDC_EDTNAME4,TEXT("不存在D盘"));
}


(5).求余优化(x%(2n)=x&(2n-1)

 | ()

(1).运算规则:有1变1,无1变0

(2).一个数or 1的结果就是把二进制最末位强行变成1

~(取反)

(1).取反运算的定义是把内存中的0和1全部取反。使用not运算时要格外小心,你需要注意整数类型有没有符号。如果not的对象是无符号整数(不能表示负数)。

如:

#include <stdio.h>
int main(void)
{
    unsigned short a=100;
    a = ~a;
    printf( "%d/n", a );
    return 0;
}

如上面的一段程序 算出来为 65435  而它的上界位65536 所以算出来的结果是它们的差,因为无符号类型的数是用$0000到$FFFF依次表示的。


<<(左移)

(1).如A<<B:是A转换为二进制后向左移动B位

(2).左移3相当于乘以2的3次方
可以使用(1 << 16 )-1来表示个常量 如#defien Max_N (1 << 16 )-1, 因为这个值表示65535
(很有用,有时大量的乘除运算可用移位代替,效率会很高!)


>>(右移)

(1).A>>B:是A转换为二进制后向右移动B位

(2).右边的位被挤掉。对于左边移出的空位,如果是正数则空位补0,若为负数,可能补0或补1,这取决于所用的计算机系统。

(3).右移3相当于除以2的3次方

下面是个例子,看电脑中存在多少磁盘(主要是右移!)

void countIt(HWND hwnd)
{   
    DWORD n = GetLogicalDrives();   
    int count = 0;//计数器  
    while(n>0)   
    {   
        if((n&1)>0)//判断最后一位是否为1   
        {   
            count ++;   
        }      
        n = n>>1;//继续右移    
    }    
    TCHAR cD[256];   
    itoa(count,cD,10);   
    MessageBox(NULL,cD,TEXT("hello!"),MB_OK);   
}  

 ^:(异或)

1.可以用一句话理解:是不是不一样 (不一样为1,一样为0)

2.两次异或同一个数还是它本身(如:(a ^b)^b=a)

3.(a ^ b) ^ b = a,像这种异或运算可用于加密 用两次异或 b位密码

4.另外还有一个是引入第三变量,交换两个变量的值 (设 a=a1,b=b1) 

5.两个二进制数异或的结果为两者之差的绝对值


一些位运算的例子:

   功能              |           示例            |    位运算   
----------------------+---------------------------+--------------------   
去掉最后一位          | (101101->10110)           | x >> 1   
在最后加一个0         | (101101->1011010)         | x << 1   
在最后加一个1         | (101101->1011011)         | x << 1+1   
把最后一位变成1       | (101100->101101)          | x | 1   
把最后一位变成0       | (101101->101100)          | x | 1-1   
最后一位取反          | (101101->101100)          | x ^ 1   
把右数第k位变成1      | (101001->101101,k=3)      | x | (1 <<(k-1))   
把右数第k位变成0      | (101101->101001,k=3)      | x & ~ (1 << (k-1))   
右数第k位取反         | (101001->101101,k=3)      | x ^ (1 << (k-1))   
取末三位              | (1101101->101)            | x & 7   
取末k位               | (1101101->1101,k=5)       | x & (1 << k-1)   
取右数第k位           | (1101101->1,k=4)          | x >> (k-1) & 1   
把末k位变成1          | (101001->101111,k=4)      | x | (1 << k-1)   
末k位取反             | (101001->100110,k=4)      | x ^ (1 << k-1)   
把右边连续的1变成0    | (100101111->100100000)    | x & (x+1)   
把右起第一个0变成1    | (100101111->100111111)    | x | (x+1)   
把右边连续的0变成1    | (11011000->11011111)      | x | (x-1)   
取右边连续的1         | (100101111->1111)         | (x ^ (x+1)) >> 1   
去掉右起第一个1的左边 | (100101000->1000)         | x & (x ^ (x-1))   


位运算求绝对值:

 x >> 31是二进制的最高位,它用来表示x的符号。如果它为0(x为正),则~ (x >> 31) + 1等于$00000000,异或任何数结果都不变;如果最高位为1(x为负),则~ (x >> 31) + 1等于$FFFFFFFF,x异或它相当于所有数位取反,异或完后再加1。




原文链接: http://blog.csdn.net/crazyjixiang/article/details/6465205

你可能感兴趣的:(Discussion:Bit Operation(& ,| ,~,<<,>>,^))