Loading

Loading

CORDIC算法证明过程推导

CORDIC算法证明过程推导

与占用大量存储单元的NCO不同,CORDIC可以不用预先存储数据,来产生正余弦信号。

CORDIC 可以看作是在“角度空间”中进行的一种特殊的二分查找。它通过迭代使用一系列越来越小的固定角度(查找表),根据当前误差决定方向,高效地逼近目标角度。

而这个“旋转查找”过程的迷人之处在于,它不仅找到了角度,还顺便完成了向量的旋转,并输出了我们需要的三角函数值。

这正是它成为硬件计算核心算法的原因。

以下,是cordic算法的推导证明过程

ffa69f36a1a56778254e5eaec19bc50e

6acc340f9a49a0a993d2e3ef01cc995d

简易的C++代码实现:

#include <bits/stdc++.h>
using namespace std;

const double pi = 3.14159265358979323846;
const int ITERATIONS = 16;  // 迭代次数,16次通常足够精确(2^16)

// CORDIC算法计算sin和cos
void cordic(double angle_rad, double &cos_val, double &sin_val) {
    // 角度预处理:将角度限制在[-pi, pi]范围
    if (angle_rad > pi) angle_rad -= 2 * pi;
    else if (angle_rad < -pi) angle_rad += 2 * pi;
    
    // 进一步限制在[-pi/2, pi/2]范围
    int quadrant = 0;  // 记录象限
    if (angle_rad > pi/2) {
        angle_rad -= pi;
        quadrant = 1;
    } else if (angle_rad < -pi/2) {
        angle_rad += pi;
        quadrant = 1;
    }
    
    // 预计算的arctan(2^{-i})表
    double atan_table[ITERATIONS] = {
        0.7853981633974483,  // arctan(2^0) = 45°
        0.4636476090008061,  // arctan(2^-1)
        0.24497866312686414,
        0.12435499454676144,
        0.06241880999595735,
        0.031239833430268277,
        0.015623728620476831,
        0.007812341060101111,
        0.0039062301319669718,
        0.0019531225164788188,
        0.0009765621895593195,
        0.0004882812111948983,
        0.00024414062014936177,
        0.00012207031189367021,
        6.103515617420877e-05,
        3.0517578115526096e-05
    };
    
    // CORDIC旋转迭代
    double x = 1.0;  // 初始x = 1/K ≈ 0.60725
    double y = 0.0;  // 初始y = 0
    double z = angle_rad;  // 当前角度(目标角度)
    
    for (int i = 0; i < ITERATIONS; i++) {
        double sigma = (z >= 0) ? 1.0 : -1.0;  // 旋转方向
        
        double x_new, y_new;
        
        if (sigma > 0) {
            // 逆时针旋转
            x_new = x - (y / (1 << i));  // x - y * 2^{-i}
            y_new = y + (x / (1 << i));  // y + x * 2^{-i}
        } else {
            // 顺时针旋转
            x_new = x + (y / (1 << i));  // x + y * 2^{-i}
            y_new = y - (x / (1 << i));  // y - x * 2^{-i}
        }
        
        x = x_new;
        y = y_new;
        z -= sigma * atan_table[i];  // 更新剩余角度
    }
    
    // 应用增益补偿并考虑象限
    double K = 0.6072529350088812561694;  // 1/1.64676
    
    if (quadrant) {
        cos_val = -x * K;  // 在第二、三象限,cos为负
        sin_val = -y * K;  // 在第二、三象限,sin为负
    } else {
        cos_val = x * K;
        sin_val = y * K;
    }
}

// 测试主函数
int main() {
    double angle_deg;
    cout << "请输入角度(度): ";
    cin >> angle_deg;
    
    // 转换为弧度
    double angle_rad = angle_deg * pi / 180.0;
    
    double cos_result, sin_result;
    cordic(angle_rad, cos_result, sin_result);
    
    // 计算误差
    double cos_std = cos(angle_rad);
    double sin_std = sin(angle_rad);
    
    cout << fixed << setprecision(10);
    cout << "\n计算结果:\n";
    cout << "CORDIC: cos(" << angle_deg << "°) = " << cos_result << endl;
    cout << "CORDIC: sin(" << angle_deg << "°) = " << sin_result << endl;
    cout << "标准库: cos(" << angle_deg << "°) = " << cos_std << endl;
    cout << "标准库: sin(" << angle_deg << "°) = " << sin_std << endl;
    cout << "误差: cos_err = " << fabs(cos_result - cos_std) 
         << ", sin_err = " << fabs(sin_result - sin_std) << endl;
    
    return 0;
}
posted @ 2026-02-25 11:30  Miya555  阅读(82)  评论(0)    收藏  举报