java位运算符详细推算过程

531 阅读3分钟

前言

开始之前,先回顾一下二进制原码、反码和补码之间的转换及计算机怎么处理二进制的。

  • 二进制的最高位是符号位:0代表正数,1代表负数;
  • 正数的原码,反码,补码都一样(三码合一);
  • 负数的反码=它的原码符号不变,其他位取反;
  • 负数的补码=它的反码+1(负数的反码=负数的补码-1);
  • 0的反码、补码都是0;
  • Java没有无符号数;
  • 在计算机底层运算的时候,都是以补码的方式来运算的
  • 当我们看运算结果的时候,看的是它的原码

位运算符

  1. 按位与&:两位全为1,结果为1,否则为0;
  2. 按位或|:两位至少一个为1,则为1,否则为0;
  3. 按位异或^:两位不同,则为1,相同为0;
  4. 按位取反~:0->1,1->0;
  5. 算术右移>>:低位溢出,符号位不变,并用符号位补溢出的高位;
  6. 算术左移<<:符号位不变,低位补0;
  7. 逻辑右移(无符号右移)>>>:低位溢出,高位补0。(注意没有<<<)

运算推算

public class BitOperator02 {
	public static void main(String[] args) {
		System.out.println(1>>2);//0
        }
}
  • 1>>2,1算术右移:低位溢出,符号位不变,并用符号位补溢出的高位(注意:计算机操作的始终是补码)
  • 正数的三码合一,1的补码:00000000 00000000 00000000 00000001
  • 1>>2的原码: 00000000 00000000 00000000 00000000--溢出01
  • 结果为0,其实相当于把1/2/2,商就是结果0
public class BitOperator02 {
	public static void main(String[] args) {
		System.out.println(-1>>2);//-1
        }
}
  • -1的原码:10000000 00000000 00000000 00000001
  • -1的反码:11111111 11111111 11111111 11111110
  • -1的补码:11111111 11111111 11111111 11111111
  • 用符号位即1补溢出的高位,-1>>2的补码: 11111111 11111111 11111111 11111111--溢出11
  • -1>>2的反码: 11111111 11111111 11111111 11111110
  • -1>>2的原码: 10000000 00000000 00000000 00000001
  • 结果为-1
public class BitOperator02 {
	public static void main(String[] args) {
		System.out.println(1<<2);//4
        }
}
  • 1<<2 1算术左移:符号位不变,低位补0
  • 1的原码:00000000 00000000 00000000 00000001
  • 1<<2: 00000000 00000000 00000000 00000100
  • 结果为4,相当于122
public class BitOperator02 {
	public static void main(String[] args) {
		System.out.println(-1<<2);//-4
        }
}
  • -1的补码:11111111 11111111 11111111 11111111
  • 算术左移:符号位不变,低位补0
  • -1<<2的补码:11111111 11111111 11111111 11111100
  • -1<<2的反码:11111111 11111111 11111111 11111011
  • -1<<2的原码:10000000 00000000 00000000 00000100
  • 结果为-4,相当于-1*2 *2
public class BitOperator02 {
	public static void main(String[] args) {
		System.out.println(1>>>2);//0
        }
}
  • 逻辑右移(无符号右移)>>>:低位溢出,高位补0(无<<<符号)
  • 1的补码:00000000 00000000 00000000 00000001
  • 1>>>2的补码即原码:00000000 00000000 00000000 00000000--溢出01
  • 结果为0
public class BitOperator02 {
	public static void main(String[] args) {
		System.out.println(-1>>>2);//1073741823
        }
}
  • -1的补码:11111111 11111111 11111111 11111111
  • -1>>>2的补码(即原码):00111111 11111111 11111111 11111111--溢出11(变正数了,三码合一,这个即是原码
  • 结果为1073741823

结语

特别需要注意的是:逻辑右移也就是无符号右移的时候,因为是使用0来补高位的,所以始终会是正数,根据三码合一原则,就可以知道变化后的补码即是原码。