# 2.3.3 补码的非
可以看到范围在 TMinw ≤ x ≤ TMaxw 中的每个数字 x 都有 +tw 下的加法逆元,我们将 -twx 表示如下。
原理:补码的非
对满足 TMinw ≤ x ≤ TMaxw 的 x,其补码的非 -twx 由下式给出:
| -twx | 条件 |
|---|---|
| TMinw | x = TMinw |
| -x | x > TMinw |
(2.15)
也就是说,对 w 位的补码加法来说,TMinw 是自己的加法的逆,而对其他任何数值 x 都有 -x 作为其加法的逆。
推导:补码的非
观察发现 TMinw + TMinw = -2w-1 + (-2w-1) = -2w。这将导致负溢出,因此 TMinw +tw TMinw = -2w + 2w = 0。对满足 x > TMinw 的 x,数值 -x 可以表示为一个 w 位的补码,它们的和 -x + x = 0。■
练习题 2.33 我们可以用一个十六进制数字来表示长度 w = 4 的位模式。根据这些数字的补码的解释,填写下表,确定所示数字的加法逆元。
| x(十六进制) | x(十进制) | -t4x(十进制) | -t4x(十六进制) |
|---|---|---|---|
| 0 | |||
| 5 | |||
| 8 | |||
| D | |||
| F |
对于补码和无符号(练习题 2.28)非(negation)产生的位模式,你观察到什么?
网络旁注 DATA:TNEG:补码非的位级表示
计算一个位级表示的值的补码非有几种聪明的方法。这些技术很有用(例如当你在调试程序的时候遇到值 0xfffffffa),同时它们也能够让你更了解补码表示的本质。
执行位级补码非的第一种方法是对每一位求补,再对结果加 1。在 C 语言中,我们可以说,对于任意整数值 x,计算表达式
-x和~x+1得到的结果完全一样。下面是一些示例,字长为 4:
x⃗ ~x⃗ incr(~x⃗) [0101]5[1010]-6[1011]-5[0111]7[1000]-8[1001]-7[1100]-4[0011]3[0100]4[0000]0[1111]-1[0000]0[1000]-8[0111]7[1000]-8从前面的例子我们知道 0xF 的补是 0x0,而 0xA 的补是 0x5,因而 0xFFFFFFFA 是 -6 的补码表示。
计算一个数 x 的补码非的第二种方法是建立在将位向量分为两部分的基础之上的。假设 k 是最右边的 1 的位置,因而 x 的位级表示形如 [xw-1, xw-2, ..., xk+1, 1, 0, ..., 0]。(只要 x ≠ 0 就能够找到这样的 k。)这个值的非写成二进制格式就是 [~xw-1, ~xw-2, ..., ~xk+1, 1, 0, ..., 0]。也就是,我们对位 k 左边的所有位取反。
我们用一些 4 位数字来说明这个方法,这里我们用斜体来突出最右边的模式 1, 0, ..., 0:
x -x [1100] -4 [0100] 4 [1000] -8 [1000] -8 [0101] 5 [1011] -5 [0111] 7 [1001] -7