《计算机组成原理》第 6 章 - 计算机的运算方法
目录
🔢 6.1 无符号数和有符号数
🔵 6.1.1 无符号数
🔵 6.1.2 有符号数
📊 6.2 数的定点表示和浮点表示
🔵 6.2.1 定点表示
🔵 6.2.2 浮点表示
🔵 6.2.3 定点数和浮点数的比较
🔵 6.2.4 举例
🔵 6.2.5 IEEE 754 标准
6.3 定点运算
🔵 6.3.1 移位运算
🔵 6.3.2 加法与减法运算
🔵 6.3.3 乘法运算
🔵 6.3.4 除法运算
🌊 6.4 浮点四则运算
🔵 6.4.1 浮点加减运算
🔵 6.4.2 浮点乘除运算
🔵 6.4.3 浮点运算所需的硬件配置
🤖 6.5 算术逻辑单元
🔵 6.5.1 ALU 电路
🔵 6.5.2 快速进位链
📚 总结
🔢 6.1 无符号数和有符号数
🔵 6.1.1 无符号数
定义:没有符号位的数,所有二进制位表示数值大小(如 8 位无符号数范围:0~255)。
代码示例:Java 实现无符号数加法
public class UnsignedNumberDemo {public static void main(String[] args) {// 8位无符号数相加(模拟溢出)byte a = (byte) 200; // 二进制:11001000(无符号值200)byte b = (byte) 100; // 二进制:01100100(无符号值100)// 无符号加法(需手动处理溢出)int sum = (a & 0xFF) + (b & 0xFF); // 0xFF转为无符号数if (sum > 0xFF) { // 超过8位无符号范围System.out.println("溢出!无符号和:" + sum);} else {System.out.println("无符号和:" + sum); // 输出:300(实际溢出为44,需注意二进制截断)}}
}
说明:通过0xFF
掩码将有符号字节转为无符号数运算,手动检测溢出。
🔵 6.1.2 有符号数
定义:最高位为符号位(0 正 1 负),常用补码表示负数。
代码示例:Python 实现补码转换
def int_to_twos_complement(n, bits=8):"""将整数转为指定位数的补码二进制字符串"""if n < 0:return bin((1 << bits) + n)[2:].zfill(bits) # 负数补码计算else:return bin(n)[2:].zfill(bits) # 正数补码即原码# 示例:-5的8位补码
print(int_to_twos_complement(-5)) # 输出:11111011
📊 6.2 数的定点表示和浮点表示
🔵 6.2.1 定点表示
定义:小数点固定(通常在符号位后或最低位后),分为纯整数和纯小数。
案例:定点数乘法(假设小数点后 4 位)
public class FixedPointMultiplication {public static void main(String[] args) {int a = 0b10101100; // 假设为定点数:1.0101100(-0.671875)int b = 0b01101000; // 0.671875int product = a * b; // 直接整数乘法int shift = 8; // 小数点后总位数(假设各4位)int result = product >>> shift; // 右移取整数部分(逻辑右移)System.out.println("定点乘积补码:" + Integer.toBinaryString(result));}
}
🔵 6.2.2 浮点表示
结构:阶码(指数)+ 尾数(小数),如:
浮点数 = 尾数 × 基数^阶码
代码示例:IEEE 754 单精度浮点数解析
import structdef float_to_binary(f):"""将浮点数转为IEEE 754单精度二进制字符串"""bits = struct.unpack('!I', struct.pack('!f', f))[0]return bin(bits)[2:].zfill(32)# 示例:解析浮点数3.5
print(float_to_binary(3.5)) # 输出:01000000111000000000000000000000
🔵 6.2.3 定点数和浮点数的比较
特性 | 定点数 | 浮点数 |
---|---|---|
范围 | 固定,需手动扩展位数 | 范围大,自动适应大小 |
精度 | 固定小数位 | 尾数决定精度 |
硬件复杂度 | 低 | 高(需阶码对齐逻辑) |
🔵 6.2.4 举例
场景:计算1000.5 + 0.25
(浮点运算)
- 对阶:
0.25
阶码提升至与1000.5
相同 - 尾数相加:
1.0000000001
+0.00000000001
=1.00000000011
- 规格化:结果为
1.00000000011 × 2^10
🔵 6.2.5 IEEE 754 标准
单精度(32 位):
- 符号位:1 位
- 阶码:8 位(偏移量 127)
- 尾数:23 位(隐含最高位 1)
6.3 定点运算
🔵 6.3.1 移位运算
逻辑移位:无符号数移位,空位补 0。
算术移位:有符号数移位,符号位不变,负数补 1。
Java 代码:算术右移模拟
public class ShiftOperation {public static void arithmeticShiftRight(int num, int bits) {int sign = num >> 31; // 取符号位for (int i = 0; i < bits; i++) {num = (num >> 1) | (sign << 31); // 符号位填充}System.out.println("算术右移结果:" + num);}
}
🔵 6.3.2 加法与减法运算
补码加法:[A+B]补 = [A]补 + [B]补
Python 实现:补码加法(处理溢出)
def twos_complement_add(a, b, bits=8):"""补码加法,返回结果及溢出标志"""sum_val = a + bmask = (1 << bits) - 1overflow = (sum_val & (1 << (bits-1))) != ((a & (1 << (bits-1))) ^ (b & (1 << (bits-1))))return sum_val & mask, overflow# 示例:-5 + 3(8位补码)
result, overflow = twos_complement_add(-5, 3)
print(f"结果:{result},溢出:{overflow}") # 输出:-2(补码11111010),无溢出
🔵 6.3.3 乘法运算
原码一位乘:符号位异或,数值位累加移位。
Java 模拟:原码乘法
public class OriginalMultiplication {public static int multiply(int a, int b) {int sign = (a < 0 ^ b < 0) ? -1 : 1; // 符号位long absA = Math.abs((long)a);long absB = Math.abs((long)b);long product = 0;while (absB > 0) {if ((absB & 1) == 1) product += absA;absA <<= 1;absB >>= 1;}return sign == 1 ? (int)product : (int)(-product);}
}
🔵 6.3.4 除法运算
补码不恢复余数法:根据余数符号决定加减除数。
流程图:
🌊 6.4 浮点四则运算
🔵 6.4.1 浮点加减运算
步骤:对阶 → 尾数加减 → 规格化 → 舍入 → 溢出判断
代码框架:
class FloatAdder:def add(self, float_a, float_b):# 解析阶码和尾数exp_a, mantissa_a = self.parse_float(float_a)exp_b, mantissa_b = self.parse_float(float_b)# 对阶if exp_a > exp_b:mantissa_b >>= (exp_a - exp_b)else:mantissa_a >>= (exp_b - exp_a)exp_a = exp_b# 尾数相加sum_mantissa = mantissa_a + mantissa_b# 规格化while (sum_mantissa & 0x8000) == 0: # 左规sum_mantissa <<= 1exp_a -= 1while (sum_mantissa & 0x10000): # 右规sum_mantissa >>= 1exp_a += 1return self.pack_float(exp_a, sum_mantissa)
🔵 6.4.2 浮点乘除运算
乘法:尾数相乘,阶码相加;除法:尾数相除,阶码相减。
🔵 6.4.3 浮点运算所需的硬件配置
- 阶码运算单元:处理指数加减
- 尾数运算单元:处理小数乘除
- 移位器:实现对阶和规格化
🤖 6.5 算术逻辑单元
🔵 6.5.1 ALU 电路
功能:实现算术运算(加减乘除)和逻辑运算(与或非异或)。
Verilog 示例:4 位 ALU
module alu (input [3:0] a, b,input [1:0] op, // 00:加 01:减 10:与 11:或output reg [3:0] result,output carry
);always @* begincase(op)2'b00: {carry, result} = a + b;2'b01: {carry, result} = a - b;2'b10: result = a & b;2'b11: result = a | b;default: result = 0;endcase
endendmodule
🔵 6.5.2 快速进位链
原理:提前计算进位生成信号(G)和传递信号(P),减少进位延迟。
📚 总结
本章围绕计算机运算核心,从数的表示(无符号 / 有符号、定点 / 浮点)到具体运算(加减乘除、移位),再到硬件实现(ALU、进位链),完整呈现了计算机运算方法的体系。通过代码示例和图表,可帮助读者深入理解理论并动手实践。
💡 提示:文中代码可在 IDE 中直接运行,建议结合单步调试观察二进制变化,加深对底层运算的理解。