关于我

数据的表示与计算

第二章_数据的表示与计算

2.1 进制和计算

2.1.1 进位计数制

本节主要内容为:

  1. 其他进制怎么转换成十进制:各位基数*权重再相加即可。
  2. 二进制、八进制和十六进制之间相互转换:不想多说,懂得都懂。
  3. 十进制怎么转换成其他进制: 整数部分除 r 取余,如图所示: 整数部分除 r 取余 整数部分乘 r 取整,如图所示: 整数部分乘 r 取整 想再快一点可以凭直觉拼凑。

值得注意的是各进制有不同的书写方式,如图所示: 各进制不同的书写方式

2.1.2 定点数的编码表示

首先明确区分概念:定点数和浮点数、真值和机器数

真值是现实中人类常用的数,机器数是需要将正负符号使用数字表示。根据小数点的位置是否固定,计算机中的数值表示分为定点表示和浮点表示。

机器内部通常会使用定点数把小数部分整数部分分开表示。但在机器内部,并没有小数点的区分,只是人为的约定了小数点的位置以方便人们进行计算。因此,在定点数的编码和计算中,无须区分该数是小数还是整数,只需关心符号位和数值位(尾数)即可。

定点数的编码表示法主要有四种: 原码、反码、补码和移码: 原码: 原码 反码: 反码 补码: 补码 移码: 注意:移码的正确计算步骤是 移码 = 真值 + 偏移量,偏移量为 2n-1 时,移码才刚好等于补码符号位取反! 移码 以题目来熟悉这几个“码”,注意做题技巧: 题目

补码的作用: 在计算机硬件的实现过程中,加法器的实现难度小于减法器的实现难度,而一个计算机的底层如果既要实现加法器又要实现减法器,会显得冗余。所以能不能只使用加法器实现加法和减法呢?

模运算中,如果两个数绝对值相加等于模,那么这两个数互为对方的补数,利用这个性质,在减去一个数的时候,只需要加上这个数的补数即可。即 原码 A − 原码 B = 原码 A + 补码 B,而补码就是这个二进制补数,模通常就是机器字长(比如 28 bit)。

如果使用数学手段严谨的证明补码为什么等于原码的补数,需要很多数论的知识,这里就不做展开,记住怎么求即可。

2.1.3 C语言中的整数类型转换

C语言中的整数类型转换内部原理如图所示: C语言中的整数类型转换 注意 C语言中定点数是补码存储!,而短类型转长类型高位填充是零填充还是符号填充,视符号位有无而定(注意是符号位!不要看到尾数第一位去了!),这样才不会改变真值!

2.2 运算方法与运算电路

2.2.1 数电基础知识

基本逻辑门电路概括如下,很简单,不用深究其数字逻辑电路细节: 注意运算优先级是:非 > 与 > 或。 基本逻辑门电路 常见公式

多路选择器、三态门: 这是两个常见的数字逻辑电路使用部件,具体介绍如下图所示: 多路选择器 三态门

2.2.2 基本运算部件

2.2.2.1 一位全加器

一位全加器示意如图所示: 一位全加器

2.2.2.2 串行进位全加器

将 n 个一位全加器串起来,就能够得到多位串行进位全加器,如图所示: 进位全加器

2.2.2.3 并行进位加法器

而串行进位加法器,这种加法器的运算速度依赖于进位输出的速度,故而速度会很慢,将多个一位全加器的进位输出信息连接到一个 CLA 部件(先行逻辑进位),形成并行进位加法器,就能够大大提高处理效率。 如图所示: 并行进位加法器

2.2.2.4 带标志位的加法器

由于加法运算过程中可能会产生溢出,所以需要额外设置输出标志位来进行标识。如图所示: 带标志位的加法器

2.2.2.5 ALU

ALU 是运算器的核心,而由于四则运算在计算机中都是通过加法进行实现,因此加法器是 ALU 的核心,其功能如下图所示: ALU 的功能 关于 ALU 的组成,只需要简单了解即可,考研不会考察 ALU 的组成,如图所示: ALU 的组成 ALU 的图示是需要看懂的,像标志加法器一样,也会产生标志信号,如图所示: ALU 的图示

