原码、反码、补码是什么
在二进制中数字采用原码来表达含义,但存储时确使用的是补码,而负数的补码又是通过反码计算得到的。
原码
在计算机中采用二进制来表示数值,以最高位来表示符号位来表示数值的正负,0001表示十进制的1,1001则表示-1。
反码
正数的反码就是原码
负数的反码是除符号位以外其余位数取反
+1=0001(原码)=0001(反码)
-1=1001(原码)=1110(反码)
补码
正数的补码和反码一样都是原码
负数的补码是反码+1
+1=0001(原码)=0001(反码)=0001(补码)
-1=1001(原码)=1110(反码)=1111(补码)
取模
以一个12小时表示的钟表为例,如果当前时间为4点,想要将钟表的时间调整到2点钟可以有两种方法。
- 将时钟往前拨动2小时即 4-2=2
- 将时钟往后拨动10小时即 (4+10) mod 12=2
第二种方法之所以能够使用这是因为钟表最高只能表示到12小时,而超过了这个阈值边会重置,这个12便可以成为模,而(4+10) mod 12=2这个过程就叫做取模
10 mod 12=10
(-2) mod 12=10
10和-2的余相等,可以看出在模为12的情况下-2与10是可以相互代替的。
在计算机中加法的运算远比减法要简单,因此就产生了通过加法来表示减法的方式。即1+(-1)=0这种方式。但是0001+1001=1010=-2而并非0。于是便产生了与调整钟表类似的,通过取模的方法来计算减法(不得不说想出这些方法的真是个人才)。
以4位二进制位例,由于最高位的二进制用来作为符号,实际上表示数的只有三位二进制 因此能表示的最大值是7,即模为7。 那么
(-1) mod 7= 6
从而可以得出
1-1=(1+6) mod 7=0
反码
由于二进制最高位为符号位,所以取模时不能当成数字计算,也就是前面提到的反码
0001(原)+1001(原)=0001(反)+1110(反)=1111(反)=1000(原)
1(原)+ (-1)(原)=1(反)+-6(反)=-7(反)=(-0)(原)
但在这里我有了疑惑取反后1001实际上变成了-6而不是真正意义上的6。在思考后得出了自己的理解:由于计算机实际上是没有相减的运算存在的,自然也没有符号的概念,所以实际上运算时并没有正负数概念,正负概念是额外给出的定义。因此可以理解为
0-7(0000-0111)为0-7 8-15(1000-1111)为-(0-7)
0001(反)+1110(反)=1111(反)
的过程可以认为是
1[1]+(-6)[14]=(-7)[15]
而反码则可以理解为
由于最高位是符号,不参与取模
1001=1000+(-001 mod 111)=1000+(111-001)
-1=(-0)+((-1)mod 7)=(-0)+(7-1)
而111-001在二进制中又可以直接通过对001取反得到
1000+001(取反)=1000+110=1110
(-0)[8]+6[6]=(-6)[14]
补码
计算机存储使用的是补码,而负数的补码是在反码基础上在+1,有什么作用呢?
由于定义的特殊性所以存在着两个0即0000和1000,分别为+0和-0,那么1+0和1-0会怎么样呢
0001(原)+0000(原)=0001(反)+0000(反)=0000=0001
0001(原)+1000(原)=0001(反)+1111(反)=10000=0000
可以看出虽然+0没有问题但是-0却出现了计算上的错误。
而补码的出现就是用来弥补存在两个0的特殊性问题
0001(原)+1000(原)=0001(反)+1111(反)=0001+10000=10001=0001
在补码的情况下-0的反码转化成了10000而4位二进制最高只能存储4位数值,所以10000就会变成0000就像钟表拨过12点一样又会重新开始。而0000又恰好是0000也就是+0的补码这样一来在存储和计算时-0与+0就相等了。那么1000—1111的补码就是10000—1001,这样可以看出补码中1000并没有使用到
(-1)+(-7)=1001(原)+1111(原)=1111(补)+1001(补)=11000(补)
(-1)+(-7)是-8,而二进制(-1)+(-7)的补码是11000存储4位就是1000,因此正好可以使用多出的(-0)[1000]的位置来表示(-8)[11000],由于存储时的有溢出位的特殊性因此-8是没有反码和原码的。这样一来不仅解决了(-0)的计算问题,同时原本的表达范围(-7)—7也变成了(-8)—7,比原本的表达范围最小值多了一个数值。
这也是为什么在程序语言中数值数据类型的范围定义负数总是比正数多一个数值的原因了。
由于课堂上老师提到了补码,出于好奇,而且觉得还是需要掌握的,所以才查阅的。理解纯属个人观点,如有理解错误还请指出。
参考文章https://www.cnblogs.com/zhangziqiu/archive/2011/03/30/ComputerCode.html
个人博客:https://www.rainc.top/2019/10/10/essay/twos-complement/