基于FPGA的数字信号处理(4)--浮点数的定点化

写在前面

首先要说明的是,题目《浮点数的定点化》中所谓的 浮点数 并不是指 IEEE754 规定的 单精度浮点数 或者 双精度浮点数 等格式,而是指10进制小数。所以说白了,这篇文章要讲的就是如何将10进制小数采用定点数的形式表示。


为什么2进制无法精准地表示10进制小数?

你在学习进制转换时,有没有关注过这样一个问题:

为什么10进制小数转成2进制小数的题目通常都会规定有效位数?

例如:将10进制数 0.1 转换为 2进制小数,要求小数有效位数为5位。按照转换方法--乘2直到小数部分为0即可。

那么 0.1(D)= 0.0001100110011····,这时你就会发现,这个乘法过程似乎可以一直持续下去,但是好在题目只要求到小数点后5位,所以结果是 0.00011。

这能说明一个问题:10进制数 0.1 没办法被2进制精准地表示。不过某些小数,在特定的位宽下是可以被2进制精准表示的,比如:

0.5(D)= 0.1(B)

0.25(D)= 0.01(B)

0.875(D)= 0.111(B)

Why?

整数的2进制表示却没有这个问题,只要不限制位宽,那10进制整数一定可以被2进制精准表示,比如:

17(D)用4位2进制数无法表示,因为它的最大范围是4'b1111即15,但可以被5位及更多位的2进制数表示。

关于这一点可以从两个方面去理解:

  1. 整数是离散的,在固定范围内整数的个数是固定的,比如在0~15范围内那必然只有16个整数;而小数是连续的,在固定范围内小数的个数是无限。不管采用定点数还是浮点数的形式,那都是在用有限的编码个数来表示无限的小数,所以某些小数必然无法精准表示。
  2. 2进制整数的最小单位是最低位,即10进制的 "1",所以整串数字可以看做是数个 "1" 的和,而显然任何整数都可以被 "1" 整除。但小数的2进制表示的最小单位是随着位宽而变化的,比如1位小数的最小单位是0.5,2位小数是0.25。所以不管是几位小数,这些 "最小单位" 都无法做到能整除所有小数。

至此,可以得出结论:并非所有的10进制小数,都可以被2进制数精确表示,在这个进制转换的过程中某些小数一定会存在误差。


浮点数到定点数

将浮点数转为定点数,也叫做 浮点数的定点化。

定点化首先需要约定好定点数的规格:**用几位表示整数,用几位表示小数,要不要表示符号位?**这些规格需要根据输入数据的范围和特性而定(这些往往在算法阶段确定)。

假如要输入的数据 a 的范围在 -9~5 之间,要求精度保留5位。那么绝对值最大的| -9 |至少需要用4位(1001)才能表示,所以整数部分为4位。综上,数据 a 的定点化规格应为:符号位1位,整数部分4位,小数部分5位,共10位。

假设a的一个值是 3.1415,那么它的定点化过程如下:

  1. 小数部分5位,则分辨率为2 ^ -5=0.03125。3.1415转化为2进制小数相当于在算需要多少个分辨率小数来表示它,所以转化过程为 3.1415 / 2 ^ -5 = 3.1415 × 2 ^ 5 = 100.528。
  2. 这个结果只能取整数部分,因为二进制小数相对其分辨率来说,只能表示整数个。例如两位小数的分辨率是1/4 = 0.25,那么 0.00-0.11(B)就分别表示0.01(B)即0.25(D)的0-3倍,即0、0.25、0.5、0.75。
  3. 取整的方法有两种:
    1. 直接截去小数部分(truncate),这相当于数学上的向下取整(floor),就电路设计角度而言,截去的实现是很简单的,所以这种方法最为常用;
    2. 四舍五入(round),这样产生的误差比直接截断的误差小,但是需要多余的电路来实现,因此不太常用。
  4. 将结果100.528的小数部分截掉,为 100(D),可以理解为需要100个0.03125才能表示,即3.1415(D) = 100(D) × 0.00001(B),所以只要将100转化为2进制表示即可,即100(D)= 1100100(B)。因为设计的位宽是10位,所以需要补上符号位和在整数部分的高位补0,即最终结果为 0_0011_00100 。

0_0011_00100表示的值为 +3.125,它和原始数之间的差值就是 量化误差,为|3.125 - 3.1415| = 0.0165。量化误差是在量化过程中因为截断或四舍五入所直接产生的,但本质上还是因为有限个2进制编码无法表示无穷个10进制小数。

浮点数乘以2^Q,然后四舍五入或截去小数,就是定点数。其中Q为定标值(以确定小数位数)。


定点数到浮点数

还是要先说明,这个浮点数不是IEEE754规定的浮点数,仅指10进制小数,显然这就是定点化的逆过程。以 定点数0_0011_00100 的转换为例:

  • 首先需要确定该定点数的规格,假设其规格如下:1位符号位 + 4位整数部分 + 5位小数部分
  • 符号位为0说明这是一个正数
  • 整数部分的值为0011,即10进制的3
  • 小数部分的值为00100,即10进制的0.125(可以理解为0.03125×4)
  • 综合起来的结果就是 +3.125

整个过程相对简单,只要将整数部分和小数部分分别从2进制转换为10进制,再结合起来即可。

相关推荐
Hello-FPGA14 小时前
基于RFSOC FPGA ZCU216 的CoaXPress 采集demo
fpga开发
9527华安16 小时前
FPGA基于ADV7182解码PAL视频,Video Processing Subsystem去隔行,提供6套工程源码和技术支持
fpga开发·音视频·pal·adv7182
hahaha601616 小时前
数字图像时域滤波或者3D降噪算法FPGA实现
算法·计算机视觉·fpga开发
GateWorld16 小时前
Xilinx 7系列FPGA时钟网络详解
fpga开发·时钟网络·xilinx 7系列
szxinmai主板定制专家1 天前
X86 工控机 vs RK3588 异构主控:AMR 控制器 BOM、散热、长期运维对比
运维·stm32·单片机·嵌入式硬件·fpga开发·am62x
szxinmai主板定制专家2 天前
AMR 项目落地:机器人控制器硬件定制化需求复盘
arm开发·单片机·fpga开发·系统架构·机器人·am62x
日晨难再2 天前
SDC命令详解:使用all_fanin命令进行查询
数字ic
FPGA小迷弟3 天前
FPGA 与卫星:从星载硬件到在轨智能的完整技术解析
fpga开发·架构·fpga·1024程序员节·无线电
NamoAmitabha1283 天前
CPU 内部结构是什么?---deepseek
fpga开发
abc light3 天前
ARM 裸机开发(6)——时钟树与定时器
arm开发·单片机·fpga开发