2.2.3 定点数的移位运算

根据操作数类型的不同,移位运算可以分为逻辑移位算术移位。 逻辑移位常用于处理无符号整数,算术移位常用于处理带符号整数。但是只是常用于,对于底层的计算机硬件(移位寄存器)来说,都只是二进制串,不论是带符号还是不带符号,只要收到的指令是用 SHR(逻辑右移) 或是 SAR(算术右移),CPU 就会真的执行不同硬件动作

2.2.3.1 逻辑移位

逻辑移位一般用于处理无符号整数。 过程如图所示,注意移位溢出和精度丢失的判别条件: 逻辑移位

2.2.3.2 算术移位

算术移位一般用于处理带符号整数。 过程如图所示,注意移位溢出和精度丢失的判别条件: 算术移位

2.2.4 定点数的加减运算

2.2.4.1 有符号数的加减运算

前面已经说过,对于定点数的加减运算,我们可以通过补码的方式将其全部转换成加法进行实现,求补码的方式前面也已经讲述过。总之就是:

  1. 有符号数原码做加减运算,变成补码之后按补码的规则做运算的到结果的补码
  2. 有符号数的补码做加法运算,直接加;做减法运算,将减数连带符号位取反再加一(即将[B]->[-B]),再做加法。

本节重点在于硬件如何判断有符号数加减是否溢出。 显然,只有同号定点数进行相加才会出现溢出现象,而溢出又分为上溢和下溢,关于溢出的判断有三种方法,具体如下所示:

  • 方法一: 两个加数为正(负),运算结果为负(正)时发生溢出。如图所示: 方法一

  • 方法二: 符号位的进位和最高数值位的进位不同则发生溢出。如图所示: 方法二

  • 方法三: 采用双符号位补码表示数值,若运算出来两个符号位不同则溢出。如图所示: 方法三

2.2.4.2 无符号数的加减运算

对于计算机底层硬件来说,无符号数加减有符号数的补码的加减运算是一样的。如图所示: 无符号数加减 关于无符号数加减的溢出判断如下图所示: 无符号数加减的溢出判断

2.2.4.3 补码加减运算电路

对于补码的加减运算电路,加法直接使用一个 n bit 加法器就能够实现,显而易见不清晰的点在于如何在实现补码的减法时,将减数全部取反再加 1,电路如下图所示: 补码加减运算电路 无符号数加减的实现电路当然和补码加减运算电路是一样的。

2.2.5 定点数的乘法运算

2.2.5.1 无符号整数乘法运算原理

手算二进制乘法,和十进制乘法非常类似,而在机器底层硬件中,乘法主要通过加法器移位运算进行实现。如图所示: 无符号整数乘法运算原理 注意:在溢出判断时,其实 OF/CF 都置为 1,但是程序员通常会使用 OF 标志位做判断。

2.2.5.2 带符号整数乘法运算原理

带符号整数进行乘法运算的电路和无符号数乘法非常类似,但是注意:带符号数在计算机中通常使用补码进行存储,补码的乘法运算的数学原理较为复杂,只需要了解计算机底层硬件的工作原理即可。如下图所示: 带符号整数乘法运算原理 用一个真题来熟悉,如下图所示: 真题

2.2.5.3 计算机实现乘法运算的三种方式

第一种: 是前面讲过的使用 ALU、移位器、寄存器、逻辑控制组成的乘法电路。 这种方式在三种方式中速度适中。

第二种: 通过阵列乘法器实现乘法运算。不必研究具体电路,知道特点即可。 这种方式在三种里面是最快的,只需要一个时钟周期。 如图所示: 阵列乘法器

第三种: 通过软件模拟(编译器生成移位 + 加法指令)。 这种方式在这三种里面是最慢的。 模拟代码如下:

