一键计算正弦和余弦 [英] Calculation sine and cosine in one shot

查看:121
本文介绍了一键计算正弦和余弦的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have a scientific code that uses both sine and cosine of the same argument (I basically need the complex exponential of that argument). I was wondering if it were possible to do this faster than calling sine and cosine functions separately.

我只需要大约0.1%的精度。那么有什么方法可以找到默认的三角函数并截断幂级数以提高速度?

Also I only need about 0.1% precision. So is there any way I can find the default trig functions and truncate the power series for speed?

我要记住的另一件事是,有什么方法可以执行余数运算使得结果始终为正?在我自己的算法中,我使用了 x = fmod(x,2 * pi); ,但是如果x为负,则需要添加2pi(较小的域意味着我可以使用较短的幂级数)

One other thing I have in mind is, is there any way to perform the remainder operation such that the result is always positive? In my own algorithm I used x=fmod(x,2*pi); but then I would need to add 2pi if x is negative (smaller domain means I can use a shorter power series)

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

LUT turned out to be the best approach for this, however I am glad I learned about other approximation techniques. I will also advise using an explicit midpoint approximation. This is what I ended up doing:

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);
}

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

The following part approximates (midpoint) 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];

另一种方法可能是使用chebyshev分解。您可以使用正交性属性来找到系数。针对指数进行了优化,如下所示:

Another approach could have been using the chebyshev decomposition. You can use the orthogonality property to find the coefficients. Optimized for exponential, it looks like this:

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


推荐答案

如果您要通过幂级数寻求具有良好(但不是很高)准确性的快速评估,则应使用Chebyshev多项式的展开式:将系数制成表格(对于0.1%的精度,您将需要很少的数据),并使用这些多项式的递归关系来评估扩展(这非常简单)。

If you seek fast evaluation with good (but not high) accuracy with powerseries you should use an expansion in Chebyshev polynomials: tabulate the coefficients (you'll need VERY few for 0.1% accuracy) and evaluate the expansion with the recursion relations for these polynomials (it's really very easy).

参考文献:


  1. 制表系数: http://www.ams.org/mcom/1980-34-149/S0025-5718-1980- 0551302-5 / S0025-5718-1980-0551302-5.pdf

  2. chebyshev扩展的评估: https://en.wikipedia.org/wiki/Chebyshev_polynomials
  1. Tabulated coefficients: http://www.ams.org/mcom/1980-34-149/S0025-5718-1980-0551302-5/S0025-5718-1980-0551302-5.pdf
  2. Evaluation of chebyshev expansion: https://en.wikipedia.org/wiki/Chebyshev_polynomials

您需要(a)取得-pi / 2 .. + pi / 2范围内的 reduced自变量然后(b)当参数实际上应位于整个基本间隔-pi .. + pi的另一一半时,处理结果中的符号。这些方面不应该构成主要问题:

You'll need to (a) get the "reduced" argument in the range -pi/2..+pi/2 and consequently then (b) handle the sign in your results when the argument actually should have been in the "other" half of the full elementary interval -pi..+pi. These aspects should not pose a major problem:


  1. 确定(并记住为整数1或-1)原始符号

  2. 使用模函数减少到区间0..2PI

  3. 确定(并记住为整数1或-1)是否在后一半中,如果是,则减去pi * 3/2,否则减去pi / 2。注意:这有效地交换了正弦和余弦(除符号外);

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

This completes the step to get an angle in -pi/2..+pi/2 After evaluating sine and cosine with the Cheb-expansions, apply the "flags" of steps 1 and 3 above to get the right signs in the values.

这篇关于一键计算正弦和余弦的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