计算机符号位的权,补码:从符号位负权理解

我所查看的绝大多数关于补码原理的资料都是从钟表原理、模数运算之类的开始讲起,让我觉得很混淆。所以关于补码的理解我打算写一篇基于自己理解注记,从符号位负权开始理解。

约定:下文讲解的例子中,中括号[...]括起的数表示二进制数。二进制位数的数据位为4位,符号位为1位,合起来共5位。

数有正负之分,比如10的二进制数是[1010],而-7的二进制数是[-0111]。然而在机器中是没有存储正负符号本身的机制,为此,我们必须将正负符号映射为{0,1}才行,比如让0对应负数,让1对应正数,则-7是[0 0111],10是[1 1010];又或者是让0对应正数,让1对应负数,则-7是[1 0111],10是[0 1010]。

究竟选取哪一种比较好呢?理论上来说两种方法都可以,只要与计算机达成协议。然而随意指定映射方案会引发两个问题:

符号位上的0、1只是单纯指定正负号,没有权值,它们本身无法参与运算,

计算机在计算加减法时必须先要判断是正是负,并且要单独设计加法器和减法器,

如果只是这样,那么未免太无趣了。实际上,如果我们为符号位指定负权值,那么让1对应负号、0对应正号就有实际意义。为什么这么说呢?

75675f3bde8c

在上图中,符号位(也就是第5位)是负权值。从第4位到第1位的数据位最大也只是15([1111]->8+4+2+1=15),那么如果第5位为1,则整个权值为(-16+15=) -1,也就是最大值为-1,最小值为-16([1 0000]),从而达到标识负数的目的;同理,如果第五位为0,则最大值为15([0 1111]),而最小值是0([0 0000]),也就达到了表示正数的目的。

通过上面可以看出,如果为最高位也就是符号位赋负权值,则:

符号位本身可以标记正负性,并且可以参与运算,

计算机不必判断正负性,所有的加减法都可以转换为做加法,

基于这种考量,符号位为负权值的这种码参与运算是很方便的,我们称就称之为补码(当然为什么叫补码后面我尝试分析);另外,统一将1代表负数,0代表正数。

然而,赋负权值之后,这个二进制数表达出来与通常的二进制数不太一样,比如,-10的普通二进制数(也就是符号位不赋权值,称之为原码)是[-1010]也就是[1 1010],但是补码是[1 0110],显然二者不同。

这个补码是怎么算的呢?因为-10<0,则符号位为1,设数据位为x,则有-16+x=-10,得到x=6=[0110],综合就是[1 0110]。

显然,按照这种算法,正数(包括正零)的补码就是它们的原码本身,因为负权值对于0而言是不影响的,下面重点看一下负数的情况:

75675f3bde8c

从上图可以看到,如果将该数的绝对值(即x)与补码相加,就会有-16+(16-x)+x=24+1=[10 0000],这是因为(16-x)+x后得到16,也就是[1 0000],它会向补码的符号位进一位,这导致符号位也会向前进一位。然而实际上这里二进制数只有5位,所以第六位的1实际应该被丢弃,最终结果应该是[0 0000],在这里只是说明两者的关系。

综上可做如下描述:若令X=-x,则|X|=x,设数据位有n位,符号位1位,则

X补码+|X|=X补码+x=2n+1

从而

X补码=2n+1-|X|=2n+1-x

这便是负数的补码与原码的关系。到这里还未结束,上面式子只是描述一个算数关系,但是对于计算机而言,因为上式要做一次减法,所以不能立刻得到给定数的补码,这就需要引入反码机制来帮助构思。

下面通过一个例子来解说:

75675f3bde8c

这个例子中,不难看出-5的原码和反码若是认为都是无符号数(符号位认为是数据位,给正权),则相加得到[10 1111]也就是(-5原码:无符号数表示)+(-5反码:无符号数表示)=24+1+(24-1)。所以如果对-5的数据位取反(符号位保持不变),那么就会得到它的反码,也就是:(-5反码:无符号数表示)=24+1+(24-1)-(-5原码:无符号数表示)=24+1+(24-1)-(5+24)=24+1-1-5。此时如果给它两边再加一个1,就得到(-5原码:无符号数表示)+1=24+1-5,对比上面给出的x与之补码的关系,不难看出最后得到的结果是数位表示的就是补码。

所以一般而言,如果是正数则补码使其原码本身,如果是负数,那么补码就是其反码再加一。

当然分析到这里仍然未结束,还可以再次化简。计算机将原码转为补码依据如下结论:如果是正数则补码就是其原码,如果是负数,则从右往左数遇到第一个1开始,将符号位的右侧、该1的左侧的全部取反,即得到补码,比如-5=[1 0101],从右往左第一个1的左侧、符号位的右侧是三个数位010,从而对其全部取反就得到-5的补码:[1 1011]。

为什么可以这样做呢?注意到,从右往左遇到第一个1,说明这个1的右侧必定全部为0,假定符合[1 xx...xx 100...0]的形式,则其反码就是[1 x'x'...x'x' 011...1],则加1以后就得到补码[1 x'x'...x'x' 100...0],与原码作对比,发现只有中间部分的xx...xx全部取了反变为x'x'...x'x'。

这里注意有一个特殊情况,就是当为-0时,其原码为[1 0000],但是其补码则与+0相同,都为[0 0000]。补码的一个好处就是将正负零统一了起来。既然[1 0000]不再表示-0的补码,那么它就可以被用来表示-24=-16。即数据位为n位、符号位为1位的二进制数,最大值是2n-1,最小值是-2n。比如当是8位是,补码范围就是[-128,127]。

下面来说说补码的加减法为什么都能转为加法,这实际上就是要证明:

x补码+y补码=(x+y)补码  (mod 2n+1)

x补码+(-y)补码=(x-y)补码  (mod 2n+1)

即 操作数的补码和等于操作数和的补码、一个操作数的补码与另一个操作数求负后的补码的和等于两操作数和的补码。

这里的关键在于若已知 y补码 如何求得 (-y)补码。可以证明,y补码 + (-y)补码=0。即

将y补码包括符号位都求反(注意!!不是求反码!反码要求符号位不动,这里要包括符号位也要变化!!)然后加1即可得到(-y)补码。这是因为只有包括符号位在内都取反,y补码 + (-y)补码=[111...1111],只要再加一即可得到0满足关系式。

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值