为什么计算中负数表示为补码?
计算机中数的表示
一、整数的表示
计算机中所有类型的数都采用二进制编码,整数也不例外。
正整数的表示,比较好理解,例如正整数“23”用8位数二进制编码表示为“00010111”,8位正整数可以表示的范围0~255。
负数的表示就不是那么显而易见。以8位数为例,一般的想法是,将最高位用作符号位,其余编码与正整数类似。以“-23”为例,其二进制编码表示为“10010111”,可以看出“23”和“-23”除了符号位不同之外,其它位均一样。但实际上在计算机中负数并不是这样表示的,在讲解负数的表示之前,有必要先介绍一下CPU中的运算单元ALU。
二、CPU运算单元ALU
CPU的运算单元一般有整形ALU、符点型ALU、向量ALU等。其中整数运算就用到整形ALU。不同CPU的整形ALU包含的部件不尽相同,但都包含两种最基础运算逻辑单元:加法器和移位器。早期的CPU没有乘法器,乘法运算可以转换为加法运算和移位运算,同样减法运算也是转为加法运算。这也是为什么通用CPU的运算力一般要远落后DSP或GPU这种专用计算元件,后者大量集成加法器、乘法器,甚至还有卷积运算单元。
三、负数的表示
因为减法算法在CPU同样是用加法器计算,如果按第一节的想法将“-23”表示为“10010111”,那么23+(-23)的结果将是“00010111”+“00010111”=“10101110”,显然结果“10101110”怎么都不可能是0。
那有什么办法让“23”的二进制表示加上“-23”的二进制表示等于0呢?伟大的计算机先驱们想到一个办法,负数可以表示为其绝对值取反加1。如图所示,其中第9位溢出了,8位的数的结果即为“0000000”。
这里给出负数表示的结论:计算机中的负数表示为其绝对值取反加1。
四、理论证明
第三节仅通过X+(-X)=0这一种特殊情况说明了-X=|X|取反加1,那对于一般的加法X+(-Y)是不是仍然可以将-Y表示为|Y|取反加1呢?答案是肯定的。
在证明之前,首先需要了解“模”的概念。“模”是指一个计量系统的计数范围。计算机能够表示的范围也是有限的。以8位数计算系统为例,能够表示0~255,8位计算系统的模即为256(二进制表示100000000)。容易想到,在8位数计算系统中任意一个数加上或减去系统的模其结果仍然不变,100000000 + 8位数X = X,因为最高位溢出,结果不变。
对于一般的X+(-Y) = X+100000000-Y = X+1+(11111111-Y).容易看出,(11111111-Y)即为|Y|取反,因为不论X为何值,(-Y)都可以表示为|Y|取反加1。