Java语言负值表示法

示例

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

s1s2x1 + x2溢出加法结果
00没有x1 + x2 = v1 + v2
00太大而无法用数据类型表示(溢出)
01没有
x1 + x2 - 2 = x1 + x2 - s2 * 2
              = v1 + v2
01
(x1 + x2)  2 = x1 + x2 - 2
                  = v1 + v2
10*见上文(交换兑付)
11没有太小而无法用数据类型表示(x1 + x2-2 n <-2 n-1;下溢)
11
(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)