我有一个使用相同参数的正弦和余弦的科学代码(我基本上需要该参数的复数指数)。我想知道是否有可能比分别调用正弦和余弦函数更快。
另外我只需要0.1%的精度。那么有什么方法可以找到默认的触发功能并截断功率系列的速度吗?
我想到的另一件事是,有没有办法执行余数运算,结果总是积极的?在我自己的算法中,我使用x=fmod(x,2*pi);
,但如果x为负数,我需要加2pi(较小的域意味着我可以使用更短的幂级数)
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)))
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分解。您可以使用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
答案 0 :(得分:1)
如果你想要使用功率良好(但不是很高)的精确度进行快速评估,你应该使用切比雪夫多项式的扩展:将系数列表(你需要非常少,精度为0.1%)并评估扩展这些多项式的递归关系(它真的很容易)。
参考文献:
您需要(a)获得&#34;减少&#34;在-pi / 2 .. + pi / 2范围内的参数,然后(b)当参数实际上应该在&#34;其他&#34;中时,处理结果中的符号。完整基本区间的一半-pi .. + pi。这些方面不应成为一个主要问题:
这样就完成了在-pi / 2 .. + pi / 2中获得角度的步骤 在使用Cheb-expansions评估正弦和余弦后,应用&#34;标志&#34;上面的步骤1和3,以获得值的正确标志。
答案 1 :(得分:1)
只需创建一个查找表。以下内容将允许您查找-2PI和2PI之间的任何弧度值的sin和cos。
// LOOK UP TABLE
var LUT_SIN_COS = [];
var N = 14400;
var HALF_N = N >> 1;
var STEP = 4 * Math.PI / N;
var INV_STEP = 1 / STEP;
// BUILD LUT
for(var i=0, r = -2*Math.PI; i < N; i++, r += STEP) {
LUT_SIN_COS[2*i] = Math.sin(r);
LUT_SIN_COS[2*i + 1] = Math.cos(r);
}
通过以下方式索引到查找表中:
var index = ((r * INV_STEP) + HALF_N) << 1;
var sin = LUT_SIN_COS[index];
var cos = LUT_SIN_COS[index + 1];
这是一个小提示,显示不同大小LUT http://jsfiddle.net/77h6tvhj/
可以预期的%误差编辑这是一个ideone(c ++),带有~base~对浮点sin和cos。 http://ideone.com/SGrFVG无论ideone.com的基准值是多少,LUT都要快5倍。
答案 2 :(得分:0)
一种方法是学习如何实现CORDIC算法。这不是困难而且非常有趣。这给你余弦和正弦。维基百科给出了MATLAB example,它应该很容易在C ++中适应。
请注意,只需降低参数n
即可增加速度并降低精度。
关于你的第二个问题,它已经被问到here(在C中)。似乎没有简单的方法。
答案 3 :(得分:0)
您还可以使用平方根计算正弦,给定角度和余弦。
以下示例假设角度范围为0到2π:
double c = cos(angle);
double s = sqrt(1.0-c*c);
if(angle>pi)s=-s;
答案 4 :(得分:0)
对于单精度浮点数,Microsoft对正弦使用11度多项式逼近,余弦使用10度:XMScalarSinCos。 它们还有更快的版本,XMScalarSinCosEst,它使用低次多项式。
如果您不在Windows上,则会在Boost许可下找到相同的代码+系数on geometrictools.com。