/*用移位运算、加法运算等效实现32bit无符号数乘法*/
unsigned int multiply_unsigned(unsigned int x, unsigned int y) {
    unsigned int result = 0;
    for (int i = 0; i < 32; i++) {
        // 提取乘数 y 的最低位
        unsigned int bit = y & 1;
        // 如果当前位为 1, 加上被乘数 x
        if (bit) {
            result += x;
        }
        // 被乘数 x 左移一位, 乘数 y 右移一位
        x <<= 1;
        y >>= 1;
    }
    return result;
}

通过一道真题来熟悉这三种方式的区别: 真题

2.2.6 定点数的除法运算

看后面在学有余力的情况下,再来补充电路细节。一轮复习不要死磕电路细节。

2.2.6.1 无符号整数的除法运算原理

标准手算的无符号整数的二进制除法和标准手算的十进制的除法其实是一样的(很多年不用这种标准除法了,回忆一下)。

关于无符号整数的除法运算电路如图所示: 无符号整数的除法运算电路

关于商溢出的进一步探讨如下图所示: 商溢出

2.2.6.2 带符号整数(补码)的除法运算原理

带符号整数(补码)的除法运算电路如下图所示: 带符号整数(补码)的除法运算

2.3 浮点数的表示和运算

由于真值能够无限增长,只使用定点数进行表示即使是现代的 64 位机器字长的计算机也表示不够。于是采用浮点数进行表示(浮点数就像“二进制科学计数法”)。 浮点数有很多的表示标准,但是考研统一使用 IEEE 754 标准。

2.3.1 浮点数的表示_IEEE 754

在 C 语言中主要有两种类型,即 单精度浮点数(float)双精度浮点数(double),当然还有其他类型,不过考研不用管。如下图所示: 单双精度浮点数 关于单精度浮点数,其具体格式如下图所示: 单精度浮点数 关于双精度浮点数,其具体格式如下图所示: 双精度浮点数

用几个例题来进行关于浮点数转化的熟悉,真值与浮点数互相转化非常重要! 例题1 例题2 例题3

2.3.2 浮点数的表示范围及几种特殊的状态

IEEE 规定,当阶码不全为 0 或者 1 的时候,这个时候的浮点数为规格化表示。阶码全为 0 和 1 的情况一般被用作表示特殊浮点数,如下图所示: 特殊浮点数 而关于规格化的浮点数的表示的范围如下图所示: 规格化的浮点数的表示的范围 当然,在处理浮点数的运算的时候,同样会产生溢出现象。 IEEE 规定把大于最大表示正数小于最小表示负数的情况都被称为上溢,关于上溢的处理具体如图所示: 上溢的处理 IEEE 规定把小于最小表示正数大于最大表示负数的情况都被称为下溢,关于下溢的处理具体如图所示: 下溢的处理 关于下溢区间会有两种情况。 特别注意非规格化数(上面表格的特殊数) 的情况,计算时容易错误,如下图所示: 非规格化数 用一道真题来熟悉非规格化数的表示: 真题 关于**无定义数(上面表格的特殊数)**也有一些需要注意的地方,如下图所示: 无定义数

2.3.3 浮点数的加减运算

2.3.3.1 例题示例

浮点数的加减运算和十进制科学计数法是一样的分为五个步骤分别是: 1. 对阶 2. 尾数加减 3. 尾数规格化 4. 尾数的舍入处理 5. 溢出判断

通过三个例子来感受,非常易错,一定去试试: 例子1 例子2 例子3

2.3.3.2 舍入问题

关于浮点数的舍入方式如下图所示,重点在于关注就近舍入这种模式: 舍入方式 关于就近舍入这种方式,举四个例子如下图所示: 就近舍入 就近舍入

2.3.3.3 溢出问题

浮点数的溢出并不是从尾数来判断的,而是通过阶码进行判断,关于上溢的判断如图所示: 上溢溢出 而关于下溢的判断也如图所示: 下溢判断

2.3.4 数据的存储和访问

2.3.4.1 大小端模式

计算机存储通常采用小端模式: 大小端模式

2.3.4.2 边界对齐

关于计算机的边界对齐如图所示: 边界对齐

总是在探索未知