计算机中的数均以0和1组成各种编码,在计算机中参与运算的数有两大类: 无符号数和有符号数。
计算机中的数均放在寄存器中,通常称寄存器的位数为机器字长。
对于有符号数,我们需要使用一位标志位表示其正负符号,这就引出了几种编码表示方式。 (下面均以8位机器字长进行分析)
原码
将最高位用来表示其正负标志:
正数最高位为0
负数最高位为1
例如:
[+1]原 = 0,000 0001
[-1]原 = 1,000 0001
但是这就带来一个问题,做普通的加法运算的时候:
1+1=0,000 0001 + 0,000 0001 = 0,000 0010 = 2 正确
1-1= 1+(-1)= 0,000 0001 + 1,000 0001 = 1,000 0010 = -2 错误
这就意味着在计算减法时,我们不能直接通过原有的加法电路来计算减法,而需要重新设计专门的计算电路来处理原码表示方法中的符号位的计算。
反码
反码可以通过原码转换得到:
当值大于0时,反码和原码相同
当值小于0时,反码=保留符号位,其余部分按位取反
例:
[+1]反 = 0,000 0001
[-1]反 = 1,111 1110
对其做加法运算:
1+1=0,000 0001 + 0,000 0001 = 0,000 0010 = 2 正确
1-1= 1+(-1)= 0,000 0001 + 1,111 1110 = 1,111 1111
将其转换为原码为1,000 0000 = -0 = 0 正确
补码
补码的计算规则:
当值大于0时,补码和原码相同
当值小于0时,补码=保留符号位,其余部分按位取反,然后+1(即在反码的基础上+1)
例:
[+1] = [00000001]原 = [00000001]反 = [00000001]补
[-1] = [10000001]原 = [11111110]反 = [11111111]补
对其做加法运算:
1+1=0,000 0001 + 0,000 0001 = 0,000 0010 = 2 正确
1-1= 1+(-1)= 0,000 0001 + 1,111 1111 = 1 0000 0000
由于最高位溢出,得到0,000 0000=0 正确
从以上我们知道,原码是最适用于人类认知的一种编码方式,但是为什么会有反码和补码的编码方式呢?
从上面关于原码计算减法的计算方案我们知道,由于将符号位直接带入计算中带来的影响,在做减法的时候,往往得到的是错误的答案。
反码的提出使直接将符号位带入计算成为了可能。将减法运算,转换为加上减数的相反数,使减法计算可以复用加法计算电路。
下面我们来看如下两个数值:
[0,000 000]反 = +0
[1,111 111]反 = -0
这样就造成了0有两种表示方法,使原本8位长度的寄存器只能表示-127-0, 0-127共255个值,比无符号数的表示方法少了一个值,因为0有+0和-0两个表示方法。
而补码的出现,解决了0有+0和-0两种表达方式的困境,我们人为规定1,000 0000用来表示-128,因为原码无法表示-128,按正常程序更无法求得其补码。
这样一来,我们就只有唯一的[0]补的表现形式0,000 0000,而且多了一个[1,000 0000]补表示负数的最小值-128
通过以上我们看到,计算机通过将有符号数进行不同的进位和表示方法,巧妙地将符号位参与到了加法运算中,那么其中的数学原理是什么呢?
下面首先介绍几个概念:
同余
两个整数a,b,若它们除以整数m所得的余数相等,则称a,b对于模m同余,记作 a ≡ b (mod m),读作 a 与 b 关于模 m 同余。
例:
4 mod 12 = 4
16 mod 12 = 4
28 mod 12 = 4
所以4, 16, 28关于模 12 同余。
计算机的字长有限,当计算得到的结果大于寄存器所能的最大长度时,会发生溢出,最高位将被舍去。
例:
对于无符号数,8位寄存器所能表达的最大数字为max = 2^8-1,那么当做加法运算max+1时,由于发生溢出,最高位被丢弃,得到的结果其实是
(max+1) mod 28,只取到对于28的余数部分。
即计算机中的所有运算实际上都是关于2^字长的同余计算。
补码的数学证明
任何计数系统都必须有两个参数:容量和精度。
模是衡量计数系统容量的参数。模代表了计数系统所能表示和存储的状态数。
比如对于字长为8的计算机,其最大能表示0-255的数,所以其模为256=28
任何有限的计数系统都有一个确定的模。如时钟的模是12,时钟每经过12小时会重新从1开始计数。
计算机同样也是一个有限容量的计数系统,其模m=2字长。
设m > b >= 0,b为整数
则b的补 b = m – b (这里定义的是补,而不是补码)
由于有正负数,计算机中对正负数的补码进行了区分定义:
1> 正整数b的补码为自身,即b的补码仍为b
2> 负整数-b的补码为b的补,即b
我们知道,a - b即可转化为 a + (-b),如果用补码来运算
a – b = [a + (-b) ] (mod m) 在计算机中计算的是 [a + b补 ] (mod m)
如果能证明 [a + (-b) ] (mod m)与[a + b补 ] (mod m)同余,那么就能说明通过以上两个式子在计算机中都能得到正确的值。
∵ b 补= m – b
∴ a + b补 = a + (m – b) = a - b + m
又 ∵a - b + m 与a - b关于m同余
∴ a - b 和 a + b补关于m同余
∴ 将负数转化为补码进行计算后,仍然是成立的
所以,计算机中用补码来储存所有的数后,就不需要增加减法器了,用加法器就可以代替计算减法,这样能节省电路设计。
.
参考资料:
http://www.cnblogs.com/organic/p/6486676.html
http://blog.csdn.net/vickyway/article/details/48788769
http://baike.baidu.com/item/%E5%90%8C%E4%BD%99%E5%AE%9A%E7%90%86/1212360?fromtitle=%E5%90%8C%E4%BD%99&fromid=1432545
https://zh.wikipedia.org/wiki/%E5%90%8C%E9%A4%98
https://www.zhihu.com/question/20159860/answer/21113783