解释两个不动点分数的计算平方根

时间:2016-10-03 15:17:35

标签: c embedded fractions blackfin

我在blackfin533上发现了一段代码,它的fract32是-1,1,格式为1.31。

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

GO_coil_D [0] .re 和GO_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范围内的值

1 个答案:

答案 0 :(得分: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.0000000011 2,im = 0.0000000100 2。对它们进行平方给出re²= 0.00000000000000001001 2,im²= 0.00000000000000010000 2。加上正方形得到abs²= 0.00000000000000011001 2。舍入到15个小数位给出abs²= 0.000000000000001 2。取平方根得到abs = 0.000000010110101 2。这与0.0000000101 2的精确结果0.000000000010101 2不同。

当预定标时,两个分数向左移动6位,给出sre = 0.0011 2,sim = 0.0100 2(我用前缀's'表示'scaled')。对它们进行平方给出sre²= 0.00001001 2,sim²= 0.00010000 2。加上正方形得到sabs 2 = 0.00011001 2。舍入到15个小数位不会改变该值。取平方根得到sabs = 0.01010000 2。将其转换为1.31格式并向右移动6位,得到abs = 0.0000000101 2,这是完全正确的(十进制为5/1024)。