假设我有一个计算时间t
正弦波值的程序。正弦波的形式为sin(f*t + phi)
。幅度为1
。
如果我只有一个sin
个词,那么一切都很好。我可以随时轻松计算出值t
。
但是,在运行时,波形在与其他波形结合时会被修改。 sin(f1 * t + phi1) + sin(f2 * t + phi2) + sin(f3 * t + phi3) + ...
最简单的解决方案是创建一个包含phi
和f
列的表,迭代所有行,并对结果求和。但对我而言,一旦我达到数千行,计算就会变慢。
有不同的方法吗?比如将所有正弦值合并为一个陈述/公式?
答案 0 :(得分:1)
存在用于表示不同波形的有利(即,紧凑)的不同基础(多个基础)。最常见和众所周知的是你提到的,通常称为傅立叶基。例如,Daubechies小波是一种相对较新的补充,它比傅立叶基更好地处理更多的不连续波形。但这实际上是一个数学主题,如果你发表数学溢出,你会得到更好的答案。
答案 1 :(得分:1)
如果您有一个傅里叶级数(即某些f的f_i
= i f
),您可以使用Clenshaw recurrence relation,这比计算所有正弦值要快得多(但可能稍微有些不太准确)。
在您的情况下,您可以考虑序列:
f_k = exp( i ( k f t + phi_k) ) , where i is the imaginary unit.
请注意Im(f_k)
= sin( k f t + phi_k )
,这是您的序列。
另外
f_k = exp( i ( k f t + phi_k) ) = exp( i k f t ) exp( i phi_k )
因此你有a_k = exp(i phi_k)
。您可以预先计算这些值并将它们存储在数组中。为简单起见,假设为a_0 = 0
。
现在,exp( i (k + 1) f t) = exp(i k f t) * exp(i f t)
,alpha_k = exp(i f t)
和beta_k = 0
。
您现在可以应用递归公式,在C ++中可以执行以下操作:
complex<double> clenshaw_fourier(double f, double t, const vector< complex<double> > & a )
{
const complex<double> alpha = exp(f * t * i);
complex<double> b = 0;
for (int k = a.size() - 1; k >0; -- k )
b = a[k] + alpha * b;
return a[0] + alpha * b;
}
假设a[k] == exp( i phi_k )
。
答案的真实部分是cos(k f t + phi_k)
的总和,而虚部是sin(k f t + phi_k)
的总和。
正如您所看到的,这仅使用加法和乘法,但exp(f * t * i)
只计算一次。