Java 负数二进制转换、位移、位运算
2019-08-22 本文已影响0人
xujicheng
Java 中 int型->32bit
范围-2147483648~2147483647
[1000,0000,0000,0000,0000,0000,0000,0000~0111,1111,1111,1111,1111,1111,1111,1111]
其中左起最高位是符号位 1表示负数 0表示正数
- 正负数如何转换呢
例如:5 [0000,0000,0000,0000,0000,0000,0000,0101]
- 对原码二进制进行取反操作
1111,1111,1111,1111,1111,1111,1111,1010 - 对取反后的结果进行补码[+1]操作得到-5的二进制
1111,1111,1111,1111,1111,1111,1111,1011
-
左位移 <<
例如://5 [0000,0000,0000,0000,0000,0000,0000,0101] int i = 5 << 1; //[0000,0000,0000,0000,0000,0000,0000,1010] = 10 int I = 5 << 2; // [0000,0000,0000,0000,0000,0000,0001,0100] = 20 //6 [0000,0000,0000,0000,0000,0000,0000,0110] int i = 6 << 1; // [0000,0000,0000,0000,0000,0000,0000,1100] =12 int I = 6 << 2; // [0000,0000,0000,0000,0000,0000,0001,1000] =24
二进制左移一位,其实就是将数字翻倍
- 右位移 >>
例如 :
//5 [0000,0000,0000,0000,0000,0000,0000,0101]
int i = 5 >> 1;
//[0000,0000,0000,0000,0000,0000,0000,0010] = 2
int I = 5 >> 2;
// [0000,0000,0000,0000,0000,0000,0000,0000] = 1
//6 [0000,0000,0000,0000,0000,0000,0000,0110]
int i = 6 >> 1;
// [0000,0000,0000,0000,0000,0000,0000,0011] =3
int I = 6 << 2;
// [0000,0000,0000,0000,0000,0000,0000,0001] =1
二进制右移一位,就是将数字除以 2 并求整数
- 右位移 >> 和 >>>的区别
Java中定义了2种右移:逻辑右移>>>和算术右移>>
目的是为了符号位是1是否右移。
逻辑右移>>>一位 左边补0
算术右移>>一位 左边补1
验证一下:
System.out.println(Integer.toBinaryString(Integer.MIN_VALUE));
System.out.println(Integer.MIN_VALUE);
System.out.println(Integer.toBinaryString(Integer.MIN_VALUE>>>1));
System.out.println(Integer.MIN_VALUE>>>1);
System.out.println(Integer.toBinaryString(Integer.MIN_VALUE>>1));
System.out.println(Integer.MIN_VALUE>>1);
/**
* 10000000000000000000000000000000
* -2147483648
* 1000000000000000000000000000000
* 1073741824
* 11000000000000000000000000000000
* -1073741824
*/
System.out.println("----------------------------------------------");
System.out.println(Integer.toBinaryString(Integer.MAX_VALUE));
System.out.println(Integer.MAX_VALUE);
System.out.println(Integer.toBinaryString(Integer.MAX_VALUE>>>1));
System.out.println(Integer.MAX_VALUE>>>1);
System.out.println(Integer.toBinaryString(Integer.MAX_VALUE>>1));
System.out.println(Integer.MAX_VALUE>>1);
/**
* 01111111111111111111111111111111
* 2147483647
* 00111111111111111111111111111111
* 1073741823
* 00111111111111111111111111111111
* 1073741823
*/
目前看 逻辑右移和算术右移只是对负数有区别,算术右移是带着符号位右移并补上原先的符号位。
那么左移是否会影响到符号位呢?
验证一下
System.out.println(Integer.toBinaryString(Integer.MAX_VALUE));
System.out.println(Integer.MAX_VALUE);
System.out.println(Integer.toBinaryString(Integer.MAX_VALUE<<1));
System.out.println(Integer.MAX_VALUE<<1);
/**
* 01111111111111111111111111111111
* 2147483647
* 11111111111111111111111111111110
* -2
*/
可见左移永远只在末尾补0,会影响符号位。
- 位运算 & 、|、^
bit 0、1 分别代表了假、真
- | :逻辑或 参与操作的位中只要有一个位是 1,那么最终结果就是 1
例如
2147483647 | -2 = -1
01111111111111111111111111111111
11111111111111111111111111111110
----逻辑或(|)------------------------
=11111111111111111111111111111111
```
System.out.println(Integer.toBinaryString(2147483647|-2));
System.out.println(2147483647|-2);
// -1 逻辑或任何数的结果都是-1
System.out.println(Integer.toBinaryString(-1|4325));
System.out.println(-1|4325);
/**
*11111111111111111111111111111111
* -1
* 11111111111111111111111111111111
* -1
*/
```
-
&:逻辑与 参与操作的位中必须全都是 1,那么最终结果才是 1
例如
2147483647 & -2 = 2147483646
01111111111111111111111111111111
11111111111111111111111111111110
----逻辑与(&)------------------------
=01111111111111111111111111111110
```
System.out.println(Integer.toBinaryString(2147483647&-2));
System.out.println(2147483647&-2);
/**
* 01111111111111111111111111111110
* 2147483646
*/
```
- ^:逻辑异或 参与操作的位相同,那么最终结果就为 0,否则为 1
例如
2147483647 ^ -2 = 2147483646
01111111111111111111111111111111
11111111111111111111111111111110
----逻辑异或(^)------------------------
=10000000000000000000000000000001
```
System.out.println(Integer.toBinaryString(2147483647^-2));
System.out.println(2147483647^-2);
//所有的数异或自身都为0
System.out.println(2345^2345);
System.out.println(-2^-2);
/**
* 10000000000000000000000000000001
* -2147483647
* 0
* 0
*/
```