Q格式问题
什么是Q格式数?
比如
_iq var = _IQ(0.1);
_iq multi = _IQmpy(1 * _IQ(1));
为什么有Q格式?
将小数(应该说是浮点数)化成整数,目的是为了加快运算速度,可以百度Q格式数的原理。
如何使用Q格式计算
既然是将小数化成整数,那么肯定是要乘上某个值,让小数变成整数
typedef long _iq; /* Fixed point data type: GLOBAL_Q format */
typedef long _iq30;
typedef long _iq29;
typedef long _iq28;
typedef long _iq27;
typedef long _iq26;
typedef long _iq25;
typedef long _iq24;
typedef long _iq23;
typedef long _iq22;
typedef long _iq21;
typedef long _iq20;
typedef long _iq19;
typedef long _iq18;
typedef long _iq17;
typedef long _iq16;
typedef long _iq15;
typedef long _iq14;
typedef long _iq13;
typedef long _iq12;
typedef long _iq11;
typedef long _iq10;
typedef long _iq9;
typedef long _iq8;
typedef long _iq7;
typedef long _iq6;
typedef long _iq5;
typedef long _iq4;
typedef long _iq3;
typedef long _iq2;
typedef long _iq1;
#define _IQ30(A) (long) ((A) * 1073741824.0L)
#define _IQ29(A) (long) ((A) * 536870912.0L)
#define _IQ28(A) (long) ((A) * 268435456.0L)
#define _IQ27(A) (long) ((A) * 134217728.0L)
#define _IQ26(A) (long) ((A) * 67108864.0L)
#define _IQ25(A) (long) ((A) * 33554432.0L)
#define _IQ24(A) (long) ((A) * 16777216.0L)
#define _IQ23(A) (long) ((A) * 8388608.0L)
#define _IQ22(A) (long) ((A) * 4194304.0L)
#define _IQ21(A) (long) ((A) * 2097152.0L)
#define _IQ20(A) (long) ((A) * 1048576.0L)
#define _IQ19(A) (long) ((A) * 524288.0L)
#define _IQ18(A) (long) ((A) * 262144.0L)
#define _IQ17(A) (long) ((A) * 131072.0L)
#define _IQ16(A) (long) ((A) * 65536.0L)
#define _IQ15(A) (long) ((A) * 32768.0L)
#define _IQ14(A) (long) ((A) * 16384.0L)
#define _IQ13(A) (long) ((A) * 8192.0L)
#define _IQ12(A) (long) ((A) * 4096.0L)
#define _IQ11(A) (long) ((A) * 2048.0L)
#define _IQ10(A) (long) ((A) * 1024.0L)
#define _IQ9(A) (long) ((A) * 512.0L)
#define _IQ8(A) (long) ((A) * 256.0L)
#define _IQ7(A) (long) ((A) * 128.0L)
#define _IQ6(A) (long) ((A) * 64.0L)
#define _IQ5(A) (long) ((A) * 32.0L)
#define _IQ4(A) (long) ((A) * 16.0L)
#define _IQ3(A) (long) ((A) * 8.0L)
#define _IQ2(A) (long) ((A) * 4.0L)
#define _IQ1(A) (long) ((A) * 2.0L)
DSP上是乘上2的N次幂,总之就是将小数变成了整数。但是从手册上可以看出不同的定义有不同的范围
刚开始的时候有个地方非常困扰我,_iq,_iq1,_iq2…,明明定义的都是long为什么会有不同的范围呢?后来我想应该是他们都是long型的意思是他们呢都有64位,但是定点数的小数点是变化的(可以看看定点数的意义),_iq30就是小数点在30位。他们的计算都是整型在计算,但是表示的格式是小数。
举个例子来说明一下,先来一个24位Q格式的
_iq24 var = _IQ24(0.75)
//代表的意思是
var = (long)(0.75 * 16777216.0L) = 12582912;
再来一个15位Q格式的
_iq15 var = _IQ15(0.75)
//代表的意思是
var = (long)(0.75 * 32768.0L) = 24567;
我们看到,虽然不同位的Q格式得到的var不同,但是我们知道表示都是0.75。然后我们再来看看为什么同是long类型,但是却又不同的范围。从手册上可以看出24位Q格式的范围是-128~128,可是他是long类型的的啊,范围应该很大的啊,为什么整数部分这么小,用一个byte就可以表示了?其他的32-8 = 24位呢?其实仔细一看手册,我们发现还有精度的表示,没错,其余的24位表示了精度。看一个例子
0.75 * 1
->转化成24位Q二进制(只是为了形象)
0000 0000 . 1100 0000 0000 0000 0000 0000
0000 0001 . 0000 0000 0000 0000 0000 0000
->转化成24位Q格式数
0000 0000 1100 0000 0000 0000 0000 0000
0000 0001 0000 0000 0000 0000 0000 0000
上面很形象的展示了Q格式。小数点在第24位的左边,左边的是整数,右边的是小数,精度是2的 -24次幂。这就很简单了。
上面的写成代码就是下面
(_IQ24(0.75) * _IQ24(1)) >> 48
或者
_IQ24mpy(_IQ24(0.75) * _IQ24(1)) >> 24
上面用了一个函数_IQ24mpy。库里是这样写的
#define _IQmpy(A,B) __IQmpy(A,B,GLOBAL_Q)
#define _IQ30mpy(A,B) __IQmpy(A,B,30)
这个函数一开始也让我觉得奇怪。后来测试了一下,表示的意思就是
(A * B) >> GLOBAL_Q