我正在研究这种讽刺。而且我发现了这一切。 K = 0.607XXX。
从CORDIC,K_i = cos(tan ^ -1(2 ^ i))。
据我所知,当我要无限时,K值为0.607xxx。
这个值来自所有K乘法。
我理解每个k存在的原因。但我很好奇它在哪里使用?为什么我们使用该值K = 0.607xx?
答案 0 :(得分:2)
CORDIC循环变体的旋转模式的比例因子可以从第一原理轻松建立。 CORDIC背后的想法是在单位圆上取一个点并逐步旋转它,通过我们想要确定的正弦和余弦的 u 角度。
为此,我们定义了一组增量角度a 0 ,..., n-1 ,这样一个 k = atan(0.5 k )。我们将这些增量角适当地加到角度s k 的部分和中,例如s n 〜= u 。设y k = cos(s k )和x k = sin(s k )。如果在给定的步骤 k 中我们通过 k 旋转,我们有
y k + 1 = cos(s k + 1 )= cos(s k + a k )
x k + 1 = sin(s k + 1 )= sin(s k + a k )< / p>
我们可以从x k 和y k 计算x k + 1 和y k + 1 如下:
y k + 1 = y k * cos(a k ) - x k * sin(一个<子>ķ子>)
x k + 1 = x k * cos(a k )+ y k * sin(a ķ子>)
考虑到我们可以加上和减去 k ,并且tan(a k )= sin(a k )/ cos (a k ),我们得到:
y k + 1 = cos(a k )*(y k ∓x k * tan (a k ))= cos(s k + 1 )
x k + 1 = cos(a k )*(x k ±y k * tan(a < sub> k ))= sin(s k + 1 )
为简化此计算,我们可以在每一步中省略cos(a k )的乘法,这为我们提供了CORDIC迭代方案:
y k + 1 =y∓x k * tan(a k )
x k + 1 = x±y k * tan(a k )
由于我们选择了 k ,如果我们用定点算术计算,乘法tan(a k )会变成简单的右移。因为我们省略了因子cos(a k ),所以我们结束了
y n 〜= cos( u )*(1 /(cos(a 0 )* cos(a 1 )* ... * cos(a n ))
x n 〜= sin( u )*(1 /(cos(a 0 )* cos(a 1 )* ... * cos(a n ))
因子 f = cos(a 0 )* cos(a 1 )* ... * cos(a n )是0.607 ......,如前所述。我们通过设置起始值
将其合并到计算中 y 0 = f * cos(0)= f
x 0 = f * sin(0)= 0
这是使用16位定点算法显示整个计算的C代码。输入角度被缩放,使得360度对应于2 16 ,而正弦和余弦输出被缩放,使得1对应于2 15 。
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
/* round (atand (0.5**i) * 65536/360) */
static const short a[15] =
{
0x2000, 0x12e4, 0x09fb, 0x0511,
0x028b, 0x0146, 0x00a3, 0x0051,
0x0029, 0x0014, 0x000a, 0x0005,
0x0003, 0x0001, 0x0001
};
#define swap(a,b){a=a^b; b=b^a; a=a^b;}
void cordic (unsigned short u, short *s, short *c)
{
short x, y, oldx, oldy, q;
int i;
x = 0;
y = 0x4dba; /* 0.60725 */
oldx = x;
oldy = y;
q = u >> 14; /* quadrant */
u = u & 0x3fff; /* reduced angle */
u = -(short)u;
i = 0;
do {
if ((short)u < 0) {
x = x + oldy;
y = y - oldx;
u = u + a[i];
} else {
x = x - oldy;
y = y + oldx;
u = u - a[i];
}
oldx = x;
oldy = y;
i++;
/* right shift of signed negative number implementation defined in C */
oldx = (oldx < 0) ? (-((-oldx) >> i)) : (oldx >> i);
oldy = (oldy < 0) ? (-((-oldy) >> i)) : (oldy >> i);
} while (i < 15);
for (i = 0; i < q; i++) {
swap (x, y);
y = -y;
}
*s = x;
*c = y;
}
int main (void)
{
float angle;
unsigned short u;
short s, c;
printf ("angle in degrees [0,360): ");
scanf ("%f", &angle);
u = (unsigned short)(angle * 65536.0f / 360.0f + 0.5f);
cordic (u, &s, &c);
printf ("sin = % f (ref: % f) cos = % f (ref: % f)\n",
s/32768.0f, sinf(angle/360*2*3.14159265f),
c/32768.0f, cosf(angle/360*2*3.14159265f));
return EXIT_SUCCESS;
}