我一直在双曲旋转模式下查看 CORDIC 算法以找到变量的平方根。 我不确定我的初始变量应该是什么(x0、y0、z0)来找到平方根。我读过一些论文,引用要找到sqrt(a),x0,y0和z0的初始值应分别设置为a+1,a-1,0。 其他人说它应该是 a+0.25,a-0.25,0。 我对此感到非常困惑
谁能帮忙?
double x = (64.0+1);
double y = (64.0-1);
double z = 0;
double k = 3;
double n = 1;
while(n <= 20 ){
double xn = pow(2.0,-1.0*n) * x;
double yn = pow(2.0,-1.0*n) * y;
if(y < 0){
x = x + xn;
y = y + yn;
z = z - atanh(pow(2.0,-1.0*n));
}
else
{
x = x - xn;
y = y - yn;
z = z + atanh(pow(2.0,-1*n));
}
if(k > 0){
k = k-1;
}
else{
k = 3;
if(y < 0){
x = x + xn;
y = y + yn;
z = z - atanh(pow(2.0,-1.0*n));
}
else
{
x = x - xn;
y = y - yn;
z = z + atanh(pow(2.0,-1.0*n));
}
}
n++;
cout << "x: " << x << " y: " << y << " z: " << z << endl;
}
编辑*除了补偿 3j+1 重复外,CORDIC 还需要在 n = 4,13,40、... 我已经更新了我的代码来弥补这一点,但它仍然不起作用。我在矢量模式下使用双曲旋转,变量d
应基于 y 的符号
编辑*事实证明,在计算较大的平方根值时,CORDIC 可能会失败,因此您必须将尝试找到平方根的数字归一化为 0.5 到 2 的范围,然后缩小答案。
对于 x0,y0 和 z0,初始值应分别设置为 A+1,A-1,0。其他人说它应该是 a+0.25,a-0.25,0。我对此感到非常困惑
最终结果是sqrt((a+1)^2 - (a-1)^2)
或sqrt((a+0.25)^2 - (a-0.25)^2)
。 无论哪种方式,a^2
项都会取消,常量项会取消。 唯一的区别是第一个版本返回sqrt(4a)
或2sqrt(a)
,第二个版本直接返回sqrt(a)
。 我不知道为什么一种或另一种情况可能更受欢迎。
编辑:您的错误正在根据y
设置d
,它应该基于z
。
执行平方根的数字规范化为 [0.5,2) 范围,然后相应地缩小。
代码中有几个错误!
- 变量不交换。
x = x + xn;
y = y + yn;
应该是:
x = x + yn;
y = y + xn;
- 迭代 4 和 13 未正确重复。需要在这些分支中重新计算以下内容:
xn = pow(2.0,-1.0*n) * y;
yn = pow(2.0,-1.0*n) * x;
- 应在输出(
x/2*1.207497
)上进行刻度校正。
有关丑陋的调试但有效的代码,请参阅此处:https://godbolt.org/z/ma4dCV
另请注意,不需要整个z
通道 (https://mathworks.com/help/fixedpoint/examples/compute-square-root-using-cordic.html)。