DSP定点数的计算规则和示例

目录

1. Q/S表示法的数值范围

2. 定点化加减法计算规则

2.1 防溢出处理

3. 定点化乘法计算规则

3.1 推算

4. 定点化除法计算规则

4.1 推算

5. 程序代码中如何确定Q值

6. 浮点转定点计算示例


1. Q/S表示法的数值范围

Q表示法

S表示法

数的范围

Q15

S0.15

-1≤X≤0.9999695

Q14

S1.14

-2≤X≤1.9999390

Q13

S2.13

-4≤X≤3.9998779

Q12

S3.12

-8≤X≤7.9997559

Q11

S4.11

-16≤X≤15.9995117

Q10

S5.10

-32≤X≤31.9990234

Q9

S6.9

-64≤X≤63.9980469

Q8

S7.8

-128≤X≤127.9960938

Q7

S8.7

-256≤X≤255.9921875

Q6

S9.6

-512≤X≤511.9804375

Q5

S10.5

-1024≤X≤1023.96875

Q4

S11.4

-2048≤X≤2047.9375

Q3

S12.3

-4096≤X≤4095.875

Q2

S13.2

-8192≤X≤8191.75

Q1

S14.1

-16384≤X≤16383.5

Q0

S15.0

-32768≤X≤32767

注:

DSP定点数的计算规则和示例_第1张图片

2. 定点化加减法计算规则

加减法,首先要做的是对标,也就是Q值相同才能进行加减法。

(1)加法

如果两个参与运算的加数Q值不同,则首先要进行小数点的调整,数学表达式推算:

DSP定点数的计算规则和示例_第2张图片

 故定点加法的伪代码描述如下:

Int x,y,z;

Long temp;

Temp=y<<(Qx-Qy);

Temp=x+temp;

If(Qx≥Qz)

z=(int)(temp>>( Qx- Qz))

else if(Qx≤Qz)

z=(int)(temp<<( Qz- Qx))

else

示例代码:

#include 
#include 
#define Q15 32768.0
#define Q13 8192.0

int main()
{
	float x=0.5;
	float y=3.1; //结果3.6-->Q13

	short x_Qx=(short)(x*Q15+0.5);
	short y_Qx=(short)(y*Q13+0.5);
	short z_Q13;

//	printf("%d\n", x_Qx);
//	printf("%d\n", y_Qx);
	long temp;
	temp=y_Qx<<2;
	temp=temp+x_Qx; 
	z_Q13=(int)(temp>>2);
	printf("res:%f\n", z_Q13/Q13);

    return 0;
}

结果:res:3.599976

(2)减法

代码示例

#include 
#include 
#define Q15 32768.0
#define Q13 8192.0

int main()
{
	float x=3.0;
	float y=3.1; //结果x-y=-0.1-->Q15

	short x_Qx=(short)(x*Q13+0.5);
	short y_Qx=(short)(y*Q13+0.5);
	short z_Q15;

//	printf("%d\n", x_Qx);
//	printf("%d\n", y_Qx);
	long temp;
	temp=x_Qx-y_Qx; //

	z_Q15=(int)(temp<<2);
	printf("res:%f\n", z_Q15/Q15);

    return 0;
}

结果:res:-0.099976

2.1 防溢出处理

整型数进行加减运算的时候,如果得到的结果超出范围:-32768≤X≤32767,即[8000H-7FFFH]

则称之为上溢或者下溢。

(1)下溢:

x=32766, y=3,x和y均从浮点数转换而来,假设它们是同一个Q值,进行加法操作后,结果为:32769,假设这里的数值都是16bit的,那么32769的补码就是:

1000000000000001

计算机将该值取出时,会把它当成一个负数(最高位符号位为1):除去符号位,其余位减1得到:0000 0000 0000 000

再取反,得到:1111 1111 1111 111,为-32767d

所以,若将该数加上1,并不是32770,而是-32766。

测试代码:

#include

#include

int main()

{

short x=32766;

short y=3;

short z=x+y;

printf("z=%d\n", z);

    return 0;

}

结果:z=-32767

(2)上溢

设x=15000,y=20000,则求和后z=x+y=35000 > 32767,如果结果超出16bit的表示范围,则保留32bit的结果(转成32bit数进行运算)。

首先,进行定标(16bit):Qx=1, Qy=0, Qz=0

