补码之求相反数

概念[来自wikipedia]

**原码(True form)**:一个二进制数左边加上符号位后所得到的码,且当二进制数大于0时,符号位为0;二进制数小于0时,符号位为1;二进制数等于0时,符号位可以为0或1(+0/-0)

反码(One’s complement):一种在计算机中数的机器码表示。对于单个数值(二进制的0和1)而言,对其进行取反操作就是将0变为1,1变为0

**补码(2’s complement)**:一种用二进制表示有号数的方法,也是一种将数字的正负号变号的方式,主要优点是 不需因为数字的正负而使用不同的计算方式

计算

正数:原码、反码、补码相同

负数:反码 — 符号位不变化,其余位数取反,补码 — 符号位不变化,其余各位原码取反+1, 即 反码+1

测试

代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@Test
public void byteTest() {
reverse(0);
reverse(6);
reverse(-6);
reverse(128);
reverse(-128);
reverse(1280);
reverse(-1280);
}

private Integer reverse(Integer a) {
System.out.printf("%5d\t%32s\t%5d\t%32s\t%5d\t%32s%n", a, Integer.toBinaryString(a), ~a, Integer.toBinaryString((~a)), ~a + 1, Integer.toBinaryString((~a + 1)));
return ~a + 1;
}

结果

1
2
3
4
5
6
7
0	                               0	   -1	11111111111111111111111111111111	    0	                               0
6 110 -7 11111111111111111111111111111001 -6 11111111111111111111111111111010
-6 11111111111111111111111111111010 5 101 6 110
128 10000000 -129 11111111111111111111111101111111 -128 11111111111111111111111110000000
-128 11111111111111111111111110000000 127 1111111 128 10000000
1280 10100000000 -1281 11111111111111111111101011111111 -1280 11111111111111111111101100000000
-1280 11111111111111111111101100000000 1279 10011111111 1280 10100000000

可以看出:

  • 对一个数字直接取反,并不是其相反数,需要+1

  • [+0]原码=0000 0000, [-0]原码=1000 0000

    [+0]反码=0000 0000, [-0]反码=1111 1111

    [+0]补码=0000 0000, [-0]补码=0000 0000