原码、补码、反码、有符号数、无符号数
www.chinaunix.net
原码、补码和反码
在计算机里如何表示整数?
整数有无穷多个,在计算机里,通常我们只能表示出其中的一部分。假如我们用
n 个比特来表示一个整数。1 个比特有 2 个状态,n 个比特就有 2^n 个状态,
把这 2^n 个状态的集合记为 A. 显然,用 A,我们可以与 n 个整数建立起一
一对应。我们还希望 A 所表示的整数能够象整数那样地运算---整数,象整数那
样运算,这是不是一句废话?数学中的整数相加,仍然是一个整数,但 A 里两
个整数相加,我们却无法保证它们的和仍在 A 中,用代数的术语来讲,叫做 "
不满足封闭性",这是个很坏的性质。
一、补码
不过数学上有处理这个问题的成熟方案,如果我们能后退一步,让 A 表示的是
模 |A| 的剩余类,则加法运算马上就封闭了。而且这个时候 A 不仅可以与 2^n
个整数对应起来,而且,在某种意义下,可以与整数环 Z 对应起来。用代数的
观点,这个 "某种意义"就是所谓的同态。
整数有两种封闭运算,一种是加法,另一种是乘法。A 作为模 2^n 的剩余类,
也有加乘两种运算。定义 Z 到 A 的映射
f(x) = m mod 2^n
f 是一个同态,也就是说,f 满足这样的良好性质:
f(x+y) = f(x) + f(y)
f(xy) = f(x)f(y)
我们通常使用 10 进制数,在这个进制下,f(x) 并不容易计算,但是在计算机里,
本质的表示是二进制,于是 f(x) 的运算变得出奇地简单。如果 x 小于 2^n,则
x 的 2 进制表示就是 f(x),如果 x>=2^n,则要求其模 2^n 的余数,这恰好是
x 二进制表示的最低 n 位,换句话说,简单地把高位抛弃就行了。顺便指出,
f(0)=0, f(1)=1.
我们来看一看 A 中的加法,f(x)+f(y), 若结果小于 2^n,则运算自然封闭,如果
f(x)+f(y) >= 2^n,则取其最低的 n 位,用电路实现时,可以简单地扔掉高位,
保留低位。
到目前为止,一切都很好,但是减法怎么办呢?对整数运算而言,减去 a 不过
是加上 a 的相反数的同义语。只要对 A 中的每个元素,能容易计算出其相反
数就可以了。理论上 f(x) 的相反数就是
f(-f(x))
不过这个好像不容易计算,因为我们现在并没有给出 A 中"负数"的概念,事实
上 A 是模 2^n 的剩余类环,根本就没有所谓的负数。
这个困难也是容易处理的。作为 f(x) 的相反数,-f(x) 应该满足这样的性质:
-f(x) + f(x) = f(0) = 0
所以我们只要有在 A 中找一个元素,使得它与 f(x) 的和是 0 就可以了。但是
f(x) 本身可能含有很多比特 1,加上一个数能使它们变成 0 吗? 考虑到 A 中
的加法要模去一个 2^n,这个问题实际上很好办,只要让求出的和是 2^n 就可
以了。所以难发现 -f(x) 就是把 f(x) 的比特"取反"---即 0 变 1, 1 变 0,并
加上 1 就得到了 -f(x)。容易验证: