小护士读书笔记系列之《深入理解计算机系统》第二章信息的表示和处理(三)
欢迎来到小护士读书笔记系列之《深入理解计算机系统》第二章信息的表示和处理(三)。上回,小护士讲到了整数是如何在计算机中表示为无符号数和有符号数的,而这次小护士将说明计算机如何做加减乘除。
2.3.1 无符号数加法
无符号数加法跟普通数学运算一样,也是 。唯一不同的地方是无符号数做加法时,如果结果值太大,超出位数最大表示范围,就会溢出。例如:
9+12 = [1001] + [1100]
21 = [10101]
假设仅用4位表示一个数,则对结果值进行截断。可得,
5 = [0101]
快速小技巧:21 mod 16 = 21 mod = 5
4次幂对应4位数表示,2为底对应二进制。
如何检测是否溢出?
如果5 < 9 || 5 < 12 == true
则为溢出。
2.3.2 补码加法
补码加法跟无符号数加法差不多,也是遵循普通数学运算逻辑,但由于补码支持负数,因此也会有
。
同样,补码加法也会溢出,但分为两种:
- 正溢出:补码的正数相加溢出
- 负溢出:补码的负数相加溢出
为了方便大家理解,直接给出表格说明补码如何做加法:
x | y | x+y | 截断值 |
---|---|---|---|
-8 [1000] |
-5 [1011] |
-13 [10011] |
3 [0011] |
-8 [1000] |
-8 [1000] |
-16 [10000] |
0 [0000] |
-8 [1000] |
5 [0101] |
-3 [11101] |
-3 [1101] |
2 [0010] |
5 [0101] |
7 [00111] |
7 [0111] |
5 [0101] |
5 [0101] |
10 [01010] |
-6 [1010] |
补码正负溢出原理:
令
,当且仅当
,
,但
时,计算
发生了正溢出。当且仅当
,
,但
时,计算
发生了负溢出。
2.3.3 补码的非(难懂非重点,可以忽略)
加法逆元听说过吗,例如
,此时
就是
的加法逆元。
对于无符号数来说,在四位表示一个数的情况下,
,截断后得
,此时
是
的加法逆元。
对于补码来说,同理可得,
,截断后得0。
2.3.4~2.3.5 无符号乘法与补码乘法
还是直接给出表格展示,比较容易理解。以3位表示一个数:
模式 | x | y | x*y | 截断值 |
---|---|---|---|---|
无符号 | 5 [101] |
3 [011] |
15 [001111] |
7 [111] |
补码 | -3 [101] |
3 [011] |
-9 [110111] |
-1 [111] |
无符号 | 4 [100] |
7 [111] |
28 [011100] |
4 [100] |
补码 | -4 [100] |
-1 [111] |
4 [000100] |
-4 [100] |
无符号 | 3 [011] |
3 [011] |
9 [001001] |
1 [001] |
补码 | 3 [011] |
3 [011] |
9 [001001] |
1 [001] |
2.3.6~2.3.7 乘以常数,除以 2 的幂(计算优化)
乘法的本质就是加法。例如,
;相当于
。
对于计算机来说,也是一样的,把 3 累加四次得出 12。
但是搞计算机科学的那些教授很厉害,发明了左移操作符<<
。
想要得出
,很简单。
那如果是 呢?对于这种奇数相乘的情况,书本没介绍,只是一笔带过说这个优化不优化完全看编译器心情。:)
大多数编译器只在需要少量移位、加法和减法就足够的时候才使用这种优化。
书中介绍了形式A和形式B的计算方式。但小护士觉得没太大必要去死记这些优化公式,毕竟在芯片实现上就是完全两码事,只是理论上可以用数学的方式来优化计算,减少计算次数。
作为读书笔记,小护士还是觉得要写一下这两个雕虫小技:
例子,
:
因为
所以
书中关于用除以2的幂来优化除法的声明:
除以2的幂可以通过逻辑或算术右移来实现。这也正是为什么大多数机器上提供这两种类型的右移。不幸的是,这种方法不能推广到除以任意常数。同乘法不同,我们不能用除以2的幂的除法来表示除以任意常数 K 的除法。
除法的本质不是减法。除以2的幂的优化方法还有技术细节要死记,但小护士建议不要这样做,那些除以2的幂的补码除法会出现向下舍入和向上舍入的若干问题。因为这里不是重点,所以,建议先跳过,毕竟看这本书的目的还是在于理解整体知识,而不是死记局部知识。而且重头戏是在后面的章节,没必要花大量时间放在第二章的细节理解上。
下篇预告: 2.4 浮点数
浮点数是个很特殊的数字,这东西与 IEEE(电气和电子工程师协会)有着深厚的联系。当年为了制定这个浮点数标准,科学家们互怼了很久,里面的感人故事绝对可以拍成电影。