在内存中保持精确的波形

时间:2015-05-31 03:56:21

标签: math trigonometry sin cos

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

如果我只有一个sin个词,那么一切都很好。我可以随时轻松计算出值t

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

最简单的解决方案是创建一个包含phif列的表,迭代所有行,并对结果求和。但对我而言,一旦我达到数千行,计算就会变慢。

有不同的方法吗?比如将所有正弦值合并为一个陈述/公式?

2 个答案:

答案 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)只计算一次。