【深入理解计算机系统 第三版 导读】第二章 信息的表示和处理
第二章 信息的表示和处理
本章节为《深入理解计算机系统》第三版的个人导读,参考B站up主-九曲阑干
2.1. 信息存储
1字=1字节(1 word=2 byte),1字节=8位(1 byte=8 bit),字节是机器最小可寻址的内存单位,不是内存中单独的位。
2.1.1. 十六进制表示法
一个字节由8位组成。在二进制表示法中,它的值域为00000000~11111111,如果看成十进制整数,它的值域就是0~255,如果用十六进制书写的话,它的值域就是00~FF。其中A~F大小写都没有问题。在二进制转化为十六进制上,首先将二进制分为4位一组,如果不够四位的话补零,例如:0011.1011 1000,转化的结果就是3.B8。转化回去就是一个逆过程。十进制转化为十六进制可以采用先转化为二进制或者除以16取余操作。
2.1.2. 字数据大小
大多数64位机器可以运行32位机器编译的程序,这是一种向后兼容。编译指令为:linux> gcc -m32 prog.c或gcc -m64 prog.c
2.1.3. 寻址和字节顺序
这一节是大端法和小端法。假设变量x的类型为int,位于地址0x100处它的十六进制为0x01234567。地址范围为0x100~0x103的字节顺序依赖于机器类型:
大小端 | … | 0x100 | 0x101 | 0x102 | 0x103 | … |
---|---|---|---|---|---|---|
大端法 | … | 01 | 23 | 45 | 67 | … |
小端法 | … | 67 | 45 | 23 | 01 | … |
2.1.4. 表示字符串
C语言中字符串被编码为一个以null(其值为0)字符结尾的字符数组。
2.1.5. 表示代码
没啥要说的
2.1.6. 布尔代数简介
布尔代数只有两种形态:对与否(1,0)。
- 非:1变0,0变1,命题逻辑用¬表示,布尔运算用~
- 与:只有p和q都为1时候,p&q=1,命题逻辑用∧表示,布尔运算用&
- 或:只有p和q都为0时候,p|q=0,命题逻辑用V表示,布尔运算用|
- 异或:p和q不同为真,相同为假,命题逻辑用⊕表示,布尔运算用^
2.1.7. C语言中的位级运算
C语言中位级运算例子:
2.1.8. C语言中的逻辑运算
C语言提供了一组逻辑运算符||、&&、!,功能和位级运算不要弄混
2.1.9. C语言中的移位运算
这个看看例子就行了
2.2. 整数表示
2.2.1. 无符号位向量到整数映射:
2.2.2. 有符号位向量到整数映射:
对于有符号数,最高位是符号位,例如上面的0101最高位是0,是正数;1011最高位为1,是负数。
2.2.3. 有符号数与无符号数的转化:
2.2.4. 无符号数转化位更大数据类型
2.2.5. 有符号数转化为更大数据类型
若一个运算为有符号数和无符号数的运算,那么C语言会隐式的将有符号数强制转化为无符号数来执行运算,例如:
int a = -1;
unsigned int b = 0;
if (a < b)
printf("-1 < 0");
else
printf("-1 > 0");
对于无符号数来说,直接补零就可以了,但是对于有符号数来说,如下:
符号位扩展保持数值不变的证明,大体思路就是假如能够证明符号位扩展一位,可以保持数值不变就可以了:
2.2.6. 截断无符号数
将一个w为的无符号数,截断成k位时,丢弃最高的w-k位,截断操作可以对应于取模运算,对于二进制取模,通俗来讲就是除以2的k次方之后得到的余数
2.2.7. 截断有符号数
有符号数截断之后成了无符号数,然后将无符号数转化为有符号数
2.3. 整数的运算
2.3.1. 无符号数加法溢出
下图展示是如何溢出的:
2.3.2. 有符号数加法溢出
有符号的溢出分为正溢出和负溢出
下面是检测有符号数相加是否发生溢出:
2.3.3. 减法
对于减法,书本中提到了一个概念叫做加法逆元,通俗点就是相反数,即x+x’=x’+x=0;
- 无符号数:溢出来获取相反数
- 有符号数:
2.3.4. 无符号数乘法
在C语言中的无符号乘法被定义为产生w位的值,就是2w位的整数乘积的低w位表示的值:
乘法可以通过移位操作
2.3.5. 补码乘法
2.3.6. 有符号和无符号除2的幂
对于无符号数采用的是逻辑右移,对于有符号数采用的是算术右移。。
2.4. 浮点数
2.4.1. 浮点数的表示与转换
某些浮点数(eg.0.1)在计算机内不能精确表示(eg.3.1f + 2.1f != 5.2f)会丢一些有效位
2.4.2. IEEE表示
浮点数在计算机中包括三个部分:
- 符号位s:当s=0时表示正数,当s=1时表示负数
- (阶码)指数位exp:用来表示数值的范围或者大小
- 尾数位frac:表示实际的数值信息(精度)
float和double的各位如下:
规格化、非规格化、无穷大、NAN:
-
当阶码字段的二进制不全为0且不全为1时,此时表示的是规格化的值。
-
当阶码字段的二进制全为1时,此时表示的是非规格化的值
-
当阶码字段的二进制全为1时,表示的是特殊值,这里的特殊值分为无穷大和不是一个数,不是一个数就比如-1开方等等。
如下图表示:
下面来详细解释一下这三种数值的表示:
2.4.3. 规格化
单精度浮点中,当表示规格化的时候,阶码e的范围为00000001~11111110,即最小值为1,最大值为254,但是
这个e并不是阶码的值,而是e值减去一个偏置量,偏置量的值与编码字段的位数是相关的,如下所示,大E就是阶码值:
再来看看小数部分,尾数M被定义为1+f,尾数M的二进制表示:M=1.f22f21…f1f0=1+f,1<=M<2,在知道M、E、S之后就可以求得浮点数的值了
2.4.4. 非规格化
当阶码字段的二进制位全为0时,所表示的是非规格化的值,关于非规格化的数有两个用途,一是提供了表示数值0的方法,当符号位S等于0,阶码字段全为0,小数字段也全为0时,此时表示的正零;当符号位S等于1,阶码字段全为0,小数字段也全为0时,此时表示负零。非规格化的是的另外一个用途就是可以表示一个非常接近于0的数
2.4.5. 特殊值
-
无穷大:符号位0时,表示正无穷大,为1时,表示负无穷大。
-
不为一个数:-1开方,∞-∞等。
2.4.6. IEEE例题
- 十六进制转十进制:
float:0xC0A00000
二进制表示:1100 0000 1010 0000 0000 0000 0000 0000
符号位 | 阶码位 | 尾数位 |
---|---|---|
1 | 1000 0001 | 010 0000 0000 0000 0000 0000 |
E=129-127=2
S=1 负数
M=1. 010 0000 0000 0000 0000 0000=1.25
所以V=-1*1.25*2^2=-5
- 十进制转十六进制:
十进制数:-12.75
化为二进制为:1100.11
转化:1.10011*2^3
所以阶码位=127+3=1000 0010
尾数位为:10011 00000…
最后:
符号位 | 阶码位 | 尾数位 |
---|---|---|
1 | 1000 0010 | 100 1100 0000 0000 0000 0000 |
Hex:C14C0000
2.4.7. 整型转浮点
以float为例子,有一个整型数12345,它的二进制为11 0000 0011 1001(只看有效位),由于M=1+f,所以
f=100 0000 1110 0100 0000 0000
12345=1.1000000111001*2^13得到E=13,所以得到e=140=10001100,最后加上符号位0
2.4.8. 舍入
由于浮点数位有限,存在一个表示范围和精度的问题,对于数值x,只能用浮点数可以表示的最接近数值x‘来近似表示,这就是舍入。IEEE规定了4种舍入的方法,分别是:向0舍入、向下舍入、向上舍入、向偶数舍入。
向0舍入就是在数轴上,舍入方向总是向0的,例如1.4->1、-1.5->-1
向下舍入就是朝着小的方向舍入
向上舍入就是朝着大的方向舍入
向偶数舍入有两个原则,一是向最接近的值舍入,再一个是当处在"中间值"时要求有效位为偶数,就是舍去或进位之后最右边那一位为偶数。
2.4.9. 浮点数加法和乘法
阶码对齐,尾数相加(相乘),规格化,若超过有效位进行舍入。
2.4.10. 转化
数的范围double>float>int
- int转化为float,不会溢出,可能会被舍入
- int或float转化为double,能够准确表示
- double转化为float,可能会溢出+∞或-∞,也可能会舍入
- float或double转化为int,可能会溢出,如果需要舍入是向零舍入。
图片来源http://t.csdnimg.cn/flJZL