Post

浮点数运算和二进制编码的十进制数运算

浮点数运算和二进制编码的十进制数运算

回顾:IEEE754浮点数表示

截屏2025-10-09 14.26.36

浮点数加减法

在做加减法的时候,一定要对齐阶码!

对于浮点数的加减法,如果两个浮点数的exponent不一样大,那我是应该把大的阶码调小,还是把小的阶码调大呢?

应该把小的调大!

截屏2025-10-09 14.08.44

步骤一:对阶(Alignment)

目的: 使两个操作数的阶码相同,从而让它们的尾数可以直接相加减。

  1. 比较阶码:比较两个浮点数的阶码 Exponent_AExponent_B
  2. 计算阶差ΔE = |Exponent_A - Exponent_B|
  3. 对阶操作“小阶向大阶看齐”
    • 找出阶码较小的那个数。
    • 小阶码的尾数向右移动 ΔE 位。
    • 同时,将小阶码的值更新为大阶码的值。

为什么这样做?

  • 保护精度:如果大阶向小阶看齐,需要将大阶数的尾数左移,这可能会把重要的高位有效数字移出表示范围,造成巨大误差。而小阶尾数右移仅损失最低位的精度,通过舍入处理可以将影响降到最低。

举例(十进制模拟): 计算 1.234 × 10³ + 5.678 × 10¹

  • 对阶:10¹10³ 看齐,阶差为2。
  • 小阶数尾数右移2位:5.678 × 10¹0.05678 × 10³
  • 现在可以相加:1.234 × 10³ + 0.05678 × 10³

步骤二:尾数求和(Mantissa Addition/Subtraction)

目的: 对对齐后的尾数进行实际的加法或减法运算。

  1. 现在两个数的阶码已经相同,我们直接对它们的尾数(包括隐藏的最高位,即IEEE 754中的“隐含1”)进行二进制加减法。
  2. 结果的阶码暂时等于对阶后的大阶码。

承接上例:

  • 尾数相加:1.234 + 0.05678 = 1.29078
  • 初步结果:1.29078 × 10³

步骤三:规格化(Normalization)

目的: 确保结果符合浮点数的标准格式。在IEEE 754中,规格化数的尾数M必须满足 1.0 ≤ M < 2.0(即二进制下的 1.f... 形式)。

加法后,结果可能出现两种情况:

  1. 尾数 ≥ 2.0(向上溢出)
    • 操作:右规(Right Shift)
    • 将尾数向右移动1位。
    • 阶码加1。
    • 例子: 10.1101 × 2^E → 右移一位 → 1.01101 × 2^(E+1)
  2. 尾数 < 1.0(向下溢出)
    • 操作:左规(Left Shift)
    • 将尾数向左移动,直到最高位为1。
    • 阶码相应地减去移动的位数。
    • 例子: 0.001101 × 2^E → 左移三位 → 1.101000 × 2^(E-3)

承接上例:

  • 我们的结果是 1.29078 × 10³,它满足 1.0 ≤ M < 10(十进制规格化),所以无需规格化。

步骤四:舍入(Rounding)

目的: 在对阶(尾数右移)和右规(尾数右移)的过程中,可能会丢失一些低位数字。舍入就是根据这些丢失的位,按照设定的规则来调整结果的尾数,使其适应有限的尾数位数。

常见的舍入模式:

  • 向最接近的值舍入(Round to Nearest, Ties to Even):这是IEEE 754的默认模式。舍入到最接近的可表示值,当恰好处于中间值时,则向“偶数”那边舍入(即让最低有效位为0)。
  • 向零舍入(Round toward Zero):直接截断多余的位。
  • 向正无穷舍入(Round toward +∞)
  • 向负无穷舍入(Round toward -∞)

舍入可能引发再次规格化!

  • 舍入操作可能导致尾数再次满足 ≥ 2.0< 1.0 的条件,因此可能需要再次执行步骤三的规格化操作。这被称为“舍入后规格化”。

完整示例(二进制)

假设单精度浮点数:A = 0.75 (1.1 × 2^-1)B = 2.5 (1.01 × 2^1) 用IEEE 754表示:

  • A: 0 01111110 10000000000000000000000 (阶码126-127=-1,尾数1.1)
  • B: 0 10000000 01000000000000000000000 (阶码128-127=1,尾数1.01)
  1. 对阶
    • E_A = -1, E_B = 1。 ΔE = 2。
    • A的阶码小,所以A的尾数右移2位:1.1000.01100
    • A的新阶码 = 1。
  2. 尾数求和
    • 现在阶码都是1。尾数相加:1.0100000 (B) + 0.0110000 (A) = 1.1010000
  3. 规格化
    • 结果 1.101 × 2^1 已经是规格化形式,无需处理。
  4. 舍入
    • 尾数 1.101 恰好能精确表示,无需舍入。

最终结果1.101 × 2^1 = 11.01 (二进制) = 3.25 (十进制)。验证:0.75 + 2.5 = 3.25,正确。

浮点数乘法

截屏2025-10-09 14.34.37

浮点数除法

截屏2025-10-09 14.37.14

保护位只能解决舍入误差,不能解决表示误差

二进制编码的十进制数加减法

加法

截屏2025-10-09 14.50.54

+6本质上是为了弥补十六进制表示十进制的缺陷

硬件实现:当值在[10,19]范围内时,需要对结果进行调整

截屏2025-10-09 15.11.51

减法

截屏2025-10-09 15.14.41

This post is licensed under CC BY 4.0 by the author.

Trending Tags