目前,计算机表示整数普遍采用的就是二进制补码记数法。它是用固定数目的二进制位来表示整数,通常是32位。如1表示成
00000000 00000000 00000000 00000001
但这里,为了方便,我们先看看3位二进制和4位二进制:
补码记数法
位模式 | 所表示的值 | 位模式 | 所表示的值 |
---|---|---|---|
- | - | 0111 | 7 |
- | - | 0110 | 6 |
- | - | 0101 | 5 |
- | - | 0100 | 4 |
011 | 3 | 0011 | 3 |
010 | 2 | 0010 | 2 |
001 | 1 | 0001 | 1 |
000 | 0 | 0000 | 0 |
111 | -1 | 1111 | -1 |
110 | -2 | 1110 | -2 |
101 | -3 | 1101 | -3 |
100 | -4 | 1100 | -4 |
- | - | 1011 | -5 |
- | - | 1010 | -6 |
- | - | 1001 | -7 |
- | - | 1000 | -8 |
在二进制补码系统中,最左边的二进制位指明所标示数值的符号,称为符号位。其中,1表示负数,0表示非负数(包括自然数0)。
二进制补码系统是这样构成的:
对于非负数:先规定适当长度的一组二进制0,使用二进制计数,从右向左,直到只有一个0,其他都是1的模式形成。这样形成的数有0、1、2、3……
对于负数:先规定适当长度的一组二进制1,使用二进制反向计数,从右向左,直到只有一个1,其他都是0的模式形成。这样形成的数有-1、-2、-3……。其中,反向计数让很多人难以理解,你可以从表格的底部开始计数。
总结一下:
二进制补码系统,以0开头表示非负数,以1开头表示负数。
因为非负数中包括0,所以对于4位模式的数字,其能表示的最大正数为2^3-1 = 7,但负数中不包括0,所以其能表示的最小的负数为-2^3 = -8。
求正数的负数二进制表示
对比表格中的数所对应的二进制表示,你会发现很有意思的一点:0和-1的二进制是按位取反的,1和-2也是如此,2和-3同样……
这是一个很有趣的发现。但是我们更希望建立一个1和-1,2和-2,3和-3……之间的关系,而不是0和-1,1和-2,2和-3……。
那么如何根据一个数的正数二进制形式,写出相对应的负数二进制呢?比如,已知6的二进制为0110,怎么样写出-6的二进制呢?
很简单:以6的二进制0110为例,从右向左看,在遇到第一个1之前(包括第一个1),都依次抄写,在第一个1之后的所有二进制位都依次取反。
那么,从右向左看,6的二进制0110的右边第一位是0,则-6的右边第一位也为0;右边的第二位是1(为第一个1),则-6的右边第二位也为1;右边的第三位为1(在第一个1之后,所以依次取反),则-6的右边第三位为0;右边的第四位为0,则-6的右边第四位为1。所以-6的二进制为1010。
求负数的正数二进制表示
已知正数的二进制表示,求其负数的二进制表示也是一样的规则:从右向左看,在遇到第一个1之前(包括第一个1),都依次抄写,在第一个1之后的所有二进制位都依次取反。
二进制补码记数法中的加法
使用二进制补码记数法主要是为了简化计算机电路设计,它可以使得减法转化为加法。而加法的电路设计是很简单的,主要是运用逻辑电路实现,但减法电路的设计通常很困难。所以通过二进制补码记数法,可以使得减法运算变成加法,使用同一套电路。
比如:7-2=5,可以转化为7+(-2)=5。其中-2就是通过2的二进制转化来的。
值得一提的是,在计算过程中,包括答案的所有位模式长度都是相同的。从右向左运算时,最后一位可能产生进位,会造成答案多出一位。这时,需要把这多出的一位删除掉。不用担心删除过后正确性会造成影响,其实删除掉过后的答案才是正确的。比如0101+0010=0111,又比如0111+1011=0010(0111+1011=10010,缩减为0010)。就是这么神奇!
使用二进制补码计数法的计算机只要学会加法就可以了,计算机需要一个加法电路和一个取负电路。
加法的溢出问题
因为使用二进制补码系统时,位数是固定的,所以可以表示的数值大小也是有限制的。比如说,4位模式的二进制补码系统,所能表示的最大正整数是7,最小负整数是-8。所以,9就无法表示,5+4你不会得到正确的结果9,而会得到-7。
溢出指的是,计算的结果超出了可以表示的数值范围。
可以分三种情况讨论:
1. 正数+正数:这时可能发生溢出问题。如果两个正数的和为负数,毫无疑问,发生了溢出。
2. 负数+负数:这时也可能发生溢出。如果两个负数的和为正数,肯定发生了溢出。
3. 正数+负数:这时运算结果不会发生溢出问题。除非两个参与运算的数本身已经溢出了。
简单地说,两个正数的和为负,或者两个负数的和为正,那么肯定发生了溢出。
不用太过担心这个问题,因为我们实际使用的位模式都是32位,或者64位的,可以表示的数非常大。
余码记数法
除了补码记数法,还有一种记数方法是余码记数法。它跟补码记数法很类似,只有一点区别:它的符号位使用1表示正数,使用0表示负数。
位模式 | 所表示的值 |
---|---|
111 | 3 |
110 | 2 |
101 | 1 |
100 | 0 |
011 | -1 |
010 | -2 |
001 | -3 |
000 | -4 |
问题与练习:
1.将下面每一个二进制补码表示转换为相应的十进制形式。
a. 00011 b.01111 c.11100
2.用8位位模式将下列每一个十进制表示转换为相应的二进制补码形式。
a.6 b.-6 c.-17
3.假定下列位模式表示的是用二进制补码计数法存储的数值,求出每一个值的负值的二进制补码表示。
a. 00000001 b.11111110 c. 01010101
4.假定一台机器用二进制补码记数法存储数值,如果及其分别采用下列长度的位模式,那么可以存储的最大数和最小数分别是什么?
a.4 b.6 c.8
5.计算下列由二进制补码记数法表示的问题,按照二进制补码记数法求出他们的答案。要注意观察可能会产生的溢出问题。
a. 0100 b. 0101 c. 1010
+0011 +0110 +1010
—————— —————— ——————
6.在二进制补码记数法里,一个整数和一个负数相加时会产生溢出吗?请说明理由。
注:文章习题和图片摘自 《计算机科学概论 11版》https://book.douban.com/subject/6862061/ 。