《电子技术应用》
您所在的位置:首页 > 嵌入式技术 > 解决方案 > 计算机系统原理(七) 整数的表示方式精解:无符号与补码编码

计算机系统原理(七) 整数的表示方式精解:无符号与补码编码

2017-06-22
关键词: 汇编语言

上一章我们简单的介绍了布尔代数以及C语言的位运算,本次我们主要来看,二进制如何表示整数,这是很重要的一章,希望各位猿友莫要错过。

C语言中的整数类型及范围

我们依然以C语言为例,C语言当中提供了多种整数类型,一共十种,位数为1、2、4、8,其中32位机器上,4位的有两种,在64位机器上,8位的有两种。不过C语言有它的最小数值范围,也就是说C语言要求这些数据类型至少要满足一个标准的范围。下图是C语言对整数类型要求的最小表示范围。

仔细看的话,可以发现,C语言只要求有符号数的范围是对称的,另外就是int和long类型的位数要求都比较低,分别是2位和4位。

可以看到以上的表中,每一种整数类型都可以加unsigned关键字,来表示一个无符号数,即没有正负之分。在书中,给出了无符号数的定义,LZ将它简化一下,对于一个w位的二进制来说,它的无符号表示为以下形式。

对于一个无符号编码来说,它的最大值和最小值很好确定,对于一个w位的二进制序列来说,当所有位都为0时,则为最小值,即

                               UMinw = 0

而当所有位都为1时,则为最大值,根据等比数列的求和公式,即

                               UMaxw = 1 * (1-2w) / 1 - 2 = 2w - 1

如果把上述的定义看成是一个函数的话,那么这个函数就是一个双射。也就是说,对于任意整数x,当0 =< x < 2w的时候,存在唯一的二进制序列与其对应。反过来也是一样的,对于任意一个w位的二进制序列,都存在唯一一个整数x满足0 =< x < 2w,与这个二进制序列对应。

无符号编码属于相对较简单的格式,因为它符合我们的惯性思维,上述定义其实就是对二进制转化为十进制的公式而已,只不过在一向严格的数学领域来说,是要给予明确的含义的。

补码编码

无符号编码符合人的惯性思维是没错,但是可惜的是,它无法表示负整数。因此我们需要一种能够表示负数的整数表示方式,这就是补码编码。与无符号编码一样,书中依然给出了补码编码的定义,即对于任意一个w位的二进制来说,它的补码表示为以下形式。

这里最高位xw-1为符号位,当它为1时,该公式得到的值为负数,当为0时,得到的则为正数。

我们观察这个公式,不难看出,补码格式下,对于一个w位的二进制序列来说,当最高位为1,其余位全为0时,得到的就是补码格式的最小值,即

                            TMinw = -2w-1

而当最高位为0,其余位全为1时,得到的就是补码格式的最大值,根据等比数列的求和公式,即

                            TMaxw = 1 * (1 - 2w-1) / 1 - 2 = 2w-1-1

与无符号编码一样,如果把上述的定义看成是一个函数的话,那么这个函数同样是一个双射。也就是说,对于任意整数x,当-2w-1 =< x < 2w-1的时候,存在唯一的二进制序列与其对应。反过来,对于任意一个w位的二进制序列,都存在唯一一个整数x满足-2w-1 =< x < 2w-1,与这个二进制序列对应。

相对于无符号编码来说,补码编码与我们的惯性思维有些不同,因此直观的理解起来会有些别扭,不过作为一个程序猿,我们应该有一颗半机器的脑子,尽量去适应机器的习惯。

两种编码的转换

在C语言当中,我们经常会使用强制类型转换,而在之前的章节中,LZ也提到过强制类型转换。强制类型转换不会改变二进制序列,但是会改变数据类型的大小以及解释方式,那么考虑相同整数类型的无符号编码和补码编码,数据类型的大小是没有任何变化的,变化的就是它们的解释方式。比如1000这个二进制序列,如果用无符号编码解释的话就是表示8,而若采用补码编码解释的话,则是表示-8。

考虑到上面我们已经说过,无论是无符号编码还是补码编码,其映射方式都是双射,因此它们都一定存在逆映射。如果我们定义U2Bw(x)为B2Uw(x)的逆映射,则对于任意一个整数x,如果0 =< x < 2w,经过U2Bw(x)的计算之后,将得到唯一一个二进制序列。同样的,如果我们定义T2Bw(x)为B2Tw(x)的逆映射,则对于任意一个整数x,如果-2w-1 =< x < 2w-1,经过T2Bw(x)的计算之后,也将得到唯一一个二进制序列。

可以很明显的看出,对于0到2w-1-1这个区间内的整数来说,两种编码得到的二进制序列是一样的。为了得到其它区间里的整数的映射关系,我们定义

                     T2Uw(x) = B2Uw(T2Bw(x))

这个函数代表的含义是补码编码转换为无符号编码的时候,先将补码编码转换为二进制序列,再将二进制序列转换为无符号编码,最终也就是补码编码转为无符号编码的计算。

下面我们简单的推算一下上面的定义,究竟是如何转换的,也就是无符号编码与补码编码的关系。我们将上面无符号编码和补码编码的公式相减,

即                              B2Uw(x) - B2Tw(x) = xw-12w-1 - (-xw-12w-1) = xw-12w

即                                           B2Uw(x) = xw-12w + B2Tw(x)

此处我们令x为T2Bw(x),则          B2Uw(T2Bw(x)) = xw-12w + B2Tw(T2Bw(x)) = xw-12w + x

即                                            T2Uw(x) = xw-12w + x

此时考虑xw-1的情况,当xw-1为1时,也就是补码编码表示负数的时候,T2Uw(x)则为2w + x 。(LZ小提示:此时x为负数,也就是说2w + x < 2w)

若xw-1为0时,则补码编码为正数,此时T2Uw(x) = x 。

综上可知,有下列式子成立

从这个式子中可以很明显的看出,最终得到的无符号数范围为0 =< x < 2w。

相反,我们用同样的方式也可以证明从无符号编码到补码编码的公式,这一部分书中省略了,LZ这里还是写上来,以免有的猿友不知所云。我们依然将无符号编码和补码编码的公式相减

即                              B2Uw(u) - B2Tw(u) = uw-12w-1 - (-uw-12w-1) = uw-12w

即                                           B2Tw(u) = B2Uw(u) - uw-12w

此时我们令u为U2Bw(u),则    B2Tw(U2Bw(u)) = B2Uw(U2Bw(u)) - uw-12w = u - uw-12w

即                                           U2Tw(u) = u - uw-12w

此时考虑uw-1的情况,当uw-1为0时,也就是无符号编码数值小于2w-1的时候,U2Tw(u)则为u 。

若uw-1为1时,也就是无符号编码数值大于或等于2w-1的时候,此时U2Tw(u)= u - 2w。(LZ小提示:此时U2Tw(u)为负数,因为 u < 2w)

综上,我们可以得到无符号编码转换为补码编码的公式

同样的,在0至2w-1-1之间,两者依然是相等的,而其余区间则不同。


本站内容除特别声明的原创文章之外,转载内容只为传递更多信息,并不代表本网站赞同其观点。转载的所有的文章、图片、音/视频文件等资料的版权归版权所有权人所有。本站采用的非本站原创文章及图片等内容无法一一联系确认版权者。如涉及作品内容、版权和其它问题,请及时通过电子邮件或电话通知我们,以便迅速采取适当措施,避免给双方造成不必要的经济损失。联系电话:010-82306118;邮箱:aet@chinaaet.com。