现在的位置: 首页 > 综合 > 正文

原码、反码、补码及使用补码的原因

2013年10月16日 ⁄ 综合 ⁄ 共 2655字 ⁄ 字号 评论关闭

大家都知道数据在计算机中都是按字节来储存了,1个字节等于8位(1Byte=8bit),而计算机只能识别0和1这两个数,所以根据排列,1个字节能代表256种不同的信息,即28(0和1两种可能,8位排列),比如定义一个字节大小的无符号整数(unsigned char),那么它能表示的是0~255(0~28-1)这些数,一共是256个数。一个字节的无符号整数,我们来进一步剖析它,0是这些数中最小的一个,我们先假设它在计算机内部就用8位二进制表示为00000000(从理论上来说也可以表示成其他不同的二进制码,只要这256个数每个数对应的二进制码都不相同就可以了),再假设1表示为00000001,2表示为00000010,3表示为00000011,依次类推,那么最大的那个数255在8位二进制中就表示为最大的数11111111,然后,我们把这些二进制码换算成十进制看看,会发现刚好和我们假设的数是相同的,而事实上,在计算机中,无符号的整数就是按这个原理来储存的,所以告诉你一个无符号的整数的二进制码,你就可以知道这个数是多少,而且知道在计算机中,这个数本身就是以这个二进制码来储存的。比如我给你一个2个字节大小的二进制码,首先声明它表示的是无符号的整数:00000000
00000010,我们把前面的0省略,换算一下,它表示的也是数值2,和前面不同的是,它占了2个字节的内存。不同的类型占的内存空间不同,如在我的电脑中char是1个字节,int是4个字节,long是8个字节(你的可能不同,这取决于不同的计算机设置),它们的不同之处仅仅是内存大的能表示的不同的信息多些,也就是能表示的数范围更大些(unsigned int能表示的范围是0~28*4-1),至于怎么算,其实都是一样的,直接把二进制与十进制相互转换,二进制就是它在计算机中的样子,十进制就是我们所表示的数。这是无符号数的表示,那么有符号的整数怎么办啊?

  有有符号的整数才有原码、反码和补码的!其他的类型一概没有。虽然我们也可以用二进制中最小的数去对应最小的负数,最大的也相对应,但是那样不科学,下面来说说科学的方法。还是说一个字节的整数,不过这次是有符号的啦,1个字节它不管怎么样还是只能表示256个数,因为有符号所以我们就把它表示成范围:-128-127。它在计算机中是怎么储存的呢?可以这样理解,用最高位表示符号位,如果是0表示正数,如果是1表示负数,剩下的7位用来储存数的绝对值的话,能表示27个数的绝对值,再考虑正负两种情况,27*2还是256个数。首先定义0在计算机中储存为00000000,对于正数我们依然可以像无符号数那样换算,从00000001到01111111依次表示1到127。那么这些数对应的二进制码就是这些数的原码。到这里很多人就会想,那负数是不是从10000001到11111111依次表示-1到-127,那你发现没有,如果这样的话那么一共就只有255个数了,因为10000000的情况没有考虑在内。实际上,10000000在计算机中表示最小的负整数,就是这里的-128,而且实际上并不是从10000001到11111111依次表示-1到-127,而是刚好相反的,从10000001到11111111依次表示-127到-1。负整数在计算机中是以补码形式储存的,补码是怎么样表示的呢,这里还要引入另一个概念——反码,所谓反码就是把负数的原码除符号位(负数的原码除符号位和它的绝对值所对应的原码相同,简单的说就是绝对值相同的数原码相同)各个位按位取反,是1就换成0,是0就换成1,如-1的原码是0000001(注意这里只有7位,不看符号位,我这里所说的负数符号位都是1),和1的原码相同,那么-1的反码就是1111110(这也是7位,后面加上了符号位都是8位了),而补码就是在反码的基础上加1,即-1的补码是11111110+1=11111111,因此我们可以算出-1在计算机中是按11111111储存的。总结一下,计算机储存有符号的整数时,是用该整数的补码进行储存的,0的原码、补码都是0,正数的原码、补码可以特殊理解为相同,负数的补码是它的反码加1。

那么,为什么计算机中为什么要用补码表示和存储呢?

引入补码是为了将减法运算转变为加法运算。基本原理以闹钟为例。例如:现在是10点,则得到6点的方法有两种。一是指针向回拨4点,即6=10-4;另一种方法是指针向前拨8点,即10+8=12+6,当加到12时,由于闹钟的最大点数是12,所以再向下记数则又从1开始了,这就相当于将12舍掉,最终得到的还是6。由此可见,在最大数一定的条件下,-4与+8的效果是一样的。

基于以上原理,可以考虑用一部分正整数来表示负整数。以8位二进制为例。8位二进制可以表示2^8个无符号整数,值域是0~255。表示有符号数时,用0~127表示正整数,用128~255表示负整数。表示负数遵守以下规则:

设x<0,[x]表示x的补码,则[x]=2^8+x
例如:[-1]=256+(-1)=255,[-128]=256+(-128)=128,[-20]=256+(-20)=236
补码的定义:设字长为n,则它所能表示的整数的个数是N=2^n,补码的表示形式:
(1)当0<=x<=N/2-1,[x]=x;
(2)当-N/2<=x<0, [x]=N+x。
解决了正数和负数的表示问题,还需要证明在加减运算时,这种表示方法的正确性(注:乘除运算可以转换为加减运算)。证明下面运算法则:[x]+[y]=[x+y]
证明:设x和y是两个整数
1、当x>0,y>0时,[x]=x,[y]=y,则[x]+[y]=x+y=[x+y]
2、当x<0,y<0时,[x]=2^8+x,[y]=2^8+y,则
[x]+[y]=(2^8+x)+(2^8+y)
=2^8+(x+y)mod(2^8)
=2^8+(x+y)
=[x+y]
3、当x>0,y<0时,[x]=x,[y]=2^8+y,则
若|x|>|y|,则x+y>0,[x]+[y]=x+2^8+y=2^8+(x+y)=x+y=[x+y](2^8被舍弃)
若|x|<|y|,则x+y<0,[x]+[y]=x+2^8+y=2^8+(x+y)=[x+y]
4、当x>0,y<0时,与第三种情况类似。
同样可以证明另两个运算法则:[x]-[y]=[x-y],[x]-[y]=[x]+[-y]。

这样就把计算机中的减、乘、除运算转化成加法运算,简化了计算机的硬件设计。

抱歉!评论已关闭.