self-confidence,the source of all the power

导航

计算机存储-补码

1。补码的介绍(two's complement)

  在计算机系统中,数值一律用补码来表示(存储)。 这样做的最大好处就是可以将符号位和其它位统一处理;即减法也可按加法来处理。

2.补码的计算

  计算机在存储有符号数的时候,会分配一个符号位(最高位)给他,因此负数的表示方式为:符号位+数值位。假设为8位机,如

    -8       1      0001000  

               符号位   数值位

  补码的计算方式:1.正数的补码不变

          2.负数的符号位不变,数值位取反后加1

  如-8的补码

    1  111 0111 ——>1 111 1000

3. 为什么采用补码

  书上说这样用可以简化硬件的设计,加法与减法的计算方式一样,其实这样说是没错,可是这样说却不太好理解。为了说明问题,我打一个类比,6个人围成一堆并且给每人一个编号0,1,2,3,4,5.现在让他们依次报号,从0号开始,当1号第二次报号时,他会报1而不是7,那现在有个问题:1号后面第九个是几号?如果你挨个数的话会发现刚好是4号,如果让你用一个算式表示出来,你会怎么算?(1+9)%6 = 4,这是不是老生常谈的取模的问题了,当累计到最大数(5)的时候,会从该范围内最小的数(0)重新开始。

  依然是上一个例子,现在我换一个问题:当前位置是1号,那我怎么才能得到4号?有两种方法:1.向前报数,第3个人就是4号   2.向后报数,第3人就是4号。

  设向前报数为加法,向后报数为减法,那为了得到4号,我列出下面的数据关系。

  当前位置  向前+   向后-  目标位置    最大值  总数

     0    4       2       4     5   6

        1           3         3        4      5   6

    2           2         4        4      5   6  

    3           1         5        4      5   6

    4           0         6        4      5   6

    5          -1         7        4      5   6

  向前报号的个数与向后报号的个数之和始终为 6,即总人数。所以可以将数(0,6),(1,5),(2,4),...,(6,0)称为互补数组。

  由以上补数原理得出,当我们需要进行减法运算的时候,可以用加上它的补数来代替,即

    2+2 = 4, 2-4 = 2 + (4的补数)= 2+2 = 4

  明白了吧,计算机就是利用这样的原理来实现加减法运算的,它直接将减法运算简化成了加法运算。

  结论:假设数列1,2,3,4,...,n。如果存在n+1 = 1, 1-1 = n这样的关系,则(1,n),(2,n-1),...(n,1)分别是互补数对,其中任一对互补数之和为n+1。

  推论1:由于最小值1与最大值n为互补数,因此最小值与最大值之和等于任一互补数之和。

   现在再来看计算机中的数据二进制表示,一个字节内,最大值二进制 1111 1111 = 2**8-1=255,按我们上面分析看,数字总数为256,那互补的数就是

(1,255),(2,254),...(250,6),...(255,1). 再看其中一组互补数的二进制(1,255)

  255  +1 = ?    1111 1111 + 0000 0001 = 1 0000 0000 ——>出现了第9位,计算机自动去掉最高位1——>0000 0000 = 0.

  所以对下面代码的结果为0.如果按照上面的结论,255+1  = 255-255 = 0,结果仍然为0

  unsigned char  a=255;

  a + 1 = 0 

  那么计算机怎么进行减法运算的呢?255-1 = ?再看它的二进制运算

  255 - 1 = 255 + -1 = 1111 1111 + 1000 0001 = 1 1000 0000 = 1000 0000 = -0 = 0

  这样看起来不太对啊,我们期望的结果应该是254才对。其实在进行运算的时候数据都是以补码的形式出现的,上式没有将负数转化成补码,所以得到的结果就会出人意料了,那为什么在进行加法(即加上正数)的时候可以直接进行运算?那是因为正数的补码是其本身。现在再看看负数的补码运算

  255 - 1 = 255 + -1 = 1111 1111 + 1000 0001的补码 = 1111 1111 + 1 111 1110 + 1 = 1 1111 1110 = 1111 1110 = 254

 

4  负数的补码运算公式的来历

  说来历这个词有点夸大,应该说是自己的推理更恰当一些。

  比如说计算机中的char类型,它的取值范围-128~127,并且127(最大值)+1 = -128(最小值),所以互补数之和应该为127+ -128=-1,127+|-128| = 255.

  上式可知,对于字节char类型,127与-128是互补数,再看其二进制表示

  127     0111 1111

  -128    1000 0000   

       -1       1111 1111

   没时间了,推不下去了,有兴趣的同学可以接着推下去,实在不好意思。

 

 

posted on 2013-05-07 14:34  漩涡鸣人  阅读(726)  评论(0编辑  收藏  举报