定点c程序之六(完):Q值的选取和动态Q值

from http://www.cnblogs.com/c6000, by  c6000@sina.com

在定点算法实现中,由于数的定标直接影响到运算的精度,因此,确定各个变量的Q值非常重要.当Q值选得过大时,可能导致变量取值超出其所能表示得范围而导致失真;当Q值选得过小时,又会因为其所能表示的精度太低达不到较好的算法性能。

确定Q值的问题实际上就是要确定变量的动态范围。

设变量的最大绝对值为|max|,取一个整数n,使其满足

  2^(n-1)< |max|<2^(n)

  则有

  2^(-Q)=2^(-15)×2^n=2^(-(15-n))

  Q = 15 – n

例如,

变量的取值在-3~+3之间,n=2,Q=15-n=13

那么,当x=2.5时,表示为010.1 0000 0000 0000 = 5000H

于是,Q值的确定转化为变量的最大绝对值取值的确定,传统上主要采用两种方法

理论分析法:通过数学理论分析确定,例如:

三角函数sin(x)/cos(x),其取值小于1,因此,可以用Q15表示。
 
统计分析法:对于无法用理论分析确定的变量,应该采用统计分析的方法来确定其适当的Q值。

所谓统计分析方法,就是用足够多的输入信号样值来确定程序中的变量的动态范围。统计分析的结果依赖于两个因素:一是输入的样值是否足够多;二是输入的样值是否遍历各种可能的取值范围。

动态Q值方法:

下面举例来说明。

定点C程序实现一例
  互相关:   

               x = {x(0),x(1),x(2)….x(n-1)}

               y = {y(0),y(1),y(2)….y(n-1),y(n), …y(n+m-1)}

               z(0) = x(0)*y(0) + x(1)*y(1)….x(m-1)*y(m-1)

             z(m) = x(0)*y(m-1) + x(1)*y(m)….x(n-1)*y(n+m-1)

  浮点程序:

           float x = {x(0),x(1)….x(n-1)};

           float y = {y(0),y(1)….y(n-1), y(n),…y(n+m-1)};

           float z[ ] = 0;

           short i,j;

           for (i =0; i < m; i++)

                                  for (j =i; j < i+n; j++)

                   z(i) += x(j-i)*y(j); 
 
由于一般的DSP的累加器是32位或者40位,这样如果输入的信号较大或者累计的次数n较大时,都会使得输出z大于32位或者40位,也就是产生溢出.
下面我们讨论几种实现上述功能的定点程序的方法
 
用DSP支持的溢出饱和处理来实现.某些处理器在大于正最大值时就会直接变成负的最小值.使得数据出现临界跳变,而DSP在大于正最大值时,则会自动饱和成正最大值
   Word16 x[ ] = {x(0),x(1)...x(n-1)};

           Word16 y[ ] = {y(0),y(1)….y(n-1), y(n),…y(n+m-1)};

           Word32 z[ ] = 0;

           Word16 i,j;

           for (i =0; i < m; i++)

                     for (j =i; j < i+n; j++)

                    z(i) = L_mac(z(i), x(j-i),y(j));

虽然DSP能保证数据不出现跳变,但是由于大于正最大值的数全都饱和成正最大值了,这样精度就不能保证了.

当然,很多DSP支持超过32位的累加器,比如TI DSP的累加器是40位的,这样直接利用40位的特性也能最大程度的保证信号的精度
 
利用40位特性

Word16 x[ ] = {x(0),x(1)...x(n-1)};

Word16 y[ ] = {y(0),y(1)….y(n-1), y(n),…y(n+m-1)};

Word40 z[ ] = 0;

short i,j;

for (i =0; i < m; i++)

     for (j =i; j < i+n; j++)

            z(i) = L_mac40(z(i), x(j-i),y(j));

下面我们介绍一种方法能够采用动态Q值来保证最后结果的精度

动态Q值方法
  Word16 shift;

  Word32 acc = 0;

  Word16 i = 0;

          for (j =0; j < m; j++){

              acc = (L_mult(x(j),y(j)) >> shift);

              z(0) = L_add(a(0),acc);

              if(z(0) > 0x40000000){

              z(0) = z(0) >>1;

              shift = shift +1;}

}

          for (i =1; i < m; i++)

          for (j =i; j < i+n; j++){

              acc = (L_mult(x(j-i),y(j)) >> shift

              z(i) = L_add(a(i),acc);

}

这种方法能够估计当前输入信号的幅度来调整Q值,就是shift,也就是结果z是Q shift的数.
于是,Q值的确定,可以采用三种方法
•理论分析法:通过数学理论分析确定
•统计分析法:对于无法用理论分析确定的变量,应该采用统计分析的方法来确定其适当的Q值。
•最后一个就是我所介绍的动态Q值的方法


本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/mobileaudio/archive/2010/08/24/5836017.aspx

原文地址:https://www.cnblogs.com/c6000/p/1807695.html