美文网首页
计算机中二进制补码的运算原理

计算机中二进制补码的运算原理

作者: sml_tj | 来源:发表于2020-07-07 16:35 被阅读0次

    在计算机中负数以补码形式表示,计算负数补码的方法是符号位不变,其余位按位取反再加1。
    简言之,补码是计算机中用来表示负数,使得负数能够使用加法器参与加法运算的一种码。

    为了更好的理解补码的含义和作用,举以下两个例子
    例1:
    假如一个时钟现在显示的是10点钟,如何将它调到6点钟?
    解:有两种方法,一是向后拨8个小时,二是向前拨4个小时
    在这个例子中,8 和 4 互为补数,也就是说4的补码是8,8的补码是4,而这个时钟的模就是12

    注意:可能有人会想,在往后调8个小时虽然也调到了6点,但是他实际上比原来日期多了12小时。是的,的确如此,但是你的时钟有地方存储了这多余的12个小时吗?答案是没有,所以在你调完后,你没有记录这12个小时,换句话说,你把这溢出的12个小时自动舍弃了。当第二个人来查看闹钟时间的时候,他看到的时间就是准的。
    例2:
    一个数的数值是11,他的模是16,那么他的补码是多少?
    解:16-11 = 5,即补码就是5。

    模:
    模是补码的一个重要概念,简单来说模就是一个循环的周期,在例1中,时钟的一个周期就是12,所以模是12。一周的模是7天,一天的模是24小时。

    通过二进制求15-11的值
    要想让减法变加法,必须转换算式为 15 + (-11)
    15为正数,符号位为0,二进制表示为 01111
    -11为负数,符号位为1,负数原码为 11011 ,补码符号位不变,其余逐位求反再 +1,即 10101
    所以 15 + (-11) = 01111 + 10101 = 100100 舍弃第一位溢出位,即00100,即+4
    这是一个最简单的补码算法运算的例子,却有很多不解之处。
    为什么负数 (-11 )逐位求反再+1就可以代表原来的数?
    为什么第一位舍弃?
    为什么符号位能够参与运算?

    1. 为什么负数 (-11 )逐位求反再+1就可以代表原来的数?
      -11 先不考虑符号,观察11的二进制表示,11使用二进制表示是 1011,将1011 逐位求反 得到 0100,因为是逐位求反,1011 +0100 = 1111 ,而1111 + 1 = 10000,发现了什么?10000是四位2二进制数的模。为什么10000是4位二进制数的模呢?原理也很简单,4位寄存器最高能表示什么数?即 (二进制)1111 = (十进制) 15 , 15 +1(多一个零) =16 = (二进制)10000,后四位寄存器清0,所以模为16。
      所以不管几位二进制数,取反后得到的值加原码会刚好的到所有的位都是1的二进制数,再加一就刚好进位得到模。所以取反加一是无论如何都能取到补码的。比如 :(原)101 + (补)((反)010 +1) = 8 ,(原)10 + (补)((反)01 +1)= 4。
      所以,负数符号位不变,其余逐位求反 +1 只是算出补码最简单的方法,而不是理论基础。

    2. 为什么第一位舍弃?
      为什么高位舍弃,这个问题其实在例1中已经做了说明,因为你没有存储这个高位的空间,用最简单的解释来解释就是,一个4位的寄存器,只能存储数据的后四位,第一位进位没地方放,就像例1中多出来的12小时,没有地方存储,那么就丢弃了,反正结果正确就行。可能有人会问,你说丢弃就丢弃吗,丢了你怎么保证是正确的?
      现在考虑符号位,将符号位加入运算。
      15 - 11 = 15 + (-11),其中 -11 为 11011(加了一位符号位,所以模为 16 * 2=32) 他的补码为 10101 = 21
      所以 15 -11 变为 15 +21 = 36 (01111 + 10101) ,原先是减一个数,变换后却变成了一个比减数更大的加数了,能不溢出吗。所以要模掉溢出位 36 % 32 = 4 。仔细观察被模数36 = 1 00100 你会发现,在第二位之前的所有高位都是32的倍数,所以用32进行模运算就会全部清0,这就是为什么高位可以直接舍弃的原因,因为高位永远会是模的倍数,在模的过程中会被清0。

    3. 为什么符号位能够参与运算?

    首先放弃符号位就是计算机表示专门定义出来表示正数和负数用的这个思维,换成这样一种理解思路:我们观察计算机中一个二进制数,它没有专门的符号位,但是正数和负数在计算机中存储第一位二进制数会存在差异,如果它的第一位是0,那么他就是正数原码,如果它的第一位是1,那么他就是负数补码,我们通过观察第一位是0还是1即可知道这个数是正数还是负数。

    通过以下例子,可以发现符号位其实是算出来的。
    计算机运算 9 - 12
    解:9 转五位二进制为 01001 //模为32(100000)

    因为12是减数,所以将12转为补码变为加数,方便参与加法运算

    12 = 01100(原) = 10011 + 1 = 10100(补)

    01001 + 10100 = 11101

    11101% 100000= 11101

    从结果看,我们可以发现,第一位为1,第一位如果是1,那么这个数值是负数补码,由此可知,这个数是一个负数,只是在计算机中,他表示为11101,反求原码,即可得到 (11101 - 1) 反 = 00011 = 十进制数 3,由此可知,11101表示的是负数的3
    从这个例子当中可以看到,在运算中完全没有考虑符号位,仅用单纯的加法运算进行运算,而得到的结果11101也没有人为去添加一个符号位,符号位是计算所得的,所以他才能参与运算。我们应该反过来看符号位,正是在补码运算中,存在第一位为0则是正数,为1则是负数这个规律,我们才方便地认定第一位为符号位,符号位跟人为定义没有任何关系(人为定义的符号位不可能满足数学规则参与数学运算)。

    符号位是计算后得出来的,所以我们要预先要在寄存器第一位留出一个位置存放计算后得出的符号位,所以我们先在第一位前面补一个0占位。
    由此可知: 要想计算结果正确, 需要满足 : 寄存器位数 >= max(操作数1,操作数2,....) 的二进制位数加一位

    参考文章:https://blog.csdn.net/zhuozuozhi/java/article/details/80896838

    相关文章

      网友评论

          本文标题:计算机中二进制补码的运算原理

          本文链接:https://www.haomeiwen.com/subject/pmaaqktx.html