空间换时间:查表法 (LUT) 与 CORDIC 算法
在 PC 上,计算 sin(x) 只需要包含 <math.h> 然后调用就行了。但在资源受限的微控制器(如 Cortex-M0/M3)上,标准库的 sin() 往往意味着几 KB 的代码量和数千个周期的耗时。
如果你的应用(如电机 FOC 控制、逆变器)需要高频计算三角函数,标准库是绝对不行的。我们有两个选择:查表法 (Look-Up Table) 和 CORDIC 算法。
1. 查表法 (LUT):简单粗暴
原理很简单:预先算出 0~90 度的正弦值,存到数组里。
1.1 基础实现
1 | const float sin_table[91] = {0.0, 0.0174, ... 1.0}; |
缺点:精度太低!只有整数角度。如果我要算 sin(45.5) 怎么办?
1.2 线性插值 (Linear Interpolation)
假设 $x$ 在 $x_1$ 和 $x_2$ 之间,那么 $y$ 就在 $y_1$ 和 $y_2$ 之间。使用线性公式:
$$ y = y_1 + (x - x_1) \frac{y_2 - y_1}{x_2 - x_1} $$
这样即使表很小(比如每隔 5 度存一个值),通过插值也能获得不错的精度。
2. CORDIC 算法:移位加减的奇迹
如果 Flash 也很小,存不下大表怎么办?或者你需要极高的精度?
CORDIC (Coordinate Rotation Digital Computer) 算法登场了。它只需要移位、加法、减法,不需要乘法器,更不需要浮点单元。
2.1 几何意义
CORDIC 的核心是伪旋转。将一个向量 $(x, y)$ 旋转 $\theta$ 角,可以通过多次旋转一连串预定义的小角度($\arctan(2^{-i})$)来逼近。
为什么选 $\arctan(2^{-i})$?因为 $\tan(\theta) = 2^{-i}$,乘法就变成了移位!
2.2 迭代过程
我们预先存储一个很小的角度表(几十字节):atan_table = [45.0, 26.565, 14.036, ...]
对于第 $i$ 次迭代:
- 如果当前角度小于目标角度,就逆时针转(加法)。
- 如果当前角度大于目标角度,就顺时针转(减法)。
- 坐标更新公式仅涉及
>> i。
1 | // 伪代码 |
3. 对比总结
| 维度 | 查表法 (LUT) | CORDIC |
|---|---|---|
| 速度 | 极快 O(1) | 较慢 O(k),跟迭代次数有关 |
| 内存 | 大 (取决于精度) | 极小 (几十字节) |
| 代码 | 简单 | 略复杂 |
| 适用 | 内存够,追求极致速度 | 内存紧缺,或需要动态高精度 |
结论:在电机控制 (FOC) 中,通常用插值查表法,因为速度第一。而在科学计算器或 FPGA 逻辑中,CORDIC 是首选。
- Title: 空间换时间:查表法 (LUT) 与 CORDIC 算法
- Author: Evek Golden
- Created at : 2025-07-05 23:30:00
- Updated at : 2026-06-12 08:57:02
- Link: https://blog.cocodemo.uno/posts/math9k3/
- License: This work is licensed under CC BY-NC-SA 4.0.