深入理解位运算操作及使用场景

布满荆棘的人生 2022-03-25 17:35 263阅读 0赞
  1. 工作中一直没用过位操作,只有在阅读一些源码的时候会看到使用位运算符(因为直接使用位运算符效率更高),为了更好的阅读源码那就好好学习一下吧,顺便把学习的东西记下来。
  2. 位运算符大致就以下几种吧。

位运算符












































名称 符号 用法
位求反 ~ ~expr 
左移 << expr1 << expr2
右移 >> expr1 >> expr2
无符号右移 >>> expr1 >>> expr2
位与 & expr1 & expr2
位或 | expr1 | expr2
位异或 ^ expr1 ^ expr2

所有的位运算都是在二进制下来进行运算的,再二进制下只有0/1。

1. ~ 位求反

运算符规则是:将运算符后二进制数反转,0变1,1变 0,所以对一个数取反偶数次结果是它本身。

例如:

  1. 0000 0000 0000 0000 0000 0000 0000 0011 -> 3
  2. 1111 1111 1111 1111 1111 1111 1111 1100 -> ~ 3 = -4

常用场景:

  • 求相反数: ~a + 1

2. << 左移

运算符规则是:各二进位全部左移若干位,高位丢弃,低位补0。

例如:6 << 2 = 24

  1. 0000 0000 0000 0000 0000 0000 0000 0110 -> 6
  2. 0000 0000 0000 0000 0000 0000 0001 1000 -> 6 << 2 = 24

我们将6的二进位向左移动两位,低位补上两个0,高位丢弃,得出来的结果就是24。

常用场景:

  • 左移常被用来做 * (2 ^ n)的运算,因为直接基于二进制运算,所以左移效率比 * (2 ^ n)高。

3. >> 右移

运算符规则是:各二进位全部右移若干位,正数高位补0,负数高位补1,低位丢弃。

例如: 12 >> 2 = 3

  1. 0000 0000 0000 0000 0000 0000 0000 1100 -> 12
  2. 0000 0000 0000 0000 0000 0000 0000 0011 -> 12 >> 2 = 3

因为12是正数,右移过程中高位补上两个0,低位丢弃,得出来的结果就是3。
例如:-12 >> 2 = -3

  1. 1111 1111 1111 1111 1111 1111 1111 0100 -> -12
  2. 1111 1111 1111 1111 1111 1111 1111 1101 -> -12 >> 2 = -3

因为-12是负数,右移过程中高位补上两个1,低位丢弃,得出来的结果就是-3。

常用场景:

  • 右移常被用来做 / (2 ^ n)的运算,因为直接基于二进制运算,所以右移效率比 / (2 ^ n)高。

4. >>> 无符号右移

运算符规则是:各二进位全部右移若干位,高位补0,低位丢弃。

例如: 12 >>> 2 = 3

  1. 0000 0000 0000 0000 0000 0000 0000 1100 -> 12
  2. 0000 0000 0000 0000 0000 0000 0000 0011 -> 12 >>> 2 = 3

我们将12的二进位向右移动两位,高位补上两个0,低位丢弃,得出来的结果就是24。
例如:-12 >>> 2 = 1073741821

  1. 1111 1111 1111 1111 1111 1111 1111 0100 -> -12
  2. 0011 1111 1111 1111 1111 1111 1111 1101 -> -12 >> 2 = 1073741821

我们将-12的二进位向右移动两位,高位补上两个0,低位丢弃,得出来的结果就是1073741821。

5. & 位与

运算符规则是:运算符两边有0,结果就为0 ,只有当两边同时为1是,结果才为1。

如下:

0 & 0 = 0; 0 & 1 = 0; 1 & 0 = 0; 1 & 1= 1;

例如:3&5

  1. 0000 0000 0000 0000 0000 0000 0000 0011 -> 3
  2. 0000 0000 0000 0000 0000 0000 0000 0101 -> 5
  3. 0000 0000 0000 0000 0000 0000 0000 0001 -> 3 & 5 = 1

位与运算的特殊用途:

  • 1.清零(将一个单元与0进行位与运算结果为零)
  • 2.取一个数指定位(例如取num=1010 1101的低四位 则将num&0xF得到0000 1101)。
  • 3.判断奇偶性:用if ((a & 1) == 0) 代替 if (a % 2 == 0)来判断a是不是偶数。

6. | 位或

运算规则就是 运算符两边有1,结果就为1 ,只有当两边同时为0是,结果才为0。

如下:

0 | 0 = 0; 0 | 1 = 1; 1 | 0 = 1; 1 | 1 = 1 ;

例如:3|5 

  1. 0000 0000 0000 0000 0000 0000 0000 0011 -> 3
  2. 0000 0000 0000 0000 0000 0000 0000 0101 -> 5
  3. 0000 0000 0000 0000 0000 0000 0000 0111 -> 3 | 5 = 7

另,负数按补码形式参加按位或运算。

使用场景:

下面这个方法是摘自HashMap类,这个算法来修改用户使用构造器传进来的size的,这个算法是使用移位和或结合来实现的,性能上比循环判断要好。

  1. public static final int tableSizeFor(int cap) {
  2. int n = cap - 1;
  3. n |= n >>> 1;
  4. n |= n >>> 2;
  5. n |= n >>> 4;
  6. n |= n >>> 8;
  7. n |= n >>> 16;
  8. return (n < 0) ? 1 : (n >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1;
  9. }

7. ^ 位异或

运算规则是:当运算符两边相同位置都是相同,结果返回0,不相同时返回1。

例如:3 ^ 5 = 1

  1. 0000 0000 0000 0000 0000 0000 0000 0011 -> 3
  2. 0000 0000 0000 0000 0000 0000 0000 0101 -> 5
  3. 0000 0000 0000 0000 0000 0000 0000 0110 -> 3 ^ 5 = 6

通常我们交换两个数会使用一个临时变量来帮忙:

  1. int t = a;
  2. a = b;
  3. b = t;

使用 ^ 位运算符(装逼必备)

  1. a ^= b;
  2. b ^= a;
  3. a ^= b;

发表评论

表情:
评论列表 (有 0 条评论,263人围观)

还没有评论,来说两句吧...

相关阅读

    相关 c++运算相关操作

    在 c++ 中,经常会对具体整型数据的位进行操作。例如:要获取整数 12(0B1100)在第 1 位上数值(为 0),第 2 位上数值(为 1),第 3 位上数值(为 1)。在

    相关 C/C++操作运算

    在C语言中,可以单独操控变量的位(bit),一般高级语言不会处理这级别的细节,C在提供高级语言便利的同时,还能为汇编语言所保留的级别上工作,这使其成为编写设备驱动程序和嵌入式代

    相关 JAVA 运算理解

    java 的位运算符有&,| ,^,~,<<,>>,>>> 一共七个 位运算符是不支持浮点类型运算的,其中&,|,^ 这三个运算符可以支持boolean类型,其它4个不支持b