Math 在存储器中保持精确的波形

Math 在存储器中保持精确的波形,math,trigonometry,Math,Trigonometry,假设我有一个程序,可以计算时间t时正弦波的值。正弦波的形式为sin(f*t+phi)。振幅为1 如果我只有一个sin术语,一切都很好。我可以随时轻松计算值t 但是,在运行时,当波形与其他波形组合时,它会被修改正弦(f1*t+phi1)+正弦(f2*t+phi2)+正弦(f3*t+phi3)+…… 最简单的解决方案是创建一个包含phi和f列的表,遍历所有行,并对结果求和。但对我来说,一旦我达到数千行,计算速度就会变慢 有没有其他的方法?就像将所有正弦组合成一个语句/公式一样?有不同的基(基的复数形

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

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

但是,在运行时,当波形与其他波形组合时,它会被修改<代码>正弦(f1*t+phi1)+正弦(f2*t+phi2)+正弦(f3*t+phi3)+……

最简单的解决方案是创建一个包含
phi
f
列的表,遍历所有行,并对结果求和。但对我来说,一旦我达到数千行,计算速度就会变慢


有没有其他的方法?就像将所有正弦组合成一个语句/公式一样?

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

如果你有一个傅里叶级数(例如,对于某些f,fúi=
i f
),你可以使用,它比计算所有正弦要快得多(但它的精确度可能稍低)


在你的情况下,你可以考虑以下顺序:

f_k = exp( i ( k f t + phi_k) ) , where i is the imaginary unit.
请注意,
Im(f_k)
=
sin(k f t+phi_k)
,这是您的序列

因此您有
a_k=exp(i phi_k)
。您可以预计算这些值并将其存储在数组中。为了简单起见,从现在开始假设
a_0=0

现在,
exp(i(k+1)ft)=exp(ikft)*exp(ift)
,所以
alpha\uk=exp(ift)
beta\uk=0

现在可以应用递归公式,C++中你可以做这样的事情:< /P>

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;
}
复数克伦肖-傅立叶(双f,双t,常数向量&a)
{
常数复α=exp(f*t*i);
复b=0;
对于(int k=a.size()-1;k>0;--k)
b=a[k]+α*b;
返回a[0]+alpha*b;
}
假设
a[k]==exp(iφk)

答案的实部是cos(kft+phi_k)之和,而虚部是sin(kft+phi_k)之和


正如你所看到的,这只使用加法和乘法,除了只计算一次的
exp(f*t*i)

它们的计算效率会差不多吗?如果你的函数是平滑的正弦函数,傅里叶基是最好的。如果你有锐利的边缘,你需要使用小波。小波压缩(或近似,如果你愿意)可以快得令人眼花缭乱。还有其他的事情。你能详细说明你的答案吗?我特别不明白我怎样才能满足这个条件
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;
}