1.计算机内部为什么没有减法器?
减法运算本身其实就是加法,如x - y即x +(-y),所以只需要将负数成功表示出来并可以参加加法运算,那加法器就可同时实现“+”和“-”的运算。这相比于对“+”和“-”做电路区分,会起到简化了硬件电路结构的作用,不用区分加减法也使得处理效率被提高。
2.负数如何成功表示?
2.1.原码表示法:
最早的可以表示负数的表示法叫做原码表示法,他是机器数最简单的一种表示形式。
原码依据机器数符号位规定来直接区分正负,例如字长为单字节0000 0001则表示1,1000 0001则表示-1。
这样的表示法比较直观,但是它的加法器电路则会较复杂:
机器要首先判断两数的符号是否相同,如果相同则两数相加,若符号不同,则两数相减。换言之,用这样一种直接的形式进行加运算时,负数的符号位不能与其数值部分一道参加运算,而必须利用单独的线路确定和的符号位,也就是还是需要用到减法器。
因此为解决机器内负数的符号位不能一起参加运算的问题,以简化电路,计算机中也就引进了补码这一机器数的实现形式。
2.2.补码的实现理论——补数
模:
当一个计量单位存在一个计数范围时,就对应会有“模”的概念。
“模”约束着计量单位的计数范围,他代表被计量单位舍弃的溢出量。因此计数范围内的值实际上为“模”的余数。显然,模值实际上就是计量单位的最大表示数+1。
例如时钟钟表这个计量单位的计数范围是0-11,则12就是他的模值,这个值作为溢出量被自动丢弃,所以12在该计量单位中被溢出丢失,从而变为0,13为1。
负数的补数:
通过上述模的溢出舍弃,即可实现减法(负数)化加法(正数)的操作。
例如时钟向后拨动n(减法)即可转换为向前拨动12-n。以2点钟为例,2点钟 +( - 1),即向后(减)拨动1,可等价于2点钟 + 11,即向前(+)拨动11。
11被称为(-1)的补数。
可见负数和他的补数的关系为:负数的补数 = 模值 - 负数的绝对值
,即负数的绝对值 + 补数 = 模值
。
也就是负数的补数
和负数的绝对值
相对于模
而言,呈现为互补关系,所以才叫做补数。
2.3.计算机中的补码:
计算机中的补数也被称为补码,在香港台湾则被叫做二补数。
计算机对数字的表示是通过二进制位来表示的,所以计量单位也就是n个bit。
例如:计量单位是8个bit,则计数范围为0000 0000 ~ 1111 1111
,一共256种表示,模值为1 0000 0000
(达到该值则溢出舍弃)。
为了使得计算机可以表示出负数以完成减法运算,计算机中将负数的补码拿来当做负数用,所以这256种表示实际上则对应着:0、1 ~ 127、-1 ~ -127、-128,这256个值。
例如-1
的绝对值是1
,也就是0000 0001
。所以补数为1 0000 0000 - 0000 0001 = 1111 1111
。
同理可得所有负数的补码:
-001 → 1 0000 0000(256)- 0000 0001(001)= 1111 1111
-002 → 1 0000 0000(256)- 0000 0010(002)= 1111 1110
-003 → 1 0000 0000(256)- 0000 0011(003)= 1111 1101
...
-127 → 1 0000 0000(256)- 0111 1111(127)= 1000 0001
-128 → 1 0000 0000(256)- 1000 0000(128)= 1000 0000
此时会发现128和-128是相同的表示,但是为顺应机器数符号位的规定,1000 0000
被视为-128。
结合上面讲的模的溢出舍弃特性,此时补数即可以直接参与运算。至此也就使得了一个加法器可以同时进行加法运算和减法运算,且不用区分符号位。
2.4.为什么会有“补码=反码+1“?
仍然以上面的单字节情况来讨论,以-2
的补码为例,可以发现补码的得出算式其实可以转换为:(1111 1111 + 0000 0001) - 0000 0010
,也就是(1111 1111 - 0000 0010) + 0000 0001
。
其中的1111 1111 - 0000 0010
的这一中间结果1111 1101
,被称为2
的反码。
通过这样的转换,即可让逻辑电路在他的计数范围内(比如这里的单字节计数范围)能够推算出负数的补码,也就是所谓的“补码 = 反码 + 1”。
因此这个公式所谓的公式,只是给逻辑电路来理解的,就向上面所说,是为了让逻辑电路可以在他的计数范围内的以推算出补码(补数),
所以,我们人没必要通过这个所谓的公式来理解或是计算,直接一个模 - 绝对值
就完事儿。