一次计算正弦和余弦

grd*_*fgr 9 c++ algorithm trigonometry

我有一个使用相同参数的正弦和余弦的科学代码(我基本上需要该参数的复数指数).我想知道是否有可能比分别调用正弦和余弦函数更快.

另外我只需要0.1%的精度.那么有什么方法可以找到默认的触发功能并截断功率系列的速度?

我想到的另一件事是,有没有办法执行余数运算,结果总是积极的?在我自己使用的算法中,x=fmod(x,2*pi);但如果x为负数,我需要加2pi(较小的域意味着我可以使用较短的幂级数)

编辑:LUT原来是最好的方法,但我很高兴我了解了其他近似技术.我还建议使用明确的中点近似.这就是我最终做的事情:

const int N = 10000;//about 3e-4 error for 1000//3e-5 for 10 000//3e-6 for 100 000
double *cs = new double[N];
double *sn = new double[N];
for(int i  =0;i<N;i++){
    double A= (i+0.5)*2*pi/N;
    cs[i]=cos(A);
    sn[i]=sin(A);
}
Run Code Online (Sandbox Code Playgroud)

以下部分近似(中点)sincos(2*pi*(wc2 + t [j]*(cotp*t [j] -wc)))

double A=(wc2+t[j]*(cotp*t[j]-wc));
int B =(int)N*(A-floor(A));
re += cs[B]*f[j];
im += sn[B]*f[j];
Run Code Online (Sandbox Code Playgroud)

另一种方法可能是使用切比雪夫分解.您可以使用orthogonality属性来查找系数.针对指数进行了优化,它看起来像这样:

double fastsin(double x){
    x=x-floor(x/2/pi)*2*pi-pi;//this line can be improved, both inside this 
                              //function and before you input it into the function

    double x2 = x*x;
    return (((0.00015025063885163012*x2- 
   0.008034350857376128)*x2+ 0.1659789684145034)*x2-0.9995812174943602)*x;} //7th order chebyshev approx
Run Code Online (Sandbox Code Playgroud)

Ber*_*lde 2

如果您寻求使用幂级数以良好(但不高)精度进行快速评估,您应该使用切比雪夫多项式的扩展:将系数制成表格(您需要非常少的系数才能达到 0.1% 的精度)并使用这些多项式的递归关系评估扩展(这真的很容易)。

参考:

  1. 系数列表:http://www.ams.org/mcom/1980-34-149/S0025-5718-1980-0551302-5/S0025-5718-1980-0551302-5.pdf
  2. 切比雪夫展开式的评估:https://en.wikipedia.org/wiki/Chebyshev_polynomials

您需要 (a) 获得 -pi/2..+pi/2 范围内的“简化”参数,然后 (b) 当参数实际上应该位于“其他”中时,处理结果中的符号" 完整基本区间的一半 -pi..+pi。这些方面不应构成主要问题:

  1. 确定(并“记住”为整数 1 或 -1)原始角度的符号并继续计算绝对值。
  2. 使用模函数减少到区间 0..2PI
  3. 确定(并“记住”为整数 1 或 -1)它是否在“后”半部分,如果是,则减去 pi*3/2,否则减去 pi/2。注意:这有效地互换了正弦和余弦(符号除外);在最终评估中考虑到这一点。

这样就完成了获取 -pi/2..+pi/2 角度的步骤。使用 Cheb 展开式评估正弦和余弦后,应用上面步骤 1 和 3 的“标志”以获得值中的正确符号。