定点加法先定标,y向x对齐:long temp=y<<1=20000<<1=40000

进行加法:temp=temp+(x<<1);//相当于两个加数同时左移

最后,结果:temp=temp>>1; //Qx>Qz

测试代码:

#include

#include

int main()

{

short x=15000, y=20000;

int temp, z;

temp=(y<<1);

temp=(x<<1)+temp;

z=temp>>1;

printf("z=%d\n", z);

    return 0;

}

结果:z=35000

结果超范围,则两个加数同时左移,最后同时右移,结果不在用16bit来存储,而是32bit。伪代码如下:

Int x,y;

Long temp, z;

Temp=y<<(Qx-Qy); //假设Qx>Qy,y向x对标,y就要左移操作(上文数学表达式推算)。

Temp=x+temp;

If(Qx≥Qz)

z=(int)(temp>>( Qx- Qz))

else if(Qx≤Qz)

z=(int)(temp<<( Qz- Qx))

else

另一种做法是,保持16bit的运算(虽然对结果进行了检查):

#include

#include

#include

int16_t Q16_add_sat(int16_t a, int16_t b)

{

    int16_t result;

    int32_t tmp;

    tmp = (int32_t)a + (int32_t)b;

    if (tmp > 0x7FFF)

        tmp = 0x7FFF;

    if (tmp < -1 * 0x8000)

        tmp = -1 * 0x8000;

    result = (int16_t)tmp;

    return result;

}

int main()

{

short x=15000, y=20000;

// int temp, z;

// temp=(y<<1);

// temp=(x<<1)+temp;

// z=temp>>1;

// printf("z=%d\n", z);

printf("z=%d\n", q_add_sat(x,y));

    return 0;

}

结果:z=32767,精度严重恶化。

修改如下:

int32_t Q16_add_sat(int16_t a, int16_t b)

{

    int32_t result;

    result = (a<<1) + (b<<1);

    result = (result>>1);

    return result;

}

int main()

{

short x=15000, y=20000;

// int temp, z;

// temp=(y<<1);

// temp=(x<<1)+temp;

// z=temp>>1;

// printf("z=%d\n", z);

printf("z=%d\n", Q16_add_sat(x,y));

    return 0;

}

3. 定点化乘法计算规则

3.1 推算

DSP定点数的计算规则和示例_第3张图片

 所以,定点乘法伪代码如下:

Int x,y,z;

Long temp;

Temp=long(x);

z=(temp*y)>>();

测试代码:

#include

#include

#include

#define Q10 1024.0

#define Q9 512.0

#define Q5 32.0

int main()

{

float x=18.4, y=36.8;

long temp;

short x_Q16=x*Q10;

short y_Q16=y*Q9;

short res;

temp=x_Q16*y_Q16;

res=temp>>(10+9-5);

printf("res=%d, %f\n", res, res/32.0);

    return 0;

}

结果:res=21666, 677.062500

4. 定点化除法计算规则

4.1 推算

DSP定点数的计算规则和示例_第4张图片

 测试代码:

#include

#include

#include

#define Q15 32768.0

#define Q10 1024.0

#define Q9 512.0

#define Q5 32.0

int main()

{

float x=18.4, y=36.8;

long temp;

short x_Q16=x*Q10;

short y_Q16=y*Q9;

short res; //Q15

temp=(x_Q16<<(15-10+9));

res=temp/y_Q16;

printf("res=%d, %f\n", res, res/Q15);

    return 0;

}

结果:res=16384, 0.500000

5. 程序代码中如何确定Q值

DSP定点数的计算规则和示例_第5张图片

6. 浮点转定点计算示例

示例1:混合计算

计算1.78x0.6+2.43

DSP定点数的计算规则和示例_第6张图片

DSP定点数的计算规则和示例_第7张图片

代码:

#include

#include

#define Q13_a (0.35*8192.0)

#define Q13_b (2.7*8192.0)

#define Q13_c (1.43*8192.0)

void main()

{

int a,b,c,d,f;

long result;

a=(int)Q13_a;

b=(int)Q13_b;

c=(int)Q13_c;

result=(long)(a*b);

d=(result>>13);

f=d+c;

printf("result:%f\n", f/8192.0);

}

示例2:汉明窗的计算

示例3:FIR低通滤波实现

你可能感兴趣的:(语音信号处理,算法)