嵌入式编程中,你应该知道的定点化知识

谈到这个话题,有必要先介绍下“浮点数”和“定点数”这两个名词的概念。

1.25 + (-2.75) = ?                                                                (1)
上面这个算式我们心算就能轻松得出结果,同样的算式,交给单片机来完成,它要大致分解为下面三个计算步骤:
1)加载操作数(也就是1.25和2.75);
2)做加法运算;
3)返回结果。

对于真实的单片机世界而言,它只有0和1组成的bits。整数好办,直接将十进制数转化为二进制数形式进行运算就好,但面对小数,该如何来表示数中的小数点呢?这便引出了数的浮点和定点表示。

对于一个“有符号数”而言,它的浮点表示由三部分组成,如图1,一个32位的浮点数示例:

图1 32bit有符号数浮点组成示例

• 符号位:0表示正数,1表示负数。
• 指数部分:类似于科学技术法中的M*10^N中的N,只不过这里是以2为底数而不是10。
• 基数部分:浮点数具体数值的实际表示,类似于科学计数法中的M。
详细了解数的浮点表示细节,可查看参考资料【1】。

对于同样一个数,它的定点表示也由三部分组成:
嵌入式编程中,你应该知道的定点化知识_第1张图片
图2 32bit有符号数浮点组成示例

• 符号位:0表示正数,1表示负数。
• 整数部分:小数点左边的数。
• 小数部分:小数点右边的数。

但计算机它并不直接区分定点数的整数和小数部分,需要程序设计者进行“人为”的定标(这里的“人为”实际上不靠任何真实操作,你可以理解为靠意念)。

对于不同的数,定标可以不一样,通常用Q来表示定标值,如图2的定标为Q23。同样,我们也可以把一个数定标为Q22、Q12等等。


“浮点”与“定点”之于单片机
根据自身硬件的不同,有些单片机支持浮点数运算,有些则只支持定点数运算。市面上大部分的单片机都是定点单片机,只有一些对数据处理要求比较高的单片机才会集成浮点处理单元。

一般而言:
浮点单片机便于浮点编程,省去了人为定标的麻烦,而且同样的位数,浮点可以表示更大范围内的数。但浮点单片机硬件复杂、功耗更大,价格也会相应高些;

定点单片机的定点运算处理效率比浮点运算要高,但因为需要人为地给各个数据定标,也带来了程序设计中的“定点化”问题。

定点化编程
在工程实践中,开发信号处理算法一般遵循下面的流程:

嵌入式编程中,你应该知道的定点化知识_第2张图片

图3 工程中算法开发流程

程序定点化之后,由于定点数据的精度限制,会存在定点误差,其运算结果可能会与Matlab的仿真结果产生一定的偏差。选择合适的定标值,以确保运算结果在符合应用要求的范围之内,这是定点化过程中最重要也是最难的一个问题。

据AccelChip 公司所做的一次调查显示,53% 的回答者认为浮点定点转换是在FPGA上实现算法时最困难的地方。而实际上我认为,定点化充其量只是过程显得繁琐一些,其中的规律还是比较简单的。下面还是以最开始的那个算式为例,来解释定点化过程中会面临的一些问题。

1. 选取合适的定标值(加载操作数)
定标的大小,影响着整数部分和小数部分的位数,定标的过程其实是在操作数动态范围和精度之间做权衡的过程。

设一个变量可能出现的最大绝对值为|max|,n为正整数,满足2^(n-1) < |max| < 2^n,则定标Q按如下规则选取最合适:

Q = 有效数据位 – n

对于32位的有符号数,数据有效位=31。如|max| = 2.75,选Q = 31 – 2 =29是最合适的。

2. 定点数之间的运算
两个定点数进行运算,它们的定标可能相同也可能不同,那该遵循怎样的规则来进行加减乘除等基本运算呢?

网上有些资料通过分别举加、减、乘、除实际运算的例子来说明这一问题,虽然很详细,但还是不够直观。

来看一看,平时我们用十进制做两个数的加减和乘除是怎么弄的。

加减法:先对位,后加减;
乘除法:先乘除,后取小数点。

而定点数之间的加减乘除,撇开符号位不谈,其过程是一样一样的:

加减法:先对标,后加减;
乘除法:先乘除,后定标。

大家可以仔细体会下这里的意思,然后再找具体的例子对照感受下,看是不是觉得简单多了呢。

3. 结果重新定标(返回结果)
两个定点数运算完成之后,所得结果的定标、动态范围、精度要求等都可能发生了变化,因此可能需要进行重新定标。

比如Q15*Q15 -> Q30,但我们依然希望得到一个Q15的数怎么办?其实只需做一个简单的右移15位操作就好,其它情况同理。

另一些探讨
• 浮点芯片均能支持定点运算,只是在一般定点芯片的基础上添加了额外的浮点处理硬件单元和指令,使得芯片得以支持快速的浮点运算。

• 定点芯片支持浮点运算吗?答案也是肯定的!我记得在本科的时候用STM32进行编程时,当时还没有对定点编程的概念,直接在程序中就用float来表示小数并进行运算了,结果也是正确的,但它确实是定点芯片呀?真实的情况是,很多编译器都为定点芯片提供了相应的浮点处理库,通过软件的方式同样来支持float型变量的操作。但这样做会使计算变得很低效,在实时性要求高的情况下,定点化依然是必不可少的一环。

参考文献/资料
【1】你应该知道的浮点数基础知识--卢钧轶的博客
【2】DSP芯片的定点运算 -- 新浪爱问
【3】DSP编程技巧之22---详解浮点运算的定点编程

·END·


想进一步跟踪本博客动态,欢迎关注我的个人微信订阅号:信号君


郑重·专业·有料



你可能感兴趣的:(编程)