定点除法器设计与实现:从基础算法到数值优化

简介

本文系统性地探讨了六种典型除法器实现方案,涵盖硬件级位操作算法与数值优化方法,重点解决定点数处理中的精度控制与舍入误差问题。主要内容包括:

  1. 硬件级算法实现

  2. 高性能优化方案

  3. 位扩展技巧:

文档提供可直接运行的Python参考实现,位操作可视化说明和算法复杂度分析,适合嵌入式系统开发者、硬件算法工程师及对数值计算感兴趣的研究人员参考。

:输入为S0I8F0定点数格式(无符号8位整数)

输出为S0I8F8定点数格式(无符号8位整数,8位小数)

基础处理

四舍五入函数

python 复制代码
def round_half_up(x):
    return int(math.floor(x + 0.5))
  • 设计目的:解决Python原生round()函数的"bankers rounding"问题(0.5舍入到最近的偶数)

  • 实现原理

    • x + 0.5:将小数点后第一位>=5的值向上提升

    • math.floor():向下取整实现传统四舍五入

  • 示例

    • round_half_up(1.5) → 2
      • round_half_up(2.5) → 3

舍入判断函数

py 复制代码
def need_round_up(remainder, divisor):
    return remainder * 2 >= divisor
  • 数学原理
    • 当余数 ≥ divisor/2 时满足四舍五入条件
    • 等价于比较:remainder ≥ divisor//2 (整数除法)
  • 避免浮点运算:用乘法代替除法比较

全精度基础除法

python 复制代码
def full_precision_divide(dividend, divisor):
    if divisor == 0:
        return None
    quotient = (dividend / divisor) * (1 << 8)
    return round_half_up(quotient)
  • 数据格式转换
    • dividend / divisor:得到标准浮点商
    • * (1 << 8):转换为S0I8F8格式(乘以256)
  • 错误处理:显式检查除零错误

恢复余数除法

python 复制代码
def restoring_remainder_division(dividend, divisor):
    a = dividend << 8  # 扩展小数位
    q = 0
    remainder = 0
    
    for i in range(16):  # 处理16位小数
        bit_pos = 15 - i  # 从高位到低位
        #余数左移1位,腾出低位;将被除数当前位(bit_pos)的值加入余数的最低位
        remainder = (remainder << 1) | ((a >> bit_pos) & 1) 
        if remainder >= divisor:
            q |= 1 << bit_pos  # 设置商位
            remainder -= divisor  # 恢复余数
            
    if need_round_up(remainder, divisor):
        q += 1  # 四舍五入
        
    return q
  • 硬件算法模拟
    1. 位扩展dividend << 8 将整数转换为Q8格式定点数
    2. 循环处理:16次迭代对应8位整数+8位小数
    3. 位提取(a >> bit_pos) & 1 按位获取被除数
    4. 余数恢复:当余数不够减时恢复原值

不恢复余数除法

py 复制代码
def non_restoring_division(dividend, divisor):
    remainder = 0
    sign = 1  # 余数符号
    
    for i in range(16):
        remainder = (remainder << 1) | ((a >> (15 - i)) & 1)
        
        if sign == 1:
            if remainder >= divisor: #余数大于被除数
                q |= 1 << (15 - i)   #设置商位
                remainder -= divisor #更新余数
                sign = 1             # 余数为正
            else:
                sign = 1  # 保持正号
        else:
            if remainder + divisor <= 0:  # 负余数处理
                q |= 1 << (15 - i)
                remainder += divisor
                sign = -1
                
    if remainder < 0:
        remainder += divisor  # 最终余数修正
        
    if need_round_up(remainder, divisor):
        q += 1
    
    return q
  • 关键差异
    • 允许余数为负
    • 根据余数符号选择加/减操作
    • 最终需要修正余数符号

LUT

python 复制代码
_lut = {d: 1.0 / d for d in range(1, 256)}

def lut_division(dividend, divisor):
    if divisor not in _lut:
        return None
    quotient = dividend * _lut[divisor]
    return round_half_up(quotient * (1 << 8))
  • 预计算优化
    • LUT存储除数倒数
    • 避免实时计算倒数
  • 限制条件
    • 仅支持1-255的除数
    • 依赖浮点运算精度

二分法

py 复制代码
def binary_bit_division(dividend, divisor):
    a = dividend << 9  # 扩展9位空间
    q = 0
    remainder = 0
    
    for i in range(17):  # 17位精度
        bit = (a >> (16 - i)) & 0x1   #依次从高到底提取对应位
        remainder = (remainder << 1) | bit #将提取的位数加到余数上
        
        if remainder >= divisor:
            q |= 1 << (16 - i)  #设置商位
            remainder -= divisor
    
    q = (q >> 1) + (q & 0x1)  # 右移1位后,若最低位为1则加1,舍入处理
    return q
  • 精度扩展设计
    • <<9 提供1位保护位(guard bit)
    • 17次循环计算17位中间结果
  • 舍入技巧
    • q >> 1:舍弃保护位
    • + (q & 0x1):根据保护位决定是否进位

牛顿-拉夫逊迭代法

python 复制代码
def newton_raphson_division(dividend, divisor, iterations=4):
    x = 1.0 / max(divisor, 1e-9)  # 防止除零
    for _ in range(iterations):
        x *= 2 - divisor * x  # 迭代公式
    quotient = dividend * x
    return round_half_up(quotient * (1 << 8))
  • 数值分析
    • 初始值:x₀ = 1/divisor
    • 迭代公式:xₙ₊₁ = xₙ(2 - D·xₙ)
    • 平方收敛:每次迭代精确位数翻倍
  • 安全措施
    • max(divisor, 1e-9) 避免除零
    • 4次迭代可达单精度浮点精度
相关推荐
Naylor几秒前
微服务概述
微服务·架构·springcloud
程序员三藏3 分钟前
软件测试之功能测试详解
自动化测试·软件测试·python·功能测试·测试工具·职场和发展·测试用例
辰%4 分钟前
如何重启pycharm中的项目?
windows·python·pycharm
weloveut5 分钟前
西门子WinCC Unified PC的GraphQL使用手册
后端·python·graphql
<但凡.26 分钟前
C++修炼:多态
开发语言·c++·算法
买了一束花32 分钟前
数据预处理之数据平滑处理详解
开发语言·人工智能·算法·matlab
秭霏鱼33 分钟前
Python+大模型 day01
开发语言·python
YuforiaCode39 分钟前
LeetCode 热题 100 35.搜索插入位置
数据结构·算法·leetcode
yanyanwenmeng1 小时前
智能体制作学习笔记2——情感客服
笔记·学习
学地理的小胖砸1 小时前
【Python 异常处理】
开发语言·python