我们在Yannick:Introduction to CSAPP(二)信息的表示与处理·概述中说到:
确定一个数值数据的值,必须确定:
- 进位计数制
它表示二进制数据,还是一个十进制数据? - 定点、浮点表示
这个数据是整数,还是小数,因为在计算机中无法表示小数点,只能约定某一位开始表示小数部分。整数和小数在字面看起来是极其类似的。 - 二进制编码形式
是正数还是负数?因为在计算机中无法表示正负号,只能约定某一位正负。
这篇文章讲的就是,第二点中的定点数表示。
结合本文内容,可以解释Introduction to CSAPP(二)信息的表示与处理·概述 - Yannick的文章 - 知乎中,引子提出来的两个问题。让我们来看看吧~
什么是定点数、浮点数?
定点数、浮点数是计算机中小数的表示方法。比如我们规定一个八位的二进制序列,第五位极其后的位表示小数部分。那么
这种表示方式就是定点数,它可以表示的数字范围是有限的。不确定小数点的数值表示法,叫浮点数。
编程语言中的整数
在计算机中,整数用小数点在最末位数后的定点数来表示。以C语言支持的基本数据类型为例:
但是这个整数的数值在C语言中并不绝对,在涉及到跨平台的问题时,不同的操作系统为基本的数据类型分配的大小时不一样的,这个涉及到操作系统选择的C数据模型。
下表 32 位和 64 位数据模型
加粗的为不同模型下表现一致的。
ILP32 => defineint, long, and pointer
as 32bits
LP64 => definelong and pointer
as 64bits
LLP64 => definelong long and pointer
as 64 bits
ILP64 => defineint, long and pointer
as 64 bits
在32位的操作系统下,大部分的操作系统都是采用的ILP32,因此,long是4个字节
在64位的操作系统下,Windows采用的是LLP64,long是4个字节,类Unix操作基本都是采用的LP64,因此,long是8个字节
Java中整数的数据类型如下表
对于Java来说,没有无符号数,具体的Java基本数据类型见这里。
整数的表示与类型转换
对于C语言来说,C语言标准没有指定有符号数在内存里要采取哪种表示方式,但是基本上所有的机器都采用补码表示。对于无符号数,无论用原码、补码还是反码,它都是一致的。
对于Java语言来说,整数数据类型的表示是补码,注意Java是没有符号概念的,reference。
在 C 语言中,如果不加关键字限制,默认的整型是有符号的。如果想要无符号数的话,需要在数字后面加 U
或者u
,例如下面的代码段
int a_signed_number = -15213;
unsigned int a_unsigned_number = 15213U;
- 具体每一个字节的内存表示值不会改变,改变的是计算机解释当前值的方式
- 如果一个表达式既包含有符号数也包含无符号数,那么会被隐式转换成无符号数进行比较
在进行有符号和无符号数的互相转换时:
我们在数轴上把有符号数和无符号数画出来的话,就能很清晰的看出相对的关系:
整数运算与溢出
- 无符号数加法
如果两个w
位的数字相加,结果是w+1
位的话,那么就会丢弃掉最高位,实际上是做了一个 mod 操作(公式为 ) - 有符号数加法
操作过程和无符号加法一样,只是解释的时候会有不同,因此会得到正溢出(positive overflow)和负溢出(negative overflow)两种。- 正溢出就是数值太大把原来为 0 的符号位修改成了 1,反而成了负数;
- 负溢出是数值太小,把原来为 1 的符号位修改成了 0,反而成了正数。
本文介绍了在计算机中,整数的表示方式。在计算机中,整数是以补码的方式表示而存储的,知道这一点,在使用 位运算时才能知道自己做了什么。
同时到了这里我们也就解释了Introduction to CSAPP(二)信息的表示与处理·概述 - Yannick的文章 - 知乎中,引子提出来的两个问题。具体解释可以见下篇文章。