-
复习:补码的运算
-
代码演示 与& 或| 非~ 异或^ 有符号右移>> 左移<< 无符号右移>>>
-
目前对于符号 >>> 我还存在一些疑问,疑问留在代码里了,自己看~
-
所有的数字对于位运算都是如下操作:转为补码 → 对补码进行位运算 → 再转换为原码 → 转为10进制
-
注意,不要漏掉符号位!符号位也是要参与运算的!
-
注意,int有32位,所以理论上应该每个数字都写满32位,但是为了方便起见,我们省略了一些位数。
public class BitArthimetic {
public static void main(String[] args) {
/**
* 与运算 & (双目运算)
* a = 011 补码 = 0,011
* b = 101 补码 = 0,101
* 补码一位按照 & 运算,获得 0,001(补码),再转为原码 0,001,再转为十进制 1
* 所以 a & b = 1
*/
int a = 3;
int b = 5;
System.out.println("a & b = " + (a & b)); //1
/**
* 或运算 | (双目运算)
* a = 011 补码 = 0,011
* b = 101 补码 = 0,101
* 补码每一位按照 | 运算,获得 0,111(补码),再转为原码 0,111,再转为十进制 7
*/
System.out.println("a | b = " + (a | b)); //7
/**
* 非运算 ~(单目运算)
* a = 011,补码 = 0,011
* 对补码进行每一位非运算,得到 1,100(补码),再转为原码 (符号位为1,表示是负数。符号位不变,其余位取反+1) = 1,100,再转为十进制 -4
*/
System.out.println("~a = " + ~a); //-4
/**
* 异或运算 ^ (双目运算)
* a = 011 补码 = 0,011
* b = 101 补码 = 0,101
* 对补码每一位进行异或运算,得到 0,110(补码),再转为原码 0,110,再转为十进制得到 6
*/
System.out.println("a ^ b = " + (a ^ b)); // 6
/**
* 左移运算符 <<(5<<2就表示对数字5进行左移2位的操作,空位补0)
* a = 0011 补码 = 0,0011
* a << 1 则将a左移1位,右边补0 得到补码 0,0110 转为原码 0,0110 转为十进制 6
* a << 2 则将a左移2位,右边补0 得到补码 0,1100 转为源码 0,1100 转为十进制 12
*/
System.out.println("a << 1 = " + (a << 1)); //6
System.out.println("a << 2 = " + (a << 2)); // 12
/**
* 带符号 右移运算符 >>
* (移动的时候,符号位也要一起移动哦!)
* (如果是正数,二进制串右移的时候用0来填充左边的空位,而对于负数而言,右移的时候用1来填充左边的空位)
* 3 = 0,011 补码=0,011 3>>1 得到补码 0,001 转为原码 0,001 转为十进制 1
* -3 = 1,000000011 补码=1,111101 -3>>1 得到补码 1,11111110 转为原码 1,000010 转为十进制 -2
*/
System.out.println("3>>1 = " + (3>>1)); //1
System.out.println("-3>>1 = " + (-3>>1)); //-2
/**
* 无符号 右移运算符 >>>
* (移动的时候,符号位也要一起移动哦!)
* 带符号右移的运算规则与无符号右移的运算规则差别就在于:无符号右移在二进制串移动之后,空位由0来补充,与符号位是0还是1毫无关系
* 3 = 0,011 补码=0,011 3>>>1 得到补码 0,001 转为原码 0,001 转为十进制 1
* -3 = 1,00000011 补码=1,1111101 -3>>>1 得到补码 0,11111110 转为原码 0,11111110 转为十进制 2147483646
*/
System.out.println("3>>>1 = " + (3>>>1)); //1
System.out.println("-3>>>1 = " + (-3>>>1)); // 2147483646
}
}