Ch2. 信息的表示与处理
说实话,这部分的东西我到大四了,我觉得我看过不下10遍了。原码反码补码浮点运算之类的。
本章重点主要包括三种数:
无符号数:表示大于等于零的数。
有符号数:通常用补码表示。
浮点数:小数。
CSAPP 主要讲解 C C++ 的数据表示方法,java 有些不同。
内存空间
计算机寻址并不是按一个个二进制位来找的,通常是8位二进制位组成的一个字节是最小的寻址单元。
内存可以被视作一个字节数组,虚拟内存。每个字节都有一定的地址序列来唯一标识这个字节。所有可能的地址集合就是虚拟地址空间。
字
计算机处理数据的单位是一个字。比如32位计算机是4字节为一个字。
原码 反码 补码 浮点数
三种码和浮点数可以阅读博主的这篇文章:
计算机组成原理_4 各种码的作用,及乘除运算_乘积高位和乘积低位是什么意思-CSDN博客
了解三种码的功能是最重要的。
原码:表示二进制数,但是需要单独表示正负号,而且会出现正负零的问题。
反码:可以表示正负数,可以进行不溢出的正负数运算,但是也会出现正负零的问题。
补码:可以进行溢出的运算,避免正负零问题。补码类似时钟,指针指到12点其实又变成从0开始了。
下面是几个位操作的例题,有助于帮助发掘计算机的运算思维和人的区别:
x 假设是4字节长度的数据。
- x<0,x*2不一定<0,可能溢出了。
- unsigned x 确实>=0.
- x后三位=1,x左移30次,得到1100000……00,第一位是1,是负数。
- 同2,对。
- 主要是负数最小值 Tmin,也就是 100000……00 的负数还是他自己。所以不一定成立。
- x*x 也是可能溢出,错误。
- x+y 也可能溢出,错误。
- 对。
- 错,因为 Tmin 的负数还是自己。所以正数取反一定是负数,负数取反有一个特例。
- 特例是0,错。不过对于其他例子,这都是成立的。
- 对。
- 错,符号位变了。
- x=Tmin 时,错误。
可见有一些东西人算的时候觉得肯定正确(x平方>=0),但是计算机他对数据处理能力有限,容易发生溢出造成错误答案。
字节序
字节数据顺序,比如我有11100010这个数据,发送给对方,是按 01000111 顺序发,还是 11100010 顺序?
发送数据是从低地址往高地址逐个发送。
大端序:权重大的位在低地址。所以发送顺序就是11100010.
小端序:权重小的位在低地址。发送顺序是01000111.
浮点数
小数点后面的每一位权重是2-1,2-2,2-3……
注意,浮点数能表示的精度范围有限,所以会出现很多甚至都不满足加法乘法结合律的运算例子。
结合律中,3.14相比1e10太小了,求和后这部分精度被省去了。
分配律中,1e20*1e20已经太大溢出了。
理解了以上内容,在自己开发过程中才会想到更优解或者避免一些奇怪的问题。比如二分法经典的 mid=(low+high)/2
,真正安全的做法是 mid=(high-low)/2+low
,因为 high+low 可能溢出。