⼆进制补码计算原理详解
⼆进制的负数在计算机中采⽤补码的⽅式表⽰。很多⼈很好奇为什么使⽤补码,直接使⽤原码表⽰多好,看上去更加直观和易于计算。然⽽事实告诉我们,这种直观只是我们⼈类的⼀厢情愿罢了,在计算机看来,补码才是它们最想要的。那么,为什么计算机使⽤补码更好,⼜是如何通过补码来计算数值的呢?
我看过⽹络上很多解释补码的⽂章,⼏乎⼀致的回答就是符号位不变,其他各位逐位求反再加⼀。在此我想说,这些都不是根本原理。谁都知道这么求,数电第⼀章就明确写了怎么求,关键是为什么这么算,其中的原理是什么?
本⽂主要的内容就是深⼊讲解补码的原理,其中内容有相互引⽤成分及计算机基础要求,不适合初学者阅读。当然,随便看看⽆所谓啦。
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。
2.模
关于模没有到固定的定义,简单来说模就是⼀个循环的周期,在例1中,时钟的⼀个周期就是12,所以模是12。⼀周的模是7天,⼀天的模是24⼩时。模是补码的⼀个重要概念。
3.使⽤补码运算
例3
模为32,使⽤补码运算该算式16-13,13 - 16。
解 16-13 = (16 + (32-13))% 32 = 35 % 32 = 3
13-16 = (13 + (32-16))% 32 = 29 % 32 = 29
4.使⽤补码进⾏⼆进制运算
有看过数电基础的都应该记得,第⼀章就有说明⼆进制补码是如何运算的。正数的补码即为⾃⼰,负数的补码为符号位不变,其余逐位求反再加1。
使⽤该定义,先通过例⼦求出数值,再对例⼦进⾏详细讲解,为什么可以使⽤负数的补码来运算。
例4  通过⼆进制求15-11的值
要想让减法变加法,必须转换算式为 15 + (-11)
15为正数,符号位为0,⼆进制表⽰为 01111
-11为负数,符号位为1,负数原码为  11011 ,补码符号位不变,其余逐位求反再 +1,即 10101
所以 15 + (-11) = 01111 + 10101 = 100100 舍弃第⼀位溢出位,即00100,即+4
这是⼀个最简单的补码算法运算的例⼦,却有很多不解之处。
1.为什么负数 (-11 )逐位求反再+1就可以代表原来的数?
2.为什么第⼀位舍弃
3.为什么符号位能够参与运算
先看问题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⼩时,没有地⽅存储,那么就丢弃了,反正结果正确就⾏。可能有⼈会问,你说丢弃就丢弃吗,丢了你怎么保证是正确的?
重新再看⼀次例4,现在考虑符号位,将符号位加⼊运算。
15 - 11 = 15 + (-11),其中 -11 为 11011(加了⼀位符号位,所以模为 16 * 2^1) 他的补码为 10101 = 21
所以 15 -11 变为 15 +21 = 36 (01111 + 10101) ,原先是减⼀个数,变换后却变成了⼀个⽐减数更⼤的加数了,能不溢出吗。所以要模掉溢出位 36 % 32 = 4 。仔细观察被模数36 = 1 00100 你会发现,在第⼆位之前的所有⾼位都是32的倍数,所以⽤32进⾏模运算就会全部清0,这就是为什么⾼位可以直接舍弃的原因,因为⾼位永远会是模的倍数,在模的过程中会被清0。
最后看问题3,为什么符号位能够参与运算,可能在这前⾯⼀直被符号位困扰,为什么参与运算就没有问题,看了这⾥的解释,我相信你将不会再被困扰。
符号位对于我对⼆进制补码的理解产⽣了很⼤的阻碍,我不明⽩为什么符号位可以参与运算,⽽且算出来还是对的。花了不少时间理解了符号位的含义。
⾸先放弃符号位就是计算机表⽰专门定义出来表⽰正数和负数⽤的这个思维,换成这样⼀种理解思路:我们观察计算机中⼀个⼆进制数,它没有专门的符号位,但是正数和负数在计算机中存储第⼀位⼆进制数会存在差异,如果它的第⼀位是0,那么他就是正数原码,如果它的第⼀位是1,那么他就是负数补码,我们通过观察第⼀位是0还是1即可知道这个数是正数还是负数。
通过以下例⼦,可以发现符号位其实是算出来的。
例5:计算机运算 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则是负数这个规律,我们才⽅便地认定第⼀位为符号位,符号位跟⼈为定义没有任何关系(⼈为定义的符号位不可能满⾜数学规则参与数学运算)。
补充:在例5中可以发现,我们在第⼀位之前补了⼀个0,将四位⼆进制数补成五位⼆进制数来计算,为什么要补这个0呢?为了说明这个问题,我们来算⼀个错误的运算
例6:计算机运算 0 - 12
解 : 我们仅仅⽤四位⼆进制数(四位寄存器)来算
12 = (⼆进制)1100 12转为⼆进制后是⼀个四位⼆进制数,它的模为10000
因为12是减数,所以将12转为补码变为加数,⽅便参与加法运算
12 = 1100(原) = 0011 + 1 = 0100(补)
0000 + 0100 = 0100 = 4 ,第⼀位是0,说明是正数原码, 即运算结果为 +4
4 != -12 运算出错
通过结果发现,只⽤四位⼆进制数运算,结果是错误的,为什么会产⽣这种错误呢?因为寄存器位数不够,四位寄存器只能存储 0 -15 的数值,没有多余的寄存器位置⽤来表⽰这个数的正负,我们虽然算出了符号位,但是计算后所得到的符号位却没有地⽅存放,导致符号位缺失,我们⼜误将四位⼆进制数结果的第⼀位当做符号位来判断数的正负,才会出现错误的结果。
通过例5我们可以知道,符号位是计算后得出来的,所以我们要预先要在寄存器第⼀位留出⼀个位置存放计算后得出的符号位,所以我们先在第⼀位前⾯补⼀个0占位。
由此可知: 要想计算结果正确, 需要满⾜ : 寄存器位数 >= max(操作数1,操作数2,....) 的⼆进制位数加⼀位
最后,附上⼀张五位⼆进制数运算转换关系图,⾃⼰体会⼆进制数如何带着所谓的符号位在计算机中运算:
有如下⼏点:
1:五位⼆进制数的所有正数都在圆环的⿊线上,⽽负数都在圆环的红线上,如果在⿊线上,那么六位寄存器第⼀位必为0,⽽在红线上,那么第⼀位必为1,我们也是通过这个位来判断数值的正负
2:五位⼆进制数运算结果取模后如果在⿊线上,那么为正数,否则为负数
负数二进制补码运算法则
3:尝试写⼏个数字转为五位⼆进制数或者写⼏个算式对号⼊座,观察是否符合,加深理解
到这⾥补码的原理就差不多讲清楚了,⽆⾮是使⽤模进⾏转化,但是我们站在⼗进制的⾓度,去看⼆进制的东西,的确会显得相当费解。最后我想说,能发明补码来计算的数学家真的是太厉害了。
内容有相互嵌套成分,阅读后回顾前⾯的内容可能会更加深⼊理解。
还有很多特殊情况没有考虑,只讲解了最核⼼的内容。
本⽂纯属个⼈理解,如有纰漏,请勿拍砖。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。