zoukankan      html  css  js  c++  java
  • 定点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

  • 相关阅读:
    shell 使用Seq算出1-100的奇数之和
    Shell脚本判断是否是闰年
    shell脚本之使用bc工具实现数值转换(浮点转二进制)
    shell脚本之函数的参数
    shell脚本之while
    大数据JAVA基础第十六天
    大数据JAVA基础第十五天
    大数据JAVA基础第十四天
    大数据JAVA基础第十三天
    大数据JAVA基础第十二天
  • 原文地址:https://www.cnblogs.com/c6000/p/1807695.html
Copyright © 2011-2022 走看看