位操作学习

位操作学习

位操作是程序设计中对位模式或二进制数的一元和二元操作,位运算比加减运算速度略快,通常位运算比乘除运算要快很多。

取反(NOT)

取反是一元运算符,对一个二进制数的每一位执行逻辑反操作,使数组1变成0,使0变成1。例如:

NOT 0001(十进制7)

= 1000(十进制8)

许多的程序语言中,取反操作符用的是~表示,此操作符与逻辑非操作符不同,在c++中,逻辑非将数组整体看作一个bool类型——将真值转为假值,将假值转化为真值,而c语言将0转化为1,将非零值转化为0,逻辑非并不是一个位操作。

按位或(OR)

按位与处理两个长度相同的二进制数,两个相应的二进制中只要有一个为1,该位的结果值为1。

​ 0101

OR 0011

= 0111

按位或能够将每一位看作旗标,在二进制书中的每一位可以表示不同的布尔变量,使用按位或操作可以将二进制数的某一位设为1。这一技巧通常用来保存大量的布尔变量。

按位异或(XOR)

按位异或运算,对于长二进制模式或者二进制数的每一位执行逻辑异或操作,操作的结果是如果某位不同则该位为一,否则该位为0。

​ 0101

XOR 0011

​ = 0110

在汇编语言中可以使用按位异或作为寄存器的值设为0的捷径。

按位异或也可以用于在比特集合中切换旗标,这一技巧可用于操作布尔变量的比特模式。

按位与(AND)

按位与处理两个长度相同的二进制数,两个相应的二进制数都为1,则该位的结果为1,否则为零。

0101

AND 0011

​= 0001

移位

移位是一个二元运算符,用来将一个二进制数中的每一位全部向一个方向移动指定位,溢出的部分将会被舍弃,而空缺的部分填入一定的值。

可以进行移位的数据类型:

char、short、int、long、unsigned char、unsigned short、unsigned int、unsigned long

不可以进行移位的数据类型:

double、float、bool、long double

逻辑移位

对于逻辑移位,就是不考虑符号位,移位的结果只是数据所有的位数进行移位。根据移位操作的目的,左移时,低位补0,右移时,高位补0

算术移位

算术是带有符号的数据,所以我们直接移动所有的位数,这可能会使得符号不正确。

关于数的移位,特别需要注意正数,三码相同,所以无论左移还是右移都是补0.而负数的补码就需要注意,左移在右边补0,右移需要在左边补1,有一个很有趣的误区是,认为符号位保持不变,仅仅移动数据位,这是不对的,因为无论数据位还是符号位,都是二进制,在整体大迁移的过程中,符号位也是要跟随潮流的。只不过,为了保证右移后,和原来的符号数一样,因此,负数在右移时左边补1.

常见的位运算问题

1、位运算实现乘除法

一个数向右移一位相当于除以2,向左移相当于乘以2

2、位操作交换两数

位操作交换两数可以不需要第三个临时变量,虽然普通操作也可以做到,但是没有其效率高

//普通交换
void swap(int& a,int& b)
{
    a = a + b;
    b = a - b;
    a = a - b;
}

//异或操作
void swap(int& a,int& b)
{
    if(a != b)
    {
        a ^= b;
        b ^= a;
        a ^= b;
    }
}

3、位操作统计二进制中 1 的个数

count = 0  
while(a){  
  a = a & (a - 1);  
  count++;  
}  
posted @ 2021-03-08 17:00  漫山华  阅读(79)  评论(0编辑  收藏  举报