0

我在 blackfin533 上找到了一段代码,它的 fract32 来自 -1, 1,格式为 1.31。

我不明白为什么计算复数(re,img)的幅度需要预移位。我知道如果你想将 1.31 乘以 1.31 小数格式,那么你需要右移 31 位。

GO_coil_D[0].reGO_coil_D[0].im是两个fract32

我无法得到以下代码在做什么:

 norm[0] = norm_fr1x32(GO_coil_D[0].re);
 norm[1] = norm_fr1x32(GO_coil_D[0].im);
 shift = (norm[0] < norm[1]) ? (norm[0] - 1) : (norm[1] - 1);
 vectorFundamentalStored.im = shl_fr1x32(GO_coil_D[0].im,shift);     
 vectorFundamentalStored.re = shl_fr1x32(GO_coil_D[0].re,shift);
 vectorFundamentalStored.im = mult_fr1x32x32(vectorFundamentalStored.im, vectorFundamentalStored.im);
 vectorFundamentalStored.re = mult_fr1x32x32(vectorFundamentalStored.re, vectorFundamentalStored.re);  
 amplitudeFundamentalStored = sqrt_fr16(round_fr1x32(add_fr1x32(vectorFundamentalStored.re,vectorFundamentalStored.im))) << 16;
 amplitudeFundamentalStored = shr_fr1x32(amplitudeFundamentalStored,shift);

round_fr1x32` (fract32 f1) fract16 使用有偏舍入将 32 位分数舍入为 16 位分数。

norm_fr1x32 norm_fr1x32 (fract32) int 返回归一化输入变量所需的左移次数,使其位于 0x40000000 到 0x7fffffff 区间或 0x80000000 到 0xc0000000 区间内。换句话说,fract32 x;shl_fr1x32(x,norm_fr1x32(x)); 返回 0x40000000 到 0x7fffffff 范围内的值,或 0x80000000 到 0xc0000000 范围内的值

4

1 回答 1

1

1) 如果小数部分的最高有效n位都是“0”位,并且后面跟着一个“1”位,则n的行为类似于值n的浮点二进制指数,其余 31- n位表现得像尾数。对数字进行平方会使前导“0”位的数量加倍为 2* n并将尾数的大小减少到 31-2* n位。这可能导致平方运算结果的精度损失。

2)round_fr1x32将 1.31 小数转换为 1.15 小数,最多损失 16 位精度。

希望您可以看到第 1 步和第 2 步可以消除数字中的很多精度。对数字进行预缩放会尽可能减少前导 '0' 位的数量n ,从而导致在步骤 1 丢失的精度更少。事实上,对于两个数字之一的平方和相加,前导 '0' 的数量' 位n将为零,因此在将其添加到另一个数字之前,对该数字进行平方仍将保留多达 31 位的精度。(第 2 步会将精度降低到 15 位。)

最后,您对两个 1.31 小数格式数字相乘的结果是错误的 - 结果需要右移 31 位,而不是 62 位。

工作示例:

假设实部是 3/1024,虚部是十进制的 4/1024,那么毕达哥拉斯的绝对值应该是 5/1024。

在没有预缩放的情况下,二进制分数是 re=0.00000000112,im=0.00000001002。将它们平方得到 re²=0.00000000000000001001²,im²=0.00000000000000010000²。添加正方形得到 abs²=0.00000000000000011001²。舍入到 15 个小数位得到 abs²=0.000000000000001²。取平方根得出 abs=0.000000010110101₂。这与精确结果 0.0000000101₂ 相差 0.000000000010101₂。

预分频时,两个分数都左移 6 位,得到 sre=0.0011₂, sim=0.0100₂(我使用前缀“s”表示“缩放”)。将它们平方得到 sre²=0.00001001₂,sim²=0.00010000₂。添加正方形得到 sabs²=0.00011001²。舍入到 15 个小数位不会更改该值。取平方根得到 sabs=0.01010000₂。将其转换为 1.31 格式并右移 6 位得到 abs=0.0000000101₂,这是完全正确的(十进制为 5/1024)。

于 2016-10-03T16:32:58.777 回答