本文转载地址:http://www.cnblogs.com/zuoxiaolong/p/computer7.html

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

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

我们依然以C语言为例,C语言当中提供了多种整数类型,一共十种,位数为1、2、4、8,其中32位机器上,4位的有两种,在64位机器上,8位的有两种。具体的LZ这里就不多做介绍了。以下是32位和64位系统上,这十种整数的范围。

上述是C语言中各个整数类型的表示范围,不过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

下图为表示补码编码与无符号编码的对应关系,可以看出在0至2w-1-1之间,两者是相等的,而其余区间则不同。

相反,我们用同样的方式也可以证明从无符号编码到补码编码的公式,这一部分书中省略了,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之间,两者依然是相等的,而其余区间则不同。

小例子

以上则是我们讨论的有符号编码与补码编码的内容,下面为了让大家更好的理解上面的公式的含义,LZ带大家写一个小程序,我们来直观的在两者之间做一下强制转换,看下得到的值是否满足我们上面的结论。

为了简单起见,我们取w为8,也就是我们只采用char类型作为例子,否则位数太高的话,算起来比较麻烦。LZ本次采用32位WIN7系统下,VS2010作为例子的编译环境。

#include <stdio.h>int main(){char t = 0xFF;unsigned char u = 0xFF;printf("t=%d u=%u\n",t,u);printf("t2u=%u u2t=%d\n",(unsigned char)t,(char)u);
}

我们给了两个同样的二进制序列0xFF,都是8个1,我们分别用补码编码和无符号编码去解释它们,并在后面使用强制转换在补码编码和无符号编码之间互相转换,得到以下结果。

t=-1 u=255
t2u=255 u2t=-1

这里LZ就不再写计算的过程了,这个计算并不难。各位猿友可以自己套用上面的(2.6)和(2.8)公式去计算,看看是否符合公式的规定。

本章小结

本章主要介绍了二进制表示整数时采用的无符号编码以及补码编码,也算是至今为止最难的一章了,因为搀和到了证明,尽管这是很简单的证明。

版权声明


作者:zuoxiaolong(左潇龙)

出处:博客园左潇龙的技术博客--http://www.cnblogs.com/zuoxiaolong

您的支持是对博主最大的鼓励,感谢您的认真阅读。

本文版权归作者所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

转载于:https://www.cnblogs.com/hthuang/articles/4629234.html

