笔记 | 计算机系统基础:02-逻辑运算电路

如题所述

第1个回答  2022-07-13

如果没学过基础逻辑电路,应该是有专门的一门课《数字逻辑电路》,那门课里有更详细的介绍。因为比较注重逻辑推理,据大学的数电老师说,自从教了这门课,反正他打桥牌就没怎么输过。在计算机系统基础这门课里只是引用一些逻辑部件,更重要的是理解C语言中各类运算是怎么通过电路实现的,由此可能存在怎样的溢出问题,这才是我们学习的重点。

另外,推荐大家一本书《编码:隐匿在计算机软硬件背后的语言》,可以看成是“如何一步步搭建一台计算机”,但是却一点都不晦涩难懂,非常生动有趣哦。

从运算符无法区分,由X的类型决定:

无符号数和带符号数加减运算都用以下部件完成:

注:其实所谓的产生溢出,无非就是最后运算的结果超出了当前类型能表示的范围,所以同样两个数相加减,当成无符号数或有符号数,溢出结果就可能不同。另外虽然我们上面进行了分类讨论,但是对于输入到整数加减运算器中的两个数,计算机可不管你是无符号数还是带符号数,一律都按同样的方式进行运算,然后把标志位存下来,至于你要拿这个结果当无符号数还有符号数,或者判断是否借位/溢出,都是你的事,这一点要记在心里。

两个n位整数相乘,结果只取2n位乘积中的低n位,高n位可以用来判断溢出:

需要注意计算机硬件是不判溢出的,仅保留2n位乘积,供软件使用,所以程序需进行一些防溢出的处理。

另外,整数乘法运算比较耗费时钟周期,因此编译器在处理 变量与常数相乘时,往往用移位、加法和减法的组合来代替 。如:x 20 = x (16+4) = (x<<4)+(x<<2),之前记得左移可能产生溢出,所以不论是否溢出,两种运算方式结果都是一样的。

对于整数除法外,因为商的绝对值不可能比被除数的绝对值大,所以 不会发生溢出,只有一种例外 带符号整数的-2 n-1 /-1 = 2 n-1 ,记得我们介绍补码时曾说过补码能增加表示一个最小负数吗?不过它没有对应的正数,所以如果对它除-1,就发生溢出了。

另外,整数除法运算更耗时钟周期,所以为了缩短运算时间,编译器在处理 一个变量与一个2的幂次形式的整数相除时,常用逻辑/算术右移运算来实现 。如:3 = 12/4 = 0000 1100 >> 2 = 0000 0011 = 3,-3 = -12/4 = 1111 0100 >> 2 = 1111 1101 = -3。

整数除法是有可能不能整除的,那就必须采用 朝零舍入 的截断方式。

若两个规格化浮点数为A = M a ·2 E a ,B = M b ·2 E b ,则:
A±B = (M a ± M b ·2 -(E a -E b ) )·2 E a (假设E a >= E b
A*B = (M a * M b )·2 (E a +E b )
A/B = (M a / M b )·2 (E a -E b )

以上运算有可能出现几种情况:
阶码上溢 :正指数超过最大允许值(127) => +∞/-∞/溢出
阶码下溢 :负指数超过最小允许值(-126) => +0/-0
尾数溢出 :最高有效位有进位 => 右规 (结果不一定溢出)
非规格化尾数 :数值部分高位为0 => 左规
右规或对阶时 ,右段有效位丢失 => 尾数舍入 (可以运算过程中添加保护位)

举例说明如何计算浮点数加/减法:
0.5 + (-0.4375)
= 1.000 x 2 -1 + (-1.110 x 2 -2 ) (规格化)
= 1.000 x 2 -1 + (-0.111 x 2 -1 ) (对阶,小阶向大阶看齐,尾数右移)
= 0.001 x 2 -1 (尾数加减)
= 1.000 x 2 -4 (规格化,左规:左移一位,阶码减1,判断是否有阶码溢出)
= 0.0625 (是否需要考虑舍入;如果尾数是0,则需将阶码也置0,表示0)

在尾数右移的过程中,可能会发生超出规定位数的情况,可以在尾数右边放 一个保护位和一个舍入位 ,用来保护对阶时右移的位或中间结果,当左规时被移入尾数中,作为舍入判断的依据。
举个例子:(假设尾数只有3位有效位)
0.59375 = 0.5 + 0.09375 = 1.00 x 2 -1 + 1.10 x 2 -4 = 1.00 x 2 -1 + 0.00 x 2 -1 (没有附加位)= 1.00 x 2 -1 = 0.5
0.59375 = 0.5 + 0.09375 = 1.00 x 2 -1 + 1.10 x 2 -4 = 1.00 x 2 -1 + 0.0011 x 2 -1 (两位附加位)= 1.0011 x 2 -1 = 1.01 x 2 -1 (舍入进位) = 0.625 (结果比上面更精确)
IEEE 754舍入的方式主要有就近舍入(舍入为最近可表示的数),正向舍入(+∞方向),负向舍入(-∞方向),和朝0方向舍入(正数floor,负数ceil)

C语言中有float和double类型的浮点数,分别对应IEEE 754单精读浮点数格式和双精度浮点数格式,那么在类型强制转换的时候可能会有什么问题?(这就是为什么我们要学习数据在计算机中真正的存储形式)



注:文中图片来源于mooc官网

相似回答