為什么有IQ格式?
將小數(應該說是浮點數)化成整數,目的是為了加快運算速度,可以百度Q格式數的原理。
如何使用IQ格式計算
既然是將小數化成整數,那么肯定是要乘上某個值,讓小數變成整數
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次冪,總之就是將小數變成了整數。但是從手冊上可以看出不同的定義有不同的范圍
許多DSP都是定點DSP,處理定點數據會相當快,但是處理浮點數據就會非常慢。可以利用Q格式進行浮點數據到定點的轉化,節約CPU時間。實際應用中,浮點運算大都時候都是既有整數部分,也有小數部分的。所以要選擇一個適當的定標格式才能更好的處理運算。
Q格式表示為:Qm.n,表示數據用m比特表示整數部分,n比特表示小數部分,共需要m+n+1位來表示這個數據,多余的一位用作符合位。假設小數點在n位的左邊(從右向左數),從而確定小數的精度
例如Q15表示小數部分有15位,一個short型數據,占2個字節,最高位是符號位,后面15位是小數位,就假設小數點在第15位左邊,表示的范圍是:-1<X<0.9999695 。
浮點數據轉化為Q15,將數據乘以2^15;Q15數據轉化為浮點數據,將數據除以2^15。
例如:假設數據存儲空間為2個字節,0.333×2^15=10911=0x2A9F,0.333的所有運算就可以用0x2A9F表示,同理10911×2^(-15)=0.332977294921875,可以看出浮點數據通過Q格式轉化后是有誤差的。
例:兩個小數相乘,0.333*0.414=0.137862
0.333*2^15=10911=0x2A9F,0.414*2^15=13565=0x34FD
short a = 0x2A9F;
short b = 0x34FD;
short c = a * b >> 15; // 兩個Q15格式的數據相乘后為Q30格式數據,因此為了得到Q15的數據結果需要右移15位
這樣c的結果是0x11A4=0001000110100100,這個數據同樣是Q15格式的,它的小數點假設在第15位左邊,即為0.001000110100100=0.1378173828125...和實際結果0.137862差距不大。或者0x11A4 / 2^15 = 0.1378173828125
Q格式的運算
1> 定點加減法:須轉換成相同的Q格式才能加減
2> 定點乘法:不同Q格式的數據相乘,相當於Q值相加,即Q15數據乘以Q10數據后的結果是Q25格式的數據
3> 定點除法:不同Q格式的數據相除,相當於Q值相減
4> 定點左移:左移相當於Q值增加
5> 定點右移:右移相當於Q減少
Q格式的應用格式
實際應用中,浮點運算大都時候都是既有整數部分,也有小數部分的。所以要選擇一個適當的定標格式才能更好的處理運算。一般用如下兩種方法:
1> 使用時使用適中的定標,既可以表示一定的整數復位也可以表示小數復位,如對於2812的32位系統,使用Q15格式,可表示-65536.0~65535.999969482區間內的數據。
2> 全部采用小數,這樣因為小數之間相乘永遠是小數,永遠不會溢出。取一個極限最大值(最好使用2的n次冪),轉換成x/Max的小數(如果Max是取的2的 n次冪,就可以使用移位代替除法)。