《计算机组成原理》第 6 章 - 计算机的运算方法

发布于:2025-05-29 ⋅ 阅读:(23) ⋅ 点赞:(0)

目录

🔢 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.671875
        int product = a * b; // 直接整数乘法
        int shift = 8; // 小数点后总位数(假设各4位)
        int result = product >>> shift; // 右移取整数部分(逻辑右移)
        System.out.println("定点乘积补码:" + Integer.toBinaryString(result));
    }
}

🔵 6.2.2 浮点表示

结构:阶码(指数)+ 尾数(小数),如:
浮点数 = 尾数 × 基数^阶码
代码示例:IEEE 754 单精度浮点数解析

import struct

def 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(浮点运算)

  1. 对阶:0.25阶码提升至与1000.5相同
  2. 尾数相加:1.0000000001 + 0.00000000001 = 1.00000000011
  3. 规格化:结果为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 + b
    mask = (1 << bits) - 1
    overflow = (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 <<= 1
            exp_a -= 1
        while (sum_mantissa & 0x10000):     # 右规
            sum_mantissa >>= 1
            exp_a += 1
        
        return 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 @* begin
    case(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
end

endmodule

🔵 6.5.2 快速进位链

原理:提前计算进位生成信号(G)和传递信号(P),减少进位延迟。

📚 总结

   本章围绕计算机运算核心,从数的表示(无符号 / 有符号、定点 / 浮点)到具体运算(加减乘除、移位),再到硬件实现(ALU、进位链),完整呈现了计算机运算方法的体系。通过代码示例和图表,可帮助读者深入理解理论并动手实践。

   💡 提示:文中代码可在 IDE 中直接运行,建议结合单步调试观察二进制变化,加深对底层运算的理解。


网站公告

今日签到

点亮在社区的每一天
去签到