Java和大多数其他语言在表示2的补码表示法中存储负整数。
对于使用n位的数据类型的唯一二进制表示形式,值的编码如下:
最低有效n-1位x以整数表示形式存储正整数。最高有效值存储一点值s。这些位代表的值是
x-s * 2 n-1
即,如果最高有效位为1,则减去一个比您可以用其他位()表示的数字大1的值,从而允许从-2 n-1(s = 1 ; x = 0)到2 n-1-1(s = 0; x = 2 n- 1-1)。2n-2 + 2n-3 + ... + 21 + 20 = 2n-1 - 1
这也有很好的副作用,您可以将二进制表示形式添加为正二进制数:
v1 = x1 - s1 * 2n-1v2 = x2 - s2 * 2n-1
s1 | s2 | x1 + x2溢出 | 加法结果 |
---|---|---|---|
0 | 0 | 没有 | x1 + x2 = v1 + v2 |
0 | 0 | 是 | 太大而无法用数据类型表示(溢出) |
0 | 1 | 没有 | x1 + x2 - 2 = x1 + x2 - s2 * 2 = v1 + v2 |
0 | 1 | 是 | (x1 + x2) 2 = x1 + x2 - 2 = v1 + v2 |
1 | 0 | * | 见上文(交换兑付) |
1 | 1 | 没有 | 太小而无法用数据类型表示(x1 + x2-2 n <-2 n-1;下溢) |
1 | 1 | 是 | (x1 + x2) 2 - 2 = (x1 + x2 - 2) - 2 = (x1 - s1 * 2) + (x2 - s2 * 2) = v1 + v2 |
请注意,这一事实使查找加法逆(即负值)的二进制表示变得容易:
观察到将按位补码加到数字上会导致所有位均为1。现在加1会使值溢出,并且得出中性元素0(所有位0)。
因此,i可以使用来计算数字的负值(忽略int此处的可能提升)
(~i) + 1
示例:取负值0(byte):
否定的结果0是11111111。加1得出的值为100000000(9位)。由于abyte只能存储8位,因此最左边的值将被截断,结果是00000000
原版的 | 处理 | 结果 |
---|---|---|
0(00000000) | 否定 | -0(11111111) |
11111111 | 将1加到二进制 | 1亿 |
1亿 | 截断为8位 | 00000000(-0等于0) |