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;
}