目录
🔢 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
(浮点运算)
- 对阶:
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 + 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 中直接运行,建议结合单步调试观察二进制变化,加深对底层运算的理解。