// 1、简单点
System.out.println(Integer.toBinaryString(-2));
// 2、自己写
/**
* 首先,Java 中所有数据都是以补码的形式表示
* 反码是什么这里就不说明了
* 正数的 补码 = 原码 = 反码
* 负数的补码 = 反码 + 1 (注意:符号为始终为1,在原码转反码的时候符号位不变,始终为 1)
* @param value 需要取补码是值
*/
public static void getComplement(int value) {
for (int i = 0; i < 32; i++) {
int t = (value & 0x80000000 >>> i) >>> (31 - i);
System.out.print(t);
}
}
说明:
1、这里要循环 32 次的原因是 int 是 32bit 的数据,如果是 long 的话就是 64 了
2、0x80000000 是 -2147483648 的十六进制表示,是 int 的最小值,二进制表示为 10000000000000000000000000000000,用这个数的原因是首位为 1 ,其余为 0,方便做位运算
3、上面的执行步骤 0x80000000 >>> i 表示 0x80000000 无符号右移 i 位
例如:
i = 2 时
10000000000000000000000000000000 >>> 2 = 00100000000000000000000000000000
4、再用第 3 点的结果和 value 做逻辑与运算,求出 value 的第 i 位是 0 还是 1,起标记作用
例如:
i = 2 , value = 2 时
00100000000000000000000000000000 & 00000000000000000000000000000010 = 00000000000000000000000000000000
5、后面的 >>> (31 - i) 表示把第 4 点求出的值右移 31 - i 位,由于前面的 0x80000000 >>> i 已经移动了 i 位,所以这里再移动 31 - i 位,剩下的值只有 0 或 1 了,也就是上面第 4 点求得的 0 或 1
例如:
i = 2
value & 0x80000000 >>> i = 00100000000000000000000000000000
那么
00100000000000000000000000000000 >>> (31 - i) = 00000000000000000000000000000001
6、最后关键点来了,哈哈哈哈哈!!!
奥秘就在这里
System.out.print(t);
不换行地打印,原来的 i 是从高位到低位循环出来的,这里这样打印就会使得高位先打印,低位排在后面,最后结果也就没错了
7、那么问题来了,为什么要用补码?
1) 更好地表示 0;
表示正数 0 时 00000000000000000000000000000000
表示负数 0 时 10000000000000000000000000000000
但是无论正数还是负数,0 的补码都是 00000000000000000000000000000000
2) 更好地参与运算
例如:用补码运算,直接把两个数的补码相加就行(因为 cpu 是没有减法运算的,只有累加器做加法运算)
-6 + 5 =
11111111111111111111111111111010
+
00000000000000000000000000000101
=
11111111111111111111111111111111
= -1