By Long Luo
之前写过一篇介绍 CORDIC 算法 的文章,里面提到 CORDIC 算法的 不足 之处,CORDIC 算法的输入角度范围需要在 \([−99.88^{\circ} , 99.88^{\circ}]\) ,那么我们不禁要问,如果输入角度 \(\large {\theta }\) 很大的话,怎么处理呢?
这个问题同样存在于 泰勒展开式(Taylor series) 中,比如 \(\large {\sin (x) }\) 和 \(\large {\cos (x) }\) 的泰勒展开式:
\[ \sin(x) = x - \frac {1}{3!}x^3 + \frac {1}{5!}x^5 - \frac {1}{7!} x^7 + \frac {1}{9!} x^9 + o(x^9) \quad \forall x \subset \mathbb{R} \]
\[ \cos(x) = 1 - \frac {1}{2!}x^2 + \frac {1}{4!}x^4 - \frac {1}{6!} x^6 + \frac {1}{8!} x^8 + o(x^8) \quad \forall x \subset \mathbb{R} \]
虽然在整个实数集 \(\large { \mathbb{R}}\) 都成立,但是在实际应用中因为展开项数限制和浮点数的精度限制, \(\large {x}\) 的范围只有在接近 \(\large {0}\) 的时候才有比较高的精度。
但是实际应用中,如果输入 \(\large {x}\) 很大的话,比如 \(\large {2^{32}, 10^{10}, 10^{22} \dots }\) 情况下怎么得到足够精确的值呢?
中学里我们知道三角函数是周期函数,对于比较大的值,我们可以使用下面的公式将值归约到一个比较小的范围内。
\[ x' = x - 2k \pi \quad k \subset \mathbb{Z} \]
这就是我们今天要讲的 参数归约(Argument Reduction) 算法。
从小学计算题开始
参数归约 听起来就很唬人,什么是参数啊,什么归约啊,都是些高大上的名词,听起来云里雾里的!
为了不让大家产生厌倦和畏难心理,我们先从一道小学数学计算题开始:
不借助计算器,计算 \(\large {66600 \times 666000}\) 的值!
对于这道题,大家可能会列出下列算术:
\[ 66600 \times 666000 = 666 \times 666 \times 100000 = 44355600000 \]
但其实呢,我们也可以使用下面的方法:
\[ \begin{aligned} 66600 \times 666000 &= 111^2 \times 4 \times 9 \times 10^5 \\&= 444 \times 999 \times 10^5 \\&= 444 \times (1000 - 1) \times 10^5 \\&= 4443556 \times 10^5 \end{aligned} \]
如果我说上面这 \(\large {2}\) 种方法都用到了参数归约的思想,你可能会感到震惊,什么?这种小学计算题也用到了参数归约算法吗?