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

devtools/2025/3/22 13:13:00/

简介

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

  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

舍入判断函数

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 Nonequotient = (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 = 0remainder = 0for 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. 余数恢复:当余数不够减时恢复原值

不恢复余数除法

def non_restoring_division(dividend, divisor):remainder = 0sign = 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 += divisorsign = -1if remainder < 0:remainder += divisor  # 最终余数修正if need_round_up(remainder, divisor):q += 1return 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 Nonequotient = dividend * _lut[divisor]return round_half_up(quotient * (1 << 8))
  • 预计算优化
    • LUT存储除数倒数
    • 避免实时计算倒数
  • 限制条件
    • 仅支持1-255的除数
    • 依赖浮点运算精度

二分法

def binary_bit_division(dividend, divisor):a = dividend << 9  # 扩展9位空间q = 0remainder = 0for i in range(17):  # 17位精度bit = (a >> (16 - i)) & 0x1   #依次从高到底提取对应位remainder = (remainder << 1) | bit #将提取的位数加到余数上if remainder >= divisor:q |= 1 << (16 - i)  #设置商位remainder -= divisorq = (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 * xreturn round_half_up(quotient * (1 << 8))
  • 数值分析
    • 初始值:x₀ = 1/divisor
    • 迭代公式:xₙ₊₁ = xₙ(2 - D·xₙ)
    • 平方收敛:每次迭代精确位数翻倍
  • 安全措施
    • max(divisor, 1e-9) 避免除零
    • 4次迭代可达单精度浮点精度

http://www.ppmy.cn/devtools/169155.html

相关文章

使用 Tkinter 编写简单计算器应用

在本篇博客中&#xff0c;我们将介绍如何使用 Python 的 Tkinter 库来编写一个简单的计算器应用。通过这个项目&#xff0c;你可以学到如何设计 GUI 界面、布局各个组件以及实现事件驱动编程思想。 一、项目需求分析 首先&#xff0c;我们需要明确项目的基本需求&#xff1a;…

jaeger安装和简单使用

文章目录 jaeger安装和使用什么是jaegerjaeger安装 jaeger安装和使用 什么是jaeger 官网&#xff1a;https://www.jaegertracing.io/ Jaeger 是一个分布式追踪系统。Jaeger的灵感来自 Dapper 和 OpenZipkin&#xff0c;是一个由 Uber 创建并捐赠给 云原生计算基金会&#xf…

DeepSeek R1 本地部署指南 (3) - 更换本地部署模型 Windows/macOS 通用

0.准备 完成 Windows 或 macOS 安装&#xff1a; DeepSeek R1 本地部署指南 (1) - Windows 本地部署-CSDN博客 DeepSeek R1 本地部署指南 (2) - macOS 本地部署-CSDN博客 以下内容 Windows 和 macOS 命令执行相同&#xff1a; Windows 管理员启动&#xff1a;命令提示符 CMD ma…

Nexus L2 L3基本配置

接口基本配置 N7K上所有端口默认处于shutdown状态; N5K上所有端口默认处于no shutdown状态(所有端口都是switchport) 默认所有接口都是三层route模式, 只有当线卡不支持三层的时候, 接口才会处于二层switchport模式 show run all | in “system default” 创建SVI口需要提前打…

【leetcode hot 100 17】电话号码的字母组合

分析&#xff1a;当设计关键字“所有组合”时&#xff0c;要考虑深度优先遍历、广度优先遍历&#xff08;层次遍历&#xff09;&#xff0c;其中&#xff1a; 深度优先搜索&#xff1a; 自顶向下的递归实现深搜定义子问题在当前递归层结合子问题结果解决原问题 广度优先搜索 利…

AtCoderABC387题解

A题 链接 题目大意&#xff1a;给你AB&#xff0c;求&#xff0c;直接上代码&#xff01; #include<iostream> using namespace std;signed main() {int a,b;cin>>a>>b;cout<<(ab)*(ab);return 0; } B题 链接 给你一个列表&#xff0c;第行第列的…

Linux--软硬链接、动静态库

一、深刻理解软硬链接 在Linux中&#xff0c;链接是一种将文件或者目录连接到其他位置的方法&#xff0c;分为硬链接和软链接。 硬链接&#xff1a;硬链接是通过在文件系统中创建一个新的文件&#xff0c;该文件与原文件共享相同的 inode&#xff08;索引节点&#xff09;。in…

IRF拆除

冗余口、冗余组、备份组、虚墙、MAD检测、被控制器纳管、转换为安全策略 黑洞路由的定义: 有来无回的路由。 对设备拆除IRF操作流程。 1、关闭主框的业务口&#xff08;对设备的接口使用shutdown&#xff09;&#xff0c;关闭MAD检测口&#xff08;BFD/NQA/MAD&#xff09;&…