将精确的波形保存在内存中

Keeping exact wave form in memory

假设我有一个程序计算时间 t 的正弦波值。正弦波的形式为 sin(f*t + phi)。振幅为 1.

如果我只有一个 sin 学期,一切都很好。我可以随时轻松计算出价值 t.

但是,在运行时,波形在与其他波形结合时会发生变化。 sin(f1 * t + phi1) + sin(f2 * t + phi2) + sin(f3 * t + phi3) + ...

最简单的解决方案是让 table 包含 phif 的列,遍历所有行,然后对结果求和。但是对我来说,一旦达到数千行,计算就会变慢。

有没有其他方法可以做到这一点?就像将所有正弦组合成一个 statement/formula?

有不同的基础(复数基础)可以有利于(即紧凑)表示不同的波形。最常见和最著名的是你提到的,通常称为傅立叶基础。例如,Daubechies 小波是一个相对较新的补充,它比傅里叶基更好地处理更多的不连续波形。但这确实是一个数学主题,如果您 post 在 Math Overflow 上,您可能会得到更好的答案。

如果你有一个傅里叶级数(即 f_i = i f 对于某些 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)