Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/66.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 如何将数字转换为Q格式_C_Embedded - Fatal编程技术网

C 如何将数字转换为Q格式

C 如何将数字转换为Q格式,c,embedded,C,Embedded,我正在使用英飞凌的XMC1300 MCU系列。对于我的应用程序,我需要找出一些数据的平方根 以下是Infineon提供的数学库api int16_t XMC_MATH_CORDIC_Q15_Sqrt(int16_t x) int32_t XMC_MATH_CORDIC_Q31_Sqrt(int32_t x) 这两个API接受并返回数据格式Q15和Q31,即它只能表示[-1,1]范围 假设我想找出 144 200 1000 34567 50000 如何在[-1,1]范围内更改这些数字 输入和

我正在使用英飞凌的XMC1300 MCU系列。对于我的应用程序,我需要找出一些数据的平方根

以下是Infineon提供的数学库api

int16_t XMC_MATH_CORDIC_Q15_Sqrt(int16_t x) 
int32_t XMC_MATH_CORDIC_Q31_Sqrt(int32_t x)
这两个API接受并返回数据格式Q15和Q31,即它只能表示[-1,1]范围

假设我想找出

144
200
1000
34567
50000
如何在[-1,1]范围内更改这些数字

输入和输出的标准化需要做些什么

问候,,
Tinchu

您不能在Q15或Q31格式中直接表示144或50000。正如您所提到的,这些格式是介于-1和1之间的数字的定点表示

所以你剩下的问题是一个基本的数学问题。 我们可以利用以下事实:

sqrt(A/B)=sqrt(A)/sqrt(B)

让我们做一个示例,其中您的值
A=144

将B设置为Q31除数
B=0x7FFFF=32768

A/B = 0.00439`
Sqrt(A/B) = 0.0663 
Sqrt(B) = Sqrt(32768) = 181.02
Sqrt(A) = Sqrt(A/B)*Sqrt(B) = 0.0663 * 181.02 = 12.
如何使用Q15数字实现这一点?所有数字都按
B
缩放。 所以Sqrt(A/B)就是
XMC\u MATH\u CORDIC\u Q15\u Sqrt(A)/=>2172

因为0.0663=2172/32768

Sqrt(B)为181。整数数学的最终结果是
181*2172/32768=12
*

对于较大的数字,您需要使用Q31除数:
0x7fffFFFF=2147483647


*注:整数数学将把答案四舍五入到11。如果你想要更好的四舍五入,你需要在除法之前检查第15位。

我通常只开发从机器到工程单位的转换公式。在这种情况下,输入和输出预计为Q15。下面我用_eu表示工程单位,_mu表示机器单位,sqrt()表示实际平方根。平方根的公式:

output_eu = sqrt(input_eu)
输入和输出的转换:

output_mu = (2^15)*output_eu
input_mu = (2^15)*input_eu
要获得以机器单位表示的等效计算,替换为:

output_mu/(2^15) = sqrt(input_mu/(2^15))
output_mu = sqrt((2^15)*input_mu)
为了优化精度,最好将输入右移,因此在144的情况下,数字可以左移7位:144*(2^7)=18432

所以输入基本上是Q7

换言之:

output_mu = sqrt((2^15)*((2^7)*input_eu))
          = (2^11)*sqrt(input_eu)
基本上,这里的输出是Q11,可以右移11位,以工程单位得到结果

所以,如果要在代码中执行此操作,假设值144加载到变量x中,我们希望将结果放入变量y中:

y = x << 7;
y = XMC_MATH_CORDIC_Q15_Sqrt(y);
y >>= 11;

所以你提到的两个函数可以确定-1到1范围内的值的平方根,你想用它们来计算0到50000的值吗?为了更好地理解,我想知道类型“int”对于-0.25的结果是什么。否则,应使用已知数字的平方(即,除以90000或接近50000的数值)进行归一化,然后将结果乘以已知数字(300)。如果您就您的问题提供一点mcve,我将用代码给出答案。@Yunnosch thanx供您回复。以上是英飞凌论坛的链接。请打开它。那边的答复不令人满意。据我所知,这两个API只接受格式为Q15和Q31的参数,并以相同的格式返回结果。如果我想要任何数字的平方根,就说57。我需要首先将其转换为Q15或Q31格式。但是我们怎么做呢?乘以四的幂可以在源操作数范围内(int16\u t或int32\t)缩放到一个较大的值。调用函数。将结果除以二的相同幂,在一些合适的数据类型中执行除法。谢谢你的回复。A=144,XMC_MATH_CORDIC_Q15_Sqrt(A)/=>2172,你如何得到这个值。因为当我将144传递给API时,我得到了3117。此外,如果我们拿其他案例,比如200或1000,这将如何工作?我不知道为什么你会得到3117。对于0x4000,您得到了什么?对于0x4000,我得到了2317023170/32768=0.707=sqrt(0.5),所以这是有意义的。仍然不确定3117从何而来,这应该是308的结果。在C代码中使用
^
表示求幂是令人困惑的,因为
^
是异或运算符。Post在从代码转换到数学时缺乏清晰度。考虑其他格式。Jonathon,Chouth-Xyx Alter为你的回复,这是怎么来的?输出μ=sqrt((2^15)*((2^7)*输入μeu))=(2^11)*sqrt(输入μeu)。(2^7)如何计算如果这个数字大于int16,我们将不得不跳转到int32,也就是Q31。在这种情况下,将进行什么样的位移位计算对不起,回复延迟了。以下是我对第二条评论的回应。对于sqrt(144)的示例情况,在计算平方根之前,希望左移位144,直到它占据14位。这将最大限度地提高计算的整体精度,因为计算输出中将填充更多的位。
1) y = (144*(2^7)) = 18432
2) y = sqrt((2^15)*18432) = 24576
3) y = 24576/(2^11) = 12