背景

java或android源码中经常会使用移位运算来代替乘除运算,因为移位运算的性能比乘除运算的高(PS:对于计算机而言,移位运算只是移了个位置),所以了解移位运算的计算过程对于我们阅读源码会有一定的帮助。

原码、反码、补码

原码是人脑最容易理解和计算的表示方式

第一位表示符号, 其余位表示值

-1的原码是10000000 00000000 00000000 00000001

反码是人脑无法直观看出其数值的. 通常需要转换成原码在计算其数值

正数的反码是其本身

负数的反码是在其原码的基础上, 符号位不变,其余各个位取反

-1的反码是11111111 11111111 11111111 11111110

补码是人脑无法直观看出其数值的. 通常需要转换成原码在计算其数值

正数的补码就是其本身

负数的补码是在其原码的基础上, 符号位不变, 其余各位取反, 最后+1. (即在反码的基础上+1)

-1的补码是11111111 11111111 11111111 11111111

左移运算符:<<

System.out.println(1<<1); // 2
System.out.println(1<<32); // 1
System.out.println(-1<<1); // -2
System.out.println(-1<<32); // -1

结论:丢弃左边指定位数,右边补0

右移运算符:>>

System.out.println(1>>1); // 0
System.out.println(1>>32); // 1
System.out.println(-1>>1); // -1,因为-1的二进制反码是11111111 11111111 11111111 11111111
System.out.println(-1>>32); // -1

结论:丢弃右边指定位数,左边补上符号位

无符号右移运算符:>>>

System.out.println(1>>>1); // 0
System.out.println(1>>>32); // 1
System.out.println(-1>>>1); // 2147483647
System.out.println(-1>>>32); // -1,这里仍然是-1,是因为int类型是32位,32%32=0,所以实际上并没有发生移位

结论:丢弃右边指定位数,左边补上0

结论

对于机器而言,java中的移位运算都是对补码执行移位运算的,下面以-1<<1=-2为例进行讲解:

  1. -1的原码:10000000 00000000 00000000 00000001
  2. -1的反码:11111111 11111111 11111111 11111110
  3. -1的补码:11111111 11111111 11111111 11111111
  4. 执行移位操作
  5. -1移位后的补码:11111111 11111111 11111111 11111110
  6. -1移位后的反码:11111111 11111111 11111111 11111101
  7. -1移位后的原码:10000000 00000000 00000000 00000010
  8. 得到最后的原码十进制值为-2

添加新评论