zoukankan      html  css  js  c++  java
  • 计算机存储补码

    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

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

  • 相关阅读:
    Coding过程中遇到的一些bug
    Git GUI的使用
    CMD控制台下的JAVAC就是“不是内部或外部命令
    Android TextView 设置滚动条(纯xml)
    Referenced file contains errors (http://www.springframework.org/schema/aop/spring-aop-3.0.xsd). For more information, right click on the message in th
    Eclipse工具栏上android的机器人小图标不见了
    eclipse indigo 安装 Eclipse Marketplace Client
    eclipse导入android项目错误,项目名称上有红叉,但代码中无报错
    Git GUI 的使用
    Android GridView 行间距过大(一页一行)
  • 原文地址:https://www.cnblogs.com/lovemo1314/p/3064717.html
Copyright © 2011-2022 走看看