Q格式

✍ dations ◷ 2025-01-12 06:48:42 #Q格式

Q格式是二进制的定点数格式,其中会标示小数位元(也可能包括整数位元)的长度。例如Q15数表示分数部分有15个位元,而Q1.14数表示1个整数位元以及14个小数位元。

针对有号的定点数,有二种Q格式的表示方式。其中一种是将符号位元算在整数位元里,但另外一种就不是。例如,16位元的有号整数(无小数位元)可以表示为Q16.0或Q15.0。因此,在用说明Q格式的有号定点数字时,可能也需要一并标示总位元数(在此处为16)。

Q格式是几种广为使用的定点数中的一种。定点数常用在不支援浮点运算器的硬件,或是用在需要固定分辨率的应用。

Q格式用来标示定点数,储存以及运算都是以一般的二进制整数为基础来处理,因此允许标准的整数硬件/算术逻辑单元来进行有理数运算。程式设计者可以依应用需求,选定其整数位元数、小数位元数(以及资料总位元数),而之后定点数的范围以及分辨率就会依整数位元数、小数位元数而不同。

有些DSP架构原生支持一些常用的Q格式(例如Q1.15),这种情形下,可以在一个指令下就进行四则运算,若是加减法,可以支援饱和运算,若是乘除法,可以有正规化的机能。不过大部分的DSP无此功能,若DSP架构不支持选定的Q格式,程式设计者就要自行再针对加减法进行饱和运算,针对乘除法进行正规化。

有号号Q格式的表示方式有两种,都写成Q.:

一种表示方式将符号位元放在整数位元 中一起计算,另一种则不是。确认方式可以将和相加,看是否等于数字位元数,若相等,表示其符号位元放在整数位元 ,若比数字位元数少1,表示其其符号位元独立计算。

此外,字母U可以放在Q前面,说明是无号数,例如UQ1.15,数值范围是0.0 to +1.999969482421875 (也就是 1 + 2 15 1 2 15 {displaystyle 1+{frac {2^{15}-1}{2^{15}}}} .格式(假设符号位元也算在m个位元内),用+位元的有号整数来处理,再考虑其中有位元是表示小数:

针对给定的UQ.格式,用+位元的有号整数来处理,再考虑其中有位元是表示小数:

例如Q15.1格式的数字:

Q格式和浮点数不同,Q格式数字的分辨率不随数字大小而不冋。

若要将浮点数(例如IEEE 754)转换为Q.的格式:

若要将Q.Q格式的数数转换为浮点数:

Q格式的数字是二个整数的比例:会储存分子,而分母固定是2。

考虑以下的例子;

若Q格式的基底固定(都相同),则Q格式的数学运算需维持分母不变。以下是二个相同Q格式数字 N 1 {displaystyle N_{1}} N 2 {displaystyle N_{2}} 的运算。

N 1 d + N 2 d = N 1 + N 2 d N 1 d N 2 d = N 1 N 2 d ( N 1 d × N 2 d ) × d = N 1 × N 2 d ( N 1 d / N 2 d ) / d = N 1 / N 2 d {displaystyle {begin{aligned}{frac {N_{1}}{d}}+{frac {N_{2}}{d}}&={frac {N_{1}+N_{2}}{d}}\{frac {N_{1}}{d}}-{frac {N_{2}}{d}}&={frac {N_{1}-N_{2}}{d}}\left({frac {N_{1}}{d}}times {frac {N_{2}}{d}}right)times d&={frac {N_{1}times N_{2}}{d}}\left({frac {N_{1}}{d}}/{frac {N_{2}}{d}}right)/d&={frac {N_{1}/N_{2}}{d}}end{aligned}}}

因为分母是二的次幂,因此和二的次幂相乘可以表示为二进制下的左移,和二的次幂相除可以表示为二进制下的右移,很多处理器的左移和右移会比乘除法要快。

为了要维持乘法和除法的精度,中间值需要用双精度来储存,在转换回需要的Q格式数字之间,也需要先注意数值修约的处理。

两个不同Q格式基底的数字也可以相乘除,相乘除的数字也可以用另一个基底表示。以下是二个Q格式数字 N 1 {displaystyle N_{1}} (分母 d 1 {displaystyle d_{1}} )和 N 2 {displaystyle N_{2}} (分母 d 2 {displaystyle d_{2}} )的运算,运算结果的分母是 d 3 {displaystyle d_{3}}

( N 1 d 1 × N 2 d 2 ) × d 1 d 2 d 3 = N 1 × N 2 d 3 ( N 1 d 1 / N 2 d 2 ) × d 1 d 2 d 3 = N 1 / N 2 d 3 {displaystyle {begin{aligned}left({frac {N_{1}}{d_{1}}}times {frac {N_{2}}{d_{2}}}right)times {frac {d_{1}d_{2}}{d_{3}}}&={frac {N_{1}times N_{2}}{d_{3}}}\left({frac {N_{1}}{d_{1}}}/{frac {N_{2}}{d_{2}}}right)times {frac {d_{1}}{d_{2}d_{3}}}&={frac {N_{1}/N_{2}}{d_{3}}}end{aligned}}}


若用C语言,相同Q格式基底数字四则运算对应的程式如下(以下的Q是表示小数部分的位元数)

int16_t q_add(int16_t a, int16_t b){    return a + b;}

有饱和

int16_t q_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;}

浮点数有±Inf,但Q格式没有,若不进行饱和处理,二个很大的正数相加,可能会变成一个很大的负数。若是用组合语言,可以用Signed Overflow旗标来避免C语言实现时需要的型态转换。

相关