DSP数的表示:定点小数Q 格式表示和加法
定点表示是的我们可以在低开销的整数硬件上使用小数运算。本文首先介绍小数表示方法Q格式,然后给一些定点加法的例子。
在低开销DSP上表示小数
为了降低开销,很多数字信号处理器都设计成只能进行整数算术运算。为了在这些处理器上表示小数,我们可以使用隐含小数点。
例如,8bit字
a=010101102
a
=
01010110
2
,单被当做整数时表示
8610
86
1
0
。然而,我们可以假设存在一个隐含的小数点,并把该数理解为一个小数。假设小数点在第4和第5个bit之间,例如,
a=0101.01102
a
=
0101.0110
2
。我们可以通过以下公式得到该数等价的十进制的值:
a=0×23+1×22+0×21+1×20+0×2−1+1×2−2+1×2−3+0×2−4=5.375
a
=
0
×
2
3
+
1
×
2
2
+
0
×
2
1
+
1
×
2
0
+
0
×
2
−
1
+
1
×
2
−
2
+
1
×
2
−
3
+
0
×
2
−
4
=
5.375
在这个例子中,我们用4bit表示整数部分,4bit表示小数部分。
从这个例子我们可以看到,小数点右边第一个bit的系数为0.5,第二个为0.25,以此类推。需要注意这个隐含的小数点并没有在硬件上表达,程序猿需要假设一个合适的缩放因子来正确的解释计算结果。在上面的例子中,硬件上只存储8bit数
a=010101102
a
=
01010110
2
。如果程序员想要用a表示5.375,就需要记住使用a进行的任何运算结果,都需要乘以一个缩放因子
2−4
2
−
4
。
Q格式
小数点位置不同,同一个二进制数可以表示不同的值。为了编程方便,我们通常在同一算法中使用固定的小数点位置。Q格式是用来表达一个二进制数中整数、小数分别有多少bit的一种表示格式。例如,我们用3bit表述整数部分,4bit表示小数部分,则这个数的格式为Q3.4格式。
对于一个字长固定的处理器,另一种可行的表示格式是只表示小数部分。例如,当我们使用一个字长为16bit的处理器的时候,我们可以简单是说我们是使用Q15格式来表示小数。这里的Q15表示小数点右边有15bit,左边有1bit。同时Q15也等效于Q1.15。
小数点位置选择
小数点位置的选取需要考虑两个方面:
- 算法中需要表示的最大值
- 可允许最大的量化噪声
第一个方面决定了整数部分需要的bit数,第二个方面决定了小数部分的bit数。
需要注意的是,除了隐含的缩放因子,Q格式的小数与计算机上整数的表示没有任何区别。我们也可以使用Q格式来表示二进制补码。
Q格式举例
例一
假设算法需要用到浮点数
a=9.21695743609119810
a
=
9.216957436091198
10
。现在该值在浮点表示时算法表现良好。假设我们要用16bit字长的定点硬件来实现该算法,最合适的表示a的Q格式是什么?
因为a的整数部分在8和16之间,因此我们至少需要4bit来表示整数部分。假设我们使用有符号数,那么符号位需要占用以为,即小数点左边有5bit。因此我们使用Q5.11格式。
改格式表示的数的缩放因子为
2−11
2
−
11
。也就是说Q5.11形式表示的a对应的去掉小数点后的值等于Q5.11表示的数乘以
211
2
11
。因此,为了将a表示为Q5.11格式,我们先将a乘以
211
2
11
,对其四舍五入到最接近的整数,然后在将四舍五入结果转换为二进制:
a×211=18876.3288≈18876=100100110111100(2)
a
×
2
11
=
18876.3288
≈
18876
=
100
1001
1011
1100
(
2
)
因为a是正数,因此符号位为0,a的Q5.11格式表示为01001.00110111100。对于负数,我们需要首先找到其绝对值的Q格式表示,然后转换为二进制补码,再加上符号位。
例二
假设
a=10.012
a
=
10.01
2
为Q2.2格式的有符号数,其对应的十进制整数是什么?
因为是有符号数,所以十进制数为-1乘以a的二进制补码对应的十进制数。a的二进制补码为 01.112 01.11 2 。因此 a=−1.7510 a = − 1.75 10 。
符号扩展
在做有符号数加法的时候,加数与被加数长度可能不同,这是,我们需要将较短的数进行符号位扩展。
例如,将
10112
1011
2
扩展两位,得到
1110112
111011
2
。对于正数来说,符号位为0,符号扩展即填零,这不会改变数的大小。
对于负数来说,在补码表示中,一个负数是依据一个互补的常数定义的。kbit的数,这个互补常数为
M=2k
M
=
2
k
。
对于一个4bit的数,互补常数为
M=24
M
=
2
4
,这时,一个4bit正数b对应的负数-b可以表示为M-b。下面解释如何用6bit表示这个4bit有符号数。
对于6bit数,互补常数为
M′=26
M
′
=
2
6
,-b可以表示为
M′−b
M
′
−
b
。因此,-b的6bit表示和4bit表示的差为:
(M′−b)−(M−b)=M′−M=26−24=01100002
(
M
′
−
b
)
−
(
M
−
b
)
=
M
′
−
M
=
2
6
−
2
4
=
0110000
2
。这就表示,为了用6bit表示一个4bit有符号负数,我们只需要在4bit表示上加上
01100002
0110000
2
,也就是将符号位扩展两位。通过符号位扩展,我们只改变了负数的互补常量,负数本身并没有变。
Q格式加法
对Q格式两个数相加时,首先需要完成小数点对其和符号位扩展。
例三
计算a+b,其中a=-1.25(补码表示为
10.112
10.11
2
),b=+3.25(补码表示为
011.0102
011.010
2
)。
a和b分别为Q2.2和Q3.3格式。首先需要进行小数点对其,然后将整数部分较短的数进行符号位扩展,最后再进行运算:
除了隐含的缩放因子,以上加法和整数补码加法一样。因为补码运算是模M运算。因此我们需要将符号位左边的数都忽略掉。因此
a+b=010.0002=+210
a
+
b
=
010.000
2
=
+
2
10
。这里需要注意在运算前进行符号位扩展。
在使用定点数运算的时候,我们需要格外小心相应Q格式表示数的范围,防止溢出。
例如,假设a使用Qna.ma格式,b使用Qnb.mb格式。如果使用与上面类似的过程计算,设符号扩展后的结果为Qnc.mc格式,则nc=maximum{na,nb},mc=maximum{ma,mb}。这个时候结果是有可能溢出的。因为Nbit数相加可能会得到(N+1)bit的结果。如果使用Qnc.mc格式表示结果,就需要程序员自己能够确定结果不会溢出。
解决溢出问题的方法有两种:
- 将两个输入缩放
- 使用Q(n+1).m格式的输出可以保证两个Qn.m格式的数相加不会溢出,这时候需要将两个输入在计算的时候也需要同时符号扩展一位。
使用保护位(guard bit)防止溢出
很多数字信号处理器的累加器的输出寄存器通常比输入数据宽几位。这些多出来的数据位叫做保护位(guard bit)。这些保护位可以保证程序员在做累加的时候不会溢出。n个保护位可以保证进行 2n 2 n 次累加不会溢出。
保护位也不是可以无限制添加的,因此累加器的累加次数的有限制的。因此在计算的时候,我们有时候需要对结果进行四舍五入和截断来得到一个较短的数。多次累加后,结果数值范围会变大,为了表示更大的值,需要使用更多的bit来表示整数部分,也就是说我们可能需要改变小数点位置。
总结
- 定点数可以用来表示小数。
- 为了降低实现开销,很多数字信号处理器只支持整数运算。为了在这些处理器中使用小数,需要引入隐含小数点。
- 如果使用n bit来表示整数部分,m bit来表示小数部分,那么这种表示叫做Qn.m格式。
- 做两个有符号数加法的时候,两个数可能长度不同。这是需要将较短的数进行符号位扩展。
- 做两个Q格式数加法的时候,需要遵循如下步骤:对其小数点;对较短的整数部分的数进行符号位扩展;进行加法运算。
- 当使用定点数来做算法实现的时候,必须注意所使用的Q格式能够表示的数的范围。