单片机学习:Q格式数

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
  • 48
    点赞
  • 175
    收藏
    觉得还不错? 一键收藏
  • 7
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值