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