深入理解计算机系统(2.3)---整数的表示方式精解无符号与补码编码(重要)...相关推荐

  1. 深入理解计算机系统(2.4)------整数的表示(无符号编码和补码编码)

    上一篇博客我们主要介绍了布尔代数和C语言当中的几个运算符.那么这一篇博客我们主要介绍在计算机中整数是如何表示的,诸如我们在编码过程中遇到的对数据类型进行强制转换可能会得到意想不到的结果在这篇博客里你会 ...

  2. c语言无符号扩展,深入理解计算机系统(2.4)---C语言的有符号与无符号、二进制整数的扩展与截断...

    开篇请各位猿友允许LZ啰嗦几句,最近一直在写计算机系统原理这系列文章,也已经下定决心要把这本书的内容写完.主要目的其实是为了巩固LZ的理解,另外也想把这些内容分享给猿友们,毕竟LZ觉得这些内容对程序猿 ...

  3. 深入理解计算机系统(2.6)------整数的运算

    前面两篇博客我们详细讲解了计算机中整数的表示,包括有符号和无符号(补码编码)的详细介绍.那么这篇博客我们将对它们的运算有个详细的了解. 在讲解之前首先看下面的一个程序,看看输出结果是啥? 1 2 3 ...

  4. 笔记-深入理解计算机系统

    文章目录 计算机系统漫游 信息的表示和处理 信息存储 数字革命的基础--二值信号 信息存储 十六进制表示法的妙用 字数据大小 寻址和字节顺序 表示字符串 布尔代数简介 C语言逻辑运算和移位运算 整数表 ...

  5. 深入理解计算机系统(2.8)---浮点数的舍入,Java中的舍入例子以及浮点数运算(重要)

    https://www.cnblogs.com/zuoxiaolong/p/computer12.html 前言 上一章我们简单介绍了IEEE浮点标准,本次我们主要讲解一下浮点运算舍入的问题,以及简单 ...

  6. 深入理解计算机系统(2.4)---C语言的有符号与无符号、二进制整数的扩展与截断...

    开篇请各位猿友允许LZ啰嗦几句,最近一直在写计算机系统原理这系列文章,也已经下定决心要把这本书的内容写完.主要目的其实是为了巩固LZ的理解,另外也想把这些内容分享给猿友们,毕竟LZ觉得这些内容对程序猿 ...

  7. 2020-11-16(深入理解计算机系统2.4节选)

    最近迷上了深入理解计算机系统这本书,看了有无符号数转换,卡了一个点,然后水了一下博客,发现这篇挺好的博客,讲解挺详细,希望有兴趣的能多花时间阅读,本篇博客主要讲解了有符号数和无符号数之间的转换: 1. ...

  8. 深入理解计算机系统(2.7)------浮点数舍入以及运算

    上一篇博客我们讲解了二进制小数如何表示以及IEEE浮点标准.而且我们也提到过因为这种表示方法限制了浮点数的范围和精度,浮点数只能近似的表示一个数. 比如 数字1/5,我们能用十进制小数 0.2 准确的 ...

  9. 深入理解计算机系统_第二章_信息的表示和处理

    深入,并且广泛-沉默犀牛 文章目录 文章导读 信息的表示和处理 信息存储 十六进制表示法 字数据大小 寻址和字节顺序 表示字符串 表示代码 布尔代数简介 C语言中的位级运算 C语言中的逻辑运算 C语言 ...

最新文章

  1. 浅谈微服务的来龙去脉
  2. 矩阵的乘法通用模板(C++/Java)
  3. 过滤请求绝技 — 布隆过滤器与布谷鸟过滤器
  4. Java并发包常见异常_Java并发包1--线程的状态及常用方法
  5. 小米11全系机型补齐,超大杯压场,但Pro版也不容忽视
  6. 【git】Git 提示fatal: remote origin already exists 错误解决办法
  7. CentOS 7安装配置Samba
  8. Java定时任务工具详解之Timer篇
  9. php文件代码格式化,php代码格式化工具(phpCodeBeautifier)
  10. 电子电路之电阻篇01——贴片电阻01.常用阻值及标注
  11. 联想Y450 gt130m显卡驱动安装
  12. 电影票业务-字节青训营
  13. OSI体系结构——数据链路层详解
  14. Spring Boot 无侵入式 实现API接口统一JSON格式返回
  15. iPhone X测试烧屏软件,iPhone X烧屏测试,亮屏3天后才会发生
  16. Linux系统性能监控与调优
  17. c语言编程题素数和,程序设计入门——C语言 第4周编程练习 1 素数和(5分)
  18. 2023年 PCB产业危机,全面价格战恐将开启
  19. Conncetion
  20. 智慧工地指挥室大屏显示系统应该如何建设?

热门文章

  1. [AT2567] [arc074_c] RGB Sequence
  2. AJAX:校验用户名是否被注册
  3. 我的Java设计模式-原型模式
  4. 【转】蓝牙技术及其系统原理
  5. MFC-使用自定义控件的方法
  6. qt-项目部署(某些情况下编译器中运行异常的话可以使用命令windeployqt 程序名在安装的qt dos命令下补全部分依赖库在运行项目或发布)
  7. et操作 python wps_拿起来就用的office二次开发(python,win32com使用经历总结)
  8. cmd背景换成老婆(冰冰)
  9. lis25ba_LIS25BA - MEMS数字输出运动传感器:低噪声,高带宽,3轴加速度计,带TDM接口 - STMicroelectronics...
  10. Qt的QStyle类的标准图标汇总