原码反码补码 一切都是表象

1.负数为什么用补码表示?

对于十进制数转二进制数,我们并不陌生。考虑8位二进制数,将8表示成二进制数是00001000(原码),-8表示成二进制数是10001000(原码),其中最高位为符号位,0表示正数,1表示负数。

然而在计算机中,负数是用补码来表示的

必须明确,正数的原码、反码和补码都是它本身。需要额外讨论的,只有负数。除符号位外,对原码按位取反,得到反码;将反码加1,得到补码。

以-8为例,计算方法如下:
原码10001000

反码11110111

补码11111000

为什么不采用更加直观的原码呢,用补码表示负数意义何在

还是以-8为例,现在有两种表示方法,一种是原码表示法,即10001000;另一种是补码表示法,即11111000。请问,哪一种表示法在加法运算中更方便?

随便写一个计算式,16 + (-8) = ?
16的二进制表示是 00010000,用原码表示法,加法就要写成:
 00010000
+10001000
---------
 10011000
可以看到,如果按照正常的加法规则,就会得到10011000的结果,转成十进制就是-24。显然,这是错误的答案。也就是说,涉及到负数的加法运算,正常的加法规则不适用。怎么办呢?一种策略是
分而治之,即制定两套运算规则,一套用于正数加正数,另一套用于正数加负数。一种策略是合而为一实现一统,即使用补码。
现在,请看补码表示法。
 00010000
+11111000
---------
100001000
可以看到,按照正常的加法规则,得到的结果是100001000。注意,这是一个9位的二进制数。我们已经假定这是一台8位机,因此最高位即第9位是一个
溢出位,会被自动舍去。所以,结果就变成了00001000,转成十进制正好是8,也就是16 + (-8) 的正确答案。这说明了,补码表示法可以将加法运算规则扩展到全体整数集。为什么负数用补码来表示?为了实现加法运算法则的统一。

2. 时钟与模、补码本质与正确性

我们先看一下模的概念。模是指一个计量系统的计量范围。下图时钟可以看做一个计量器,这是改版的时钟,刻度12改成了刻度0。

时钟的计量范围是0~11,模=12。模”实质上是计量器产生“溢出”的量,它的值无法在计量器上表示出来,计量器上只能表示出模的余数。任何有模的计量器,均可化减法为加法运算。假设当前时针指向10点,而准确时间是2点,调整时间可有以下两种拨法:可以往回拨8个小时,也可以向前拨4个小时。在以12模的系统中,加4和减8是同样的效果。因此,凡是减 8运算,都可以用加 4来代替。相对于模而言,8和4互为补数,原数 +补数=模。实际上以12模的系统中,11和1,10和2,9和3,7和5,6和6都有这个特性。显而易见,两者相加等于模。

计算机也可以看成一个计量器,它也有一个计量范围,即存在一个模。对于n位计算机,假设n=8,每个比特位(bite)可以为0或1,从00000000到11111111,能表示从0~255之间的整数,一共256个,所以8位二进制系统的模为2^8=256。若将n位计算机看成一个计量系统,它的模等于2的n次方。在此系统中,减法问题也可以化成加法问题。相对于模而言,原码和补码互为补码,原码 +补码 =模

以下数学关系式不言而喻:

原数 +补数=模

原码 +补码 =模

原码 +反码 +1=模

补码 =反码 +1

3.负数需要原码吗?

 十进制数             原码               反码              补码

      -1              10000001        11111110     11111111

      -2              10000010        11111101     11111110

      …                   …                                   

    -127            11111111        10000000     10000001

    -128                  -                       -              10000000

表格中有两个数据是空着的,十进制数-128,原码写成10000000 、反码写成11111111合适吗?实际上,-128并没有原码和反码,而-128的补码是怎么来的呢?观察补码这一列,从上到下,要得出-128的补码是10000000这一结论,应该比较自然。似乎是这样的,补码必须得有,原码有没有无所谓。原码→反码→补码的推导逻辑真的没问题吗,到底谁在前,谁在后?原码+补码→反码的推导逻辑似乎更合理。

理顺原码、反码和补码的关系,需要从头开始。

使用补码,计算1-1=1+(-1)=?

    000 0 000 1
+ 1  1 1 1  1  1  1  1 
---------
  0 0 0 0 000 0

使用补码,计算-1-127=-1+(-127)=?

    1  1 1 1  1  1  1  1 
+1 00 0 000 1
---------
1  1 0 0 0 000 0

负数表示成原码参与计算时,无法统一加法运算法则;引入反码,计算式1-1的结果为10000000得出-0,0带负号没有任何意义;引入补码,1-1的结果是00000000,解决了-0的问题,同时计算式-1-127的结果为10000000,这样既解决了原先的-0问题,又扩展了负数的范围,即多了一个-128。计算机内部用什么方式表示负数,其实是无所谓的,只要能够保证一一对应的关系。目前使用的补码,应该是最方便简洁的。

4.符号位存不存在?

如前所述,正数的原码、反码和补码都是它本身,负数用补码表示。这是表象,真相并非如此。可以这么说,计算机中根本不存在原码,所有数都以补码形式保存,所有的加减运算都是补码间的加法运算。

  数                 补码                 模-补码      原码

-128       10000000→128          -                -

-127       10000001→129         127      11111111           

…                   …                        …           …

 -2          11111110→254           2        10000010           

 -1          11111111→255           1        10000001           

  0           00000000→0               -        00000000           

  1           00000001→1               -        00000001           

  2           00000010→2               -        00000010           

  3           00000011→3               -        00000011           

 …                 …                          …            …

126        01111110→126            -        01111110           

127        01111111→127            -        01111111           

在-128~127之间的整数与补码之间存在一一对应关系,正数的原码=补码,负数的原码=模-补码。补码的最高位的1当作负号了吗?根本没有,其实是0~255这些整数及其与-128~127的映射关系罢了。在补码加原码等于模的计算过程中,根本就没有把最高位的1当作符号位,而是当作实实在在的1来计算的。符号位是一个善意的谎言,是为了方便人类理解而假想出来的。-128的原码写成1000 0000也无可厚非,却为何不写呢?因为追求严谨。

5 知道了原码的真相后该如何面对原码?

真相是:

机器数根本不存在原码,所有数据都是以补码形式保存。

机器数根本不存在符号位。

逻辑顺序是补码→原码。

正数的原码=补码。

负数的原码=模-补码。


看清了真相,却依然喜爱这样的描述方式:

机器数最高位是符号位,0表示正数,1表示负数。

逻辑顺序是原码→反码→补码。

正数的补码=反码=原码。

负数用补码表示,补码=反码+1。


特别感谢:

https://www.douban.com/note/279593693/

http://blog.csdn.net/scythe666/article/details/46872391

http://www.cnblogs.com/zhangziqiu/archive/2011/03/30/ComputerCode.html

https://www.zhihu.com/question/20159860/answer/21113783


  • 5
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值