# 第6章 运算方法

> 📖 本章介绍计算机中数据的表示方法和算术运算，是课程的重点和难点。
> 🎯 重点理解补码运算和浮点数表示
> ⚠️ 考试范围：不考6.3.4、6.4.2、6.4.3、6.5节。重点复习例题6.2~6.4、6.6、6.8~6.23、6.29、6.30

---

## 📋 本章目录

- [[#6.1 无符号数和有符号数]]
- [[#6.2 定点数]]
- [[#6.3 浮点数]]
- [[#6.4 定点运算]]
- [[#6.5 浮点运算]]
- [[#本章小结]]
- [[#真题与作业精选]]
- [[#例题与解析]]

---

## 6.1 无符号数和有符号数

### 6.1.1 无符号数

> [!info] 定义
> 没有符号的数，所有位都表示数值。

**表示范围**（n位）：
$$0 \sim 2^n - 1$$

> [!example] 示例
> 16位无符号数：0 ~ 65535

无符号数就像你钱包里的钱，只有正数没有负数，范围从0到最大值。内存地址、数组索引、颜色值通常用无符号数表示。

### 6.1.2 有符号数

#### 机器数与真值

| 概念 | 定义 | 示例 |
|------|------|------|
| **真值** | 带正负号的数 | +1100, -1100 |
| **机器数** | 符号数字化的数 | 0,1100, 1,1100 |

**符号编码**：
- 0 表示正数
- 1 表示负数

真值用"+"和"-"表示正负，人容易理解但计算机不好处理；机器数用0和1表示正负，计算机容易处理但人不好理解。就像温度计用"+"和"-"表示零上和零下。

#### 1. 原码表示法

> [!info] 定义
> 符号位 + 数值的绝对值

**整数原码**：
$$[x]_{原} = \begin{cases} 0,x & 2^n > x \geq 0 \\ 2^n - x & 0 \geq x > -2^n \end{cases}$$

**小数原码**：
$$[x]_{原} = \begin{cases} x & 1 > x \geq 0 \\ 1 - x & 0 \geq x > -1 \end{cases}$$

> [!example] 示例
> - x = +1110 → [x]原 = 0,1110
> - x = -1110 → [x]原 = 1,1110
> - x = +0.1101 → [x]原 = 0.1101
> - x = -0.1101 → [x]原 = 1.1101

**零的表示**：
- [+0]原 = 0.0000
- [-0]原 = 1.0000

**特点**：表示简单易于转换，但加减运算复杂，零有两种表示。

原码用0表示正数1表示负数，后面跟着数值的绝对值。表示简单容易理解，但加减运算需要考虑符号，零有两种表示（+0和-0）。就像温度计用"+"和"-"表示零上和零下。

#### 2. 补码表示法

> [!important] 核心思想
> 用正数代替负数，将减法转换为加法。

**补数的概念**（时钟例子）：
- 时钟模为12
- -3 ≡ +9 (mod 12)
- 9 - 5 = 9 + 7 = 16 ≡ 4 (mod 12)

**整数补码**：
$$[x]_{补} = \begin{cases} 0,x & 2^n > x \geq 0 \\ 2^{n+1} + x & 0 > x \geq -2^n \end{cases}$$

**小数补码**：
$$[x]_{补} = \begin{cases} x & 1 > x \geq 0 \\ 2 + x & 0 > x \geq -1 \end{cases}$$

> [!example] 示例
> - x = +1010 → [x]补 = 0,1010
> - x = -1010 → [x]补 = 2^5 + (-1010) = 100000 - 1010 = 1,0110
> - x = +0.1001 → [x]补 = 0.1001
> - x = -0.1001 → [x]补 = 2 + (-0.1001) = 1.0111

**零的表示**：[+0]补 = [-0]补 = 0.0000（唯一表示）

**补码范围**（n位整数）：$-2^n \sim +(2^n - 1)$

> [!warning] 特殊值
> 8位补码：-128的补码为10000000，没有对应的原码

补码可以用时钟来理解：时钟模为12，-3小时相当于+9小时（因为-3+12=9）。补码就是用正数代替负数，将减法转换为加法。正数直接用原码表示，负数用模减去绝对值。

比如8位二进制：-10的补码是256-10=246=11110110。补码的优点是加减运算简单不需要考虑符号，零只有一种表示，范围比原码大1。缺点是表示不直观需要转换。所有整数运算都用补码。

#### 3. 反码表示法

**整数反码**：
$$[x]_{反} = \begin{cases} 0,x & 2^n > x \geq 0 \\ (2^{n+1}-1) + x & 0 \geq x > -2^n \end{cases}$$

**小数反码**：
$$[x]_{反} = \begin{cases} x & 1 > x \geq 0 \\ (2-2^{-n}) + x & 0 \geq x > -1 \end{cases}$$

> [!example] 示例
> - x = +1101 → [x]反 = 0,1101
> - x = -1101 → [x]反 = 1,0010

**零的表示**：
- [+0]反 = 0.0000
- [-0]反 = 1.1111

反码是补码减1，正数和原码相同，负数是原码除符号位外取反。是计算补码的中间步骤，某些旧计算机使用反码。

#### 4. 移码表示法

> [!info] 定义
> 移码 = 补码符号位取反

**用途**：便于比较大小（移码大的真值大）

**整数移码**：
$$[x]_{移} = 2^n + x \quad (-2^n \leq x < 2^n)$$

> [!example] 示例
> - x = +1010 → [x]移 = 1,1010
> - x = -1010 → [x]移 = 0,0110

移码把所有数都加上一个偏移量变成正数，便于比较大小。偏移量是128（8位移码），-128变成0，0变成128，+127变成255。浮点数的阶码通常用移码表示。

#### 四种编码对比

| 编码 | 符号位 | 零的表示 | 范围 | 运算 |
|------|--------|----------|------|------|
| 原码 | 0正1负 | 两种 | $-(2^{n-1}-1) \sim +(2^{n-1}-1)$ | 复杂 |
| 补码 | 0正1负 | 唯一 | $-2^{n-1} \sim +(2^{n-1}-1)$ | 简单 |
| 反码 | 0正1负 | 两种 | $-(2^{n-1}-1) \sim +(2^{n-1}-1)$ | 较复杂 |
| 移码 | 1正0负 | 唯一 | $-2^{n-1} \sim +(2^{n-1}-1)$ | 便于比较 |

**转换关系**：正数原码=反码=补码，负数补码=反码+1。

原码直接用符号位和绝对值，简单直观但运算复杂零有两种表示；补码用正数代替负数，运算简单零只有一种表示但表示不直观；反码是补码减1，是计算补码的中间步骤；移码补码符号位取反，便于比较大小。

---

## 6.2 定点数

### 6.2.1 定点表示

> [!info] 定义
> 小数点位置固定的数

**两种形式**：

```mermaid
graph LR
    subgraph "定点整数"
        A1[符号位] --> B1[数值部分] --> C1[小数点在最后]
    end

    subgraph "定点小数"
        A2[符号位] --> B2[小数点] --> C2[数值部分]
    end
```

**表示范围**：

| 类型 | 原码范围 | 补码范围 |
|------|----------|----------|
| 定点整数 | $-(2^{n-1}-1) \sim +(2^{n-1}-1)$ | $-2^{n-1} \sim +(2^{n-1}-1)$ |
| 定点小数 | $-(1-2^{-(n-1)}) \sim +(1-2^{-(n-1)})$ | $-1 \sim +(1-2^{-(n-1)})$ |

定点数用固定刻度的尺子：定点整数小数点在最后只表示整数，比如1010表示10；定点小数小数点在符号位后面只表示小数，比如0.1010表示0.625。

---

## 6.3 浮点数

### 6.3.1 浮点表示

> [!info] 定义
> 小数点位置可浮动的数，类似科学计数法。

**表示形式**：
$$N = S \times r^j$$

- S：尾数（小数）
- j：阶码（整数）
- r：基数（通常为2）

**存储格式**：

```mermaid
graph LR
    subgraph "浮点数格式"
        MS[阶符] --> E[阶码] --> M[数符] --> N[尾数]
    end
```

浮点数就像科学计数法，把一个数表示成尾数乘以2的阶码次方。比如101.1=1.011×2²，可以表示很大或很小的数。

### 6.3.2 浮点数规格化

**规格化目的**：提高精度，使尾数的最高位为1。

**规格化方法**：
- **左规**：尾数左移，阶码减1
- **右规**：尾数右移，阶码加1

规格化前0.001011×2³尾数前面有0精度低，规格化后1.011×2⁰尾数最高位为1精度高。

### 6.3.3 IEEE 754标准

> ⚠️ **这是考试高频考点**，IEEE 754格式转换在期中考试和样卷中都出现过。

**单精度浮点数（32位）**：符号位1位，阶码8位（移码表示），尾数23位
**双精度浮点数（64位）**：符号位1位，阶码11位（移码表示），尾数52位

**IEEE 754格式要点**：
- 阶码采用移码表示，偏移量为 $2^{n-1}-1$（单精度偏移127，双精度偏移1023）
- 尾数隐含一个整数位1（隐含的"1"），实际存储的是小数部分
- 阶码全0和全1有特殊含义（0、无穷大、NaN）

> [!example] 示例：IEEE 754转换
> 十进制-53 → IEEE 754单精度：符号位1，阶码132（偏移后），尾数1.10101
> 详细过程见下方"真题与作业精选"部分

IEEE 754标准是浮点数的"国家标准"：单精度32位精度较低但速度快，用于大多数图形处理和科学计算；双精度64位精度高但速度慢，用于高精度科学计算和金融计算。

---

## 6.4 定点运算

### 6.4.1 移位运算

> ⚠️ **算术移位是作业原题考点**，不同编码（原码、补码、反码）的移位规则不同，需要特别注意。

**算术移位**：左移相当于乘以2，右移相当于除以2

**不同编码的移位规则**：

| 编码 | 左移低位补 | 右移高位补 |
|------|-----------|-----------|
| 原码 | 补0 | 补0 |
| 反码 | 补0（正数）/补1（负数） | 补0（正数）/补1（负数） |
| 补码 | 补0 | 正数补0，负数补1（即补符号位） |

**注意**：算术左移可能溢出。比如原码1.1101000左移一位得到1.1010000，最高数值位的1被移出导致溢出。这是考试中常见的陷阱，三种编码的移位结果可能不同，具体示例见"真题与作业精选"部分。

算术移位像移动小数点，左移小数点向右移动数值变大，右移小数点向左移动数值变小。逻辑移位所有位向左或向右移动。1010左移1位变成10100（10→20）。

**逻辑移位**：左移高位移出低位补0，右移低位移出高位补0

---

## 6.5 浮点运算

### 6.5.1 浮点加减运算

> ⚠️ 6.5节不在考试范围内，以下内容仅供了解。

**步骤**：
1. **对阶**：使两个数的阶码相同
2. **尾数运算**：对阶后进行尾数加减
3. **规格化**：结果规格化
4. **舍入**：处理精度问题
5. **溢出判断**：检查阶码是否溢出

浮点加减运算像科学计数法加减：对阶使两个数的阶码相同，小阶向大阶看齐；尾数运算对阶后进行尾数加减；规格化使结果符合规格化要求；舍入处理精度问题；溢出判断检查阶码是否溢出。

1.01×2²+1.10×2¹：对阶变成1.01×2²+0.110×2²，尾数运算1.01+0.110=10.00，规格化10.00×2²=1.00×2³=8。

### 6.5.2 浮点乘除运算

**乘法**：阶码相加，尾数相乘，规格化
**除法**：阶码相减，尾数相除，规格化

浮点乘除运算像科学计数法乘除：10²×10³=10⁵，1.2×3.4=4.08，1.2×10²×3.4×10³=4.08×10⁵。

---

## 📝 本章小结

### 核心概念

1. **数据表示**：原码、补码、反码、移码
2. **定点数**：小数点位置固定
3. **浮点数**：小数点位置可浮动
4. **定点运算**：移位、加减、乘除
5. **浮点运算**：对阶、尾数运算、规格化

### 关键术语

| 术语 | 英文 | 含义 |
|------|------|------|
| 原码 | Sign-Magnitude | 符号位+绝对值 |
| 补码 | Two's Complement | 用正数代替负数 |
| 反码 | One's Complement | 补码减1 |
| 移码 | Excess Code | 补码符号位取反 |
| 浮点数 | Floating Point | 小数点位置可浮动 |

### 重点图示

> [!summary] 必须掌握的图
> 1. 四种编码的转换关系
> 2. 定点数和浮点数的表示
> 3. 浮点数加减运算流程
> 4. IEEE 754标准格式

---

## 📖 真题与作业精选

> 以下是来自期中考试、样卷和课后作业的真实题目，覆盖本章核心考点。

### 真题1：补码加减运算（期中原题）

**题目**：已知 A=-87, B=53，用8位补码计算 A-B。

**解答过程**：

首先求出A和B的补码表示：
- A = -87，87的二进制为01010111，取反加1得 [A]补 = 10101001
- B = 53，53的二进制为00110101，[B]补 = 00110101
- A - B = A + (-B)，需要求 [-B]补：B的补码取反加1得 [-B]补 = 11001011

补码相加：
```
  10101001   (A的补码)
+ 11001011   (-B的补码)
-----------
1 01110100   最高位进位丢弃
```

结果 [A-B]补 = 01110100，真值为 +116。

**判断溢出**：A是负数（符号位1），-B是负数（符号位1），两个负数相加结果为正数（符号位0），发生**负溢出**。

> 💡 这道题展示了补码减法的完整过程：减法转化为加法，以及双符号位溢出判断法——两个负数相加得正数即为溢出。

### 真题2：IEEE 754转换（样卷原题）

**题目**：将IEEE 754单精度浮点数 C2540000H 转换为十进制。

**解答过程**：

十六进制转二进制：C2540000H = 11000010 01010100 00000000 00000000

按IEEE 754格式拆分：
- 符号位：**1**（负数）
- 阶码：**10000100** = 132，偏移后 e = 132 - 127 = 5
- 尾数：**01010100 00000000 00000000**，加上隐含的1，实际尾数为 1.01010100... = 1.10101

计算结果：
$$-(1.10101)_2 \times 2^5 = -110101.0_2 = -(53)_{10}$$

> 💡 IEEE 754转换是高频考点，步骤：十六进制→二进制→拆分符号/阶码/尾数→阶码减偏移量→组装尾数（加隐含1）→计算结果。考试时务必注意阶码偏移量是127（单精度）或1023（双精度）。

### 真题3：浮点数表示（期中原题）

**题目**：用浮点数表示 x₁=7.375 和 x₂=-86.5，分别写出阶码和尾数的原码及补码形式。

**解答过程**：

**x₁ = 7.375**：
- 转换为二进制：7.375 = 111.011 = 0.111011 × 2³（规格化）
- 阶码3，8位原码：00000011
- 尾数0.111011，补足位数：0.1110110000
- 因为是正数，原码 = 补码

**x₂ = -86.5**：
- 转换为二进制：86.5 = 1010110.1 = 0.10101101 × 2⁷（规格化）
- 阶码7，8位原码：00000111
- 尾数为负数：原码为 1.1010110100，补码需要对负数尾数取反加1

> 💡 浮点数表示需要注意：1）规格化（尾数最高位为1）；2）阶码和尾数的符号分开处理；3）负数尾数的补码表示不要遗漏。这也是期中考试考过的原题。

### 真题4：算术移位（第6章作业原题）

**题目**：对以下三个数分别进行算术左移一位，比较三种编码的结果。

- [x]原 = 1.1101000
- [y]补 = 1.1101000
- [z]反 = 1.1101000

**解答过程**：

**原码左移**：符号位不变，数值位整体左移，低位补0。
- 1.1101000 → 1.1010000
- 原码左移后最高数值位的1被移出，发生**溢出**，结果出错。

**补码左移**：符号位不变，数值位整体左移，低位补0。
- 1.1101000 → 1.1010000
- 补码的左移规则与原码相同（低位补0），此结果正确。

**反码左移**：负数反码低位补1。
- 1.1101000 → 1.101000**1**
- 反码负数左移时低位补1，结果正确。

> 💡 三种编码左移规则的区别是作业重点：原码和补码左移低位补0，但原码需额外判断溢出；反码负数低位补1。这些细微差异是考试中容易丢分的地方。

---

## ⚡ 知识点速记卡

> 考前快速过一遍，30秒回忆整章核心

**本章考试重点排序**（按出现频率）：
1. **补码加减运算** —— 期中必考，期末高频，掌握溢出判断（双符号位法）
2. **IEEE 754浮点数转换** —— 样卷、期中均有原题，熟记偏移量127/1023
3. **浮点数规格化表示** —— 期中原题，注意阶码和尾数分别编码
4. **算术移位** —— 作业原题，三种编码移位规则的区别
5. **Booth算法（补码乘法）** —— 课后习题重点，理解每步的判断规则

**四种编码速记**：原码（符号+绝对值，零有两种）、补码（正代负，零唯一，运算最简单）、反码（补码-1，过渡用）、移码（补码符号取反，便于比较大小）。

**正数**：原码=反码=补码。**负数**：补码=反码+1。口诀：正数不变，负数取反加1。

**补码范围**（n位）：-2^(n-1) ~ +(2^(n-1)-1)。8位补码：-128~127。-128没有对应原码！

**补码加减运算**：加法直接加，减法变补码后加。溢出判断：两个正数相加得负数（正溢出），两个负数相加得正数（负溢出）。口诀：同号相加看结果，异号相加不会溢出。

**定点数**：小数点位置固定。定点整数（小数点在末尾）、定点小数（小数点在符号位后）。

**浮点数 = 尾数 × 2^阶码**，类似科学计数法。规格化：尾数最高位为1，左规尾数左移阶码减1，右规尾数右移阶码加1。

**IEEE 754单精度（32位）**：1位符号 + 8位阶码（移码，偏移127）+ 23位尾数。隐含整数位1。阶码全0和全1有特殊含义。

**IEEE 754转换速查**：
- 十六进制→二进制→拆分（1+8+23）
- 阶码值 - 127 = 实际指数
- 尾数前加隐含的1.，乘以2的指数次方
- 符号位1为负，0为正

**浮点加减五步**：对阶（小阶向大阶看齐）→ 尾数运算 → 规格化 → 舍入 → 溢出判断。

**移位运算**：算术左移=×2，算术右移=÷2。逻辑移位补0，算术移位保持符号位。注意原码、补码、反码移位时低位补值不同。

---

## 🧪 例题与解析

### 例题1：补码计算

**题目**：计算8位补码的表示范围，并求-5的补码。

**答案**：

8位补码范围：-2⁷=-128到2⁷-1=127，即-128~127。
-5的补码：5的二进制00000101，取反11111010，加1得11111011。

这就像一个8位的时钟，范围-128到127，-5的补码是时钟倒退5小时。

### 例题2：浮点数表示

**题目**：将十进制数-0.75表示为IEEE 754单精度浮点数。

**答案**：

0.75=0.11(二进制)，-0.75=-0.11，规格化-1.1×2⁻¹。
符号位1（负数），阶码-1+127=126=01111110，尾数10000000000000000000000。
完整表示：1 01111110 10000000000000000000000。

### 例题3：补码加法

**题目**：用补码计算 5 + (-3)。

**答案**：

5的补码00000101，-3的补码11111101，相加：
```
  00000101
+ 11111101
-----------
1 00000010
```
补码结果00000010，真值+2。5+(-3)=2✓

### 例题4：浮点数加法

**题目**：计算 1.01 × 2² + 1.10 × 2¹。

**答案**：

对阶：1.10×2¹=0.110×2²
尾数运算：1.010+0.110=10.000
规格化：10.000×2²=1.000×2³=8
验证：1.01×2²=5，1.10×2¹=3，5+3=8✓

### 例题5：溢出判断

**题目**：判断8位补码运算 127 + 1 是否溢出。

**答案**：

127的补码01111111，1的补码00000001，相加得10000000。
两个正数相加结果为负数（10000000是-128的补码），发生正溢出。
真正结果128，实际结果-128，溢出。

---

## 🔗 相关链接

- [[00_计算机组成原理学习指南]] - 返回主目录
- [[05_输入输出系统]] - 上一章
- [[07_指令系统]] - 下一章
- [[08_CPU结构与功能]] - CPU相关内容

---

*本章难度：⭐⭐⭐⭐⭐ 困难*
*重要程度：⭐⭐⭐⭐⭐ 重点*
*考试提醒：本章是期中考试和期末考试的核心章节，补码运算和IEEE 754几乎必考*
