操作系统之原码、反码、补码、移码的杂谈

86570791 2019-06-28

序言

本文随便聊一下计算机表示数据的方式,也算是总结一下以便将来回顾。如有纰漏错误请高人指点、共同进步。

  • 计算机中的数值表示
    任何数据在计算机中都是以二进制机器码的形式存在的,举个例子现实生活中的+2在机器中表示为00000010(姑且假设这个计算机的字长定义为8位)。但这是+2对应的机器码,因为首位是用来表示数值的正负的:0为正1为负。所以如果想表示-2的话则是对应的机器码为10000010,所以看见一串机器码的时候首先考虑值的正负,10000010如果直接按权展开计算其真值是不对的,如果直接按权展开是1*2^7 + 1*2^1 = 130 显然不是2。因为首位是1,所以为负值,然后计算后面位按权展开结果为-2。
  • 原码
    像上段文中举例那样,用机器码表示出来的值称为原码,+2的原码就是00000010,-2的原码是10000010。
  • 反码
    反码一般情况下是计算机用处最少用到的表示方式,为什么稍微会谈到,先说下反码怎么表示:如果是正数的反码则是原码本身,没什么变化。如果是负数的反码,则是符号位也就是第一位上的数值不变,其余位取反。比如+2的原码 00000010,那么+2的反码也是00000010。-2的原码表示10000010,反码即为11111101。
  • 补码
    补码是计算机的数值运算中用到最多的一种编码方式,具体原因稍微会聊。先说下补码的表示方式,正数的补码就是原码本身,这点跟反码是一样的。负数的补码是其反码+1后的结果。比如+2的补码就是00000010。而-2的补码:11111101(反码)+1 = 11111110。
  • 移码
    移码是将数值加上一个偏置常数。当编码位数为n时,通常情况偏移2的n-1次方。比如-2的移码 = 原码+2的7次方 = 00000010 + 10000000 = 10000010,可以当做-2的补码11111110符号位不变其余位取反后+1
  • 为什么有补码和反码?
    模运算系统
    拿生活中的钟表计时方式来说,10点如果变成6点可以往回拨4,10-4=6。也可以顺时针拨8,10+8=18模12=6。可以看出来关于模12,-4和+8是相等的。8就是4关于模12的补码。这样的话可以把所有的减法计算转化成加法运算。
    如果是“4位的十进制”模系统运算中,9828-1928运算相当于9828 + (10^4-1928)= 9828+8072 = 17000,取10^4模 = 7000。所以计算机中运算减法的时候,是相当于加上 -1928的补码进行运算的。
    其实我们人脑直接用原码进行数值计算是最直观和最简单的,为什么计算机不能直接用数值的原码去进行计算,因为有一个很重要的运算因素存在----负数。我们知道原码的首位是代表符号位0代表正数1代表负数,但是计算机不知道。如果计算1+(-1)那么结果是00000001(+1原码)+10000001(-1原码) = 10000010(原码) = -2 很明显结果是不对的
    那么反码的诞生是否解决了这类的问题?来试试 。1+(-1)= 00000001(原) + 10000001(原) = 00000001(反)+11111110(反) = 11111111(反) = 10000000(原) = -0 注意这里的0是有符号位的是个负值。这与我们数学运算规则不符(虽然现实中0不分正负但是计算机中正确结果应该是+0)
    于是最后出现了补码的编码方式进行计算机运算,1+(-1)= 00000001(原) + 10000001(原) = 00000001(反)+11111110(反) = 00000001(补) + 11111111(补) = 00000000(补) = 0,结果正确。
  • 为什么有移码?

    移码主要是为了便于计算机运算指数而引进的,比我们运算一个加法1.1*2^-1 + 1.2*2^3,根据运算规则来讲底数2相同时,需要先把指数处理为相同时才能进行1.1和1.2的加法运算。0.00011*2^3 + 1.2*2^3这样运算就简单多了。所以为了进行运算就需要比较指数部分,指数-1和3进行比较是如果是原码编码的方式去处理,就会形成10000001和00000011进行比较的结果,显然这么一比是-1>3的,计算机无法进行准确运算。如果用移码的形式,比如让指数-1和3同时+4,就成了3和7的比较,很容易进行比较出来大小方便对齐最大幂进行运算。所以移码的思想就是这样由来的。

相关推荐