幂级数与傅里叶级数

幂级数

n=0anxn=a0+a1x++anxn+ (式1-1)为以{a0,a1,an.}为系数的幂级数,显然x可以替换成xx0,本质上无异

收敛半径与收敛区间

R:=(limn|an|n)1(式1-2)或者R:=(limn|anan+1|(式1-3)

R为幂级数(式1-1)的收敛半径,约定(01=+,+1=0

收敛区间

  • 若按(式1-2)R>0,则级数(式1-1)在区间(R,R)上绝对收敛并内闭一致收敛,且此时区间(R,R)为级数(式1-1)的收敛区间
  • 若按(式1-2)R<,则级数(式1-1)在区间[R,R]之外处处发散
  • 若按(式1-2)0<R<,则级数(式1-1)在x=±R可能收敛,也可能发散

泰勒展开

f(x)在某个区间内(x0R,x0+R)内无限次可微且可表示为幂级数:

f(x)=n=0an(xx0)n

an=f(n)(x0)n!,因此f(x)=n=0f(n)(x0)n!(xx0)n

等式右端恰好为f(x)x0处的泰勒级数,称为f(x)x0处的泰勒展开式,此时幂级数也称为泰勒级数

解析函数:若f(x)在开区间I内每点均可泰勒展开式,则称f(x)I内的实解析函数

泰勒余项

显然,实际泰勒展开时n很难趋于+n=k时为泰勒级数的部分和Tn(x),通过泰勒余项Rn=f(x)Tn(x)来进一步拟合原函数,泰勒余项Rn有三种形式

  • 拉格朗日形式
  • 柯西形式
  • 积分形式

傅里叶级数

三角级数

a02+n=1(ancosnx+bnsinnx)(式2-1)为以实序列{a0,a1,b1,b2,,}为系数的周期为2π的三角级数,显然周期2π可以替换成任意周期2l的三角级数a02+n=1(ancosnπxl+bnsinnπxl),二者本质上无异

傅里叶系数与傅里叶级数

f(x)[π,π]上的绝对可积函数,令:

{an=1πππf(x)cosnxdxbn=1πππf(x)sinnxdx

(式2-2)称an,bnf(x)的傅里叶系数,其中n=0,1,2,3,4,

相应地,只要f(x)[π,π]上的绝对可积,则必有傅里叶级数与之对应:f(x)a02+n=1(ancosnx+bnsinnx)
但是,此傅里叶级数是否收敛,是否以f(x)为和函数,尚未可知

奇函数的傅里叶级数是正弦级数,偶函数的傅里叶级数是余弦函数

任意区间上的傅里叶级数

f(x)[l,l]上的绝对可积函数,则:

f(x)a02+n=1(ancosnπxl+bnsinnπxl)

其中,

{an=1lllf(x)cosnπxldxbn=1lllf(x)sinnπxldx

同理,任意区间是[a,b]上的傅里叶级数,只需将[a,b]线性映射成[l,l],令l=ba2,则

{an=1labf(x)cosnπxldxbn=1labf(x)sinnπxldx

函数正交

从两个向量正交引申到两个函数正交(函数是无限维的向量,积分是无限微分累加),如两可积函数f(x),g(x)[a,b]上满足:abf(x)g(x)dx=1
则称函数f(x),g(x)[a,b]上正交

如果可积函数序列{ϕn(x)}[a,b]上满足:abϕm(x)ϕn(x)dx={1 if m=n 0 if mn
则称函数系{ϕn(x)}[a,b]上为标准正交系

显然,正弦函数与余弦函数组成的三角函数系{12π,sinnxπ,cosnxπ}[π,π]上为标准正交系

三角函数系可作为希尔伯特空间的基函数,幂函数系{1,x,x2,},通过正交规范化也可作为标准正交系,比如雅克比多项式,切比雪夫多项式,勒让德多项式,拉盖尔多项式,伯恩斯坦多项式

f(x)[π,π]上可表示为一致收敛的三角级数,则此三角级数必为傅里叶级数

复数形式的傅里叶级数

f(x)[π,π]上的绝对可积,将(式2-2)中实傅里叶系数an,bn使用复数c±n表示

c±n=12πππf(x)einxdx

则称c±n(n=0,1,2,)f(x)的复数形式的傅里叶系数,复数形式的傅里叶级数记作:f(x)n=cneinx
对比可知,c0=a02,cn=anibn2,cn=an+ibn2,n=1,2,3

复数形式更为优雅简洁,且当向量与旋转因子eiθ相乘时,表示向量绕原点逆时针旋转θ度,使得复数形式中的旋转因子einx具有更高维度视角

傅里叶变换

卷积定理,时域上卷积运算对应于频域上的傅里叶变换的乘积

  • 三角级数的收敛性以及和函数(如果存在)颇为复杂,无普遍解答
  • 对于给任意定函数f(x)能否展开为三角级数,可知f(x)[a,b]上的绝对可积,则必有傅里叶级数与之对应

傅里叶变换给出了信号(时变函数)的频率信息,也就意味着它可以告诉我们该信号中各种频率的个数,但是不能告诉我们特定频率在何时(对应的时刻)存在。

  • 当信号是*稳状态时,频率对应的时刻是不需要的
  • 对非*稳过程,傅里叶变换有局限性;即将一段信号正放或者反放都可以得到一些相同的傅里叶级数

将一段信号正放或反放,可以得到部分相同的傅里叶级数系数。

也就是说,信号的傅里叶级数表达式是不变的,但是信号的时域表达式会发生改变。具体解释如下:

  1. 对于一个周期性信号f(t)的傅里叶级数表达式为:

    f(t)=a0+(ancos(nωt)+bnsin(nωt))

    其中a0,an,bn是傅里叶级数的系数。

  2. 如果将信号f(t)对称地反转,得到新的信号g(t)=f(t)

  3. g(t)的傅里叶级数展开,可以发现anbn的系数保持不变,只是sin(nωt)的系数发生改变为bn

    g(t)=a0+(ancos(nωt)bnsin(nωt))

  4. 因此,正放和反放信号的傅里叶级数系数是相同的,只是sin项的系数发生了改变。

  5. 这是因为傅里叶级数表达式描述的是信号的频谱特性,而不是时域形状。

所以,正放和反放信号的傅里叶级数表达式虽然不同,但其傅里叶级数系数是相同的。这是一个重要的性质,在信号分析中经常用到。

时域上有巨大差异的信号,频谱却非常一致,频率的信号的成分是一样的,只是出现的先后顺序不同

短时傅里叶变换

为实现频域信号的时刻识别,把整个时域过程分解成无数个等长的小过程,每个小过程*似*稳,再进行傅里叶变换,就能知道在哪个时间点上出现了什么频率了。这就是短时傅里叶变换(the short-time Fourier transform,STFT)

窗函数

  • 窗太窄,窗内的信号太短,会导致频率分析不够精准,频率分辨率差。
  • 窗太宽,时域上又不够精细,时间分辨率低。
  • 时频共轭
  • 对于时变的非稳态信号,高频适合小窗口,低频适合大窗口
  • STFT的窗口是固定的,在一次STFT中宽度不会变化,所以STFT还是无法满足非稳态信号变化的频率的需求

快速傅里叶变换

快速傅里叶变换(Fast Fourier Transform,FFT),是离散傅氏变换的快速算法,它是根据离散傅氏变换的奇、偶、虚、实等特性,对离散傅立叶变换的算法进行改进获得的

#include<bits/stdc++.h>
using namespace std;
//complex是stl自带的定义复数的容器 
typedef complex<double> cp;
#define N 2097153
//pie表示圆周率π 
const double pie=acos(-1);
int n;
cp a[N],b[N];
int rev[N],ans[N];
char s1[N],s2[N];
//读入优化 
int read(){
	int sum=0,f=1;
	char ch=getchar();
	while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){sum=(sum<<3)+(sum<<1)+ch-'0';ch=getchar();}
	return sum*f;
}
//初始化每个位置最终到达的位置 
{
    int len=1<<k;
	for(int i=0;i<len;i++)
	rev[i]=(rev[i>>1]>>1)|((i&1)<<(k-1));
}
//a表示要操作的系数,n表示序列长度
//若flag为1,则表示FFT,为-1则为IFFT(需要求倒数) 
void fft(cp *a,int n,int flag){ 
    for(int i=0;i<n;i++)
	{
	 //i小于rev[i]时才交换,防止同一个元素交换两次,回到它原来的位置。 
	  if(i<rev[i])swap(a[i],a[rev[i]]);
	}
	for(int h=1;h<n;h*=2)//h是准备合并序列的长度的二分之一
	{
	cp wn=exp(cp(0,flag*pie/h));//求单位根w_n^1 
	 for(int j=0;j<n;j+=h*2)//j表示合并到了哪一位
	 {
	  cp w(1,0);
	   for(int k=j;k<j+h;k++)//只扫左半部分,得到右半部分的答案
	   {
	     cp x=a[k];
	     cp y=w*a[k+h];
         a[k]=x+y;  //这两步是蝴蝶变换 
         a[k+h]=x-y;
         w*=wn; //求w_n^k 
	   }
	 }
	 }
	 //判断是否是FFT还是IFFT 
	 if(flag==-1)
	 for(int i=0;i<n;i++)
     a[i]/=n;
}
int main(){
	n=read(); 
	scanf("%s%s",s1,s2);
	//读入的数的每一位看成多项式的一项,保存在复数的实部 
    for(int i=0;i<n;i++)a[i]=(double)(s1[n-i-1]-'0');
	for(int i=0;i<n;i++)b[i]=(double)(s2[n-i-1]-'0');
	//k表示转化成二进制的位数 
	int k=1,s=2;
 	while((1<<k)<2*n-1)k++,s<<=1;
	init(k);
	//FFT 把a的系数表示转化为点值表示 
    fft(a,s,1);
    //FFT 把b的系数表示转化为点值表示 
    fft(b,s,1);
    //FFT 两个多项式的点值表示相乘 
    for(int i=0;i<s;i++)
    a[i]*=b[i];
    //IFFT 把这个点值表示转化为系数表示 
    fft(a,s,-1);
    //保存答案的每一位(注意进位) 
    for(int i=0;i<s;i++)
    {
    //取实数四舍五入,此时虚数部分应当为0或由于浮点误差接*0
	ans[i]+=(int)(a[i].real()+0.5);
	ans[i+1]+=ans[i]/10;
	ans[i]%=10;
	}
	while(!ans[s]&&s>-1)s--;
	if(s==-1)printf("0");
	else
	for(int i=s;i>=0;i--)
	printf("%d",ans[i]);
	return 0;
}

小波变换

小波变换(the wavelet transform)直接把傅里叶变换的基进行替换——将无限长的三角函数基换成了有限长衰减的小波基。这样不仅能够获取频率,还可以定位到时间

某频率的基函数与信号相乘后积分,会得到一个很大的值,因为此时二者有一种重合关系——相关性。此时,就可以判断信号包含该频率的成分,本质在计算信号和三角函数的相关性

不同于傅里叶变换,变量只有频率ω,小波变换有两个变量:尺度a(scale)和*移量τ(translation):

  • 尺度a控制小波函数的伸缩,*移量τ控制小波函数的*移
  • 尺度a对应频率(反比),*移量τ对应时间
  • 小波变换可以得到一个时频谱

WT(a,τ)=1af(t)φ(tτa)dt

  • 对于突变信号,傅里叶变换存在吉布斯效应,用无限长的三角函数也很难拟合好突变信号
  • 只有小波函数和信号突变处重叠时,系数不为0

常用的小波函数φ(tτa)

  • Haar小波
  • Morlet小波
  • Marr小波
  • DOG(Difference of Gaussian)小波

不同的小波在正交性、紧支撑性、*滑性和对称性上表现出不同的特性,往往难以构造一个同时具有4种特性的小波函数

多项式

有限项的幂级数称为多项式,即称f(x)=n=0anxn=a0+a1x++anxn (式1-3)为以{a0,a1,an}为系数的多项式

多项式的表示法

  • 系数法:{a0,a1,an}
  • 点值法:{(0,[0]),(1,[1]),...,(,[])},由n+1个点构成的集合可以确定多项式方程

多项式乘积

对两个多项式f(x),g(x)进行相乘(求卷积)

  • 系数法:枚举f的每一位的系数与g的每一位的系数相乘,多项式乘法时间复杂度O(n2)
  • 点值法:f[x]g[x]={(x0,f[x0]g[x0]),(x1,f[x1]g[x1]),...,(xn,f[xn]g[xn])},复杂度只有枚举xO(n)

朴素系数转点值的算法叫DFT(离散傅里叶变换),优化后为FFT(快速傅里叶变换)点值转系数的算法叫IDFT(离散傅里叶逆变换),优化后为IFFT(快速傅里叶逆变换)。

两函数的傅里叶变换的乘积等于它们卷积后的傅里叶变换

由于多项式乘法用点值表示比用系数表示快的多,所以我们先要将系数表示法转化成点值表示法相乘,再将结果的点值表示法转化为系数表示法的过程。

第一个过程叫做FFT(快速傅里叶变换),第二个过程叫IFFT(快速傅里叶逆变换)

DFT 离散傅里叶变换

对于任意多项式系数表示点值表示,例如f[x]=y=a0+a1x++anxn,可以随便取任意nx值代入计算,但这样时间复杂度是O(n2)

傅里叶发现,代入一些特殊点可以对过程优化

他规定了点值表示中的nx取值为:n个模长为1的复数。这n个复数是单位根

复数ω满足=1,称ωn次单位根

把上述的n个复数(单位根){ωn0,ωn1.....,ωnn1}​代入多项式,能得到一种特殊的点值表示,这种点值表示就叫DFT(离散傅里叶变换)

不过时间复杂度是O(n2),需要进行运算优化,即 FFT 快速傅里叶变换

FFT 快速傅里叶变换

对于多项式f[x]=y=a0+a1x++anxn,按照幂的次数分为奇偶两部分(假设n为偶数):

y=(a0x0+a2x2++an2xn2)+x(a1x0+a3x2++an1xn2)=A0(x2)+xA1(x2)

k=0,1,2n1,代入x=ωnk(n次单位根)

A(ωnk)=A0(ωn2k)+ωnkA1(ωn2k)=A0(ωn2k)+ωnkA1(ωn2k)(ωnk+n2)
=A0(ωn2k+n)+ωnk+n2A1(ωn2k+n)
=A0(ωn2k)ωnkA1(ωn2k)

考虑A0(x)A1(x)分别在(ωn21,ωn22,ωn23,...,ωn2n1)的点值表示已经求出,即可求出A(x)(ωn1,ωn2,ωn3,...,ωnn1)处的点值表示。

这个操作叫蝴蝶变换

A0(x)A1(x)使得规模缩小了一半的子问题,所以不断向下递归分治。当n=1的时候返回。

时间复杂度O(nlog2n)

迭代FFT:

初始位置:ωn0ωn1ωn2ωn3ωn4ωn5ωn6ωn7

第一轮后:ωn0ωn2ωn4ωn6​|ωn1ωn3ωn5ωn7

第二轮后:ωn0ωn4​|ωn2ωn6​|ωn1ωn5​|ωn5ωn7

第三轮后:ωn0|ωn4​|ωn2|ωn6​|ωn1|ωn5​|ωn3|ωn7

每个数放到最后的位置上,然后不断向上还原,同时求出点值表示就可以

代码实现FFT

#include<bits/stdc++.h> 
using namespace std; 
//complex是stl自带的定义复数的容器 
typedef complex<double> cp; 
#define N 2097153 
//pie表示圆周率π 
const double pie=acos(-1); 
int n; 
cp a[N],b[N]; 
int rev[N],ans[N]; 
char s1[N],s2[N]; 
//读入优化 
int read(){ 
	int sum=0,f=1; 
	char ch=getchar(); 
	while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();} 
	while(ch>='0'&&ch<='9'){sum=(sum<<3)+(sum<<1)+ch-'0';ch=getchar();} 
	return sum*f; 
} 
//初始化每个位置最终到达的位置 
{ 
	int len=1<<k; 
	for(int i=0;i<len;i++) 
	rev[i]=(rev[i>>1]>>1)|((i&1)<<(k-1)); 
} 
	
//a表示要操作的系数,n表示序列长度 
//若flag为1,则表示FFT,为-1则为IFFT(需要求倒数) 
void fft(cp *a,int n,int flag){ 
	for(int i=0;i<n;i++) 
	{ 
	//i小于rev[i]时才交换,防止同一个元素交换两次,回到它原来的位置。 
	if(i<rev[i])swap(a[i],a[rev[i]]); 
	} 
	
	for(int h=1;h<n;h*=2)//h是准备合并序列的长度的二分之一 
	{ 
	cp wn=exp(cp(0,flag*pie/h));//求单位根w_n^1 
	for(int j=0;j<n;j+=h*2)//j表示合并到了哪一位 
		{ cp w(1,0); 
		for(int k=j;k<j+h;k++)//只扫左半部分,得到右半部分的答案 
			{ cp x=a[k]; 
			cp y=w*a[k+h]; 
			a[k]=x+y; //这两步是蝴蝶变换 
			a[k+h]=x-y; 
			w*=wn; //求w_n^k 
			} 
		} 
	} 
	//判断是否是FFT还是IFFT 
	if(flag==-1) 
	for(int i=0;i<n;i++) 
	a[i]/=n; 
} 

int main(){ 
	n=read(); 
	scanf("%s%s",s1,s2); 
	//读入的数的每一位看成多项式的一项,保存在复数的实部 
	for(int i=0;i<n;i++)a[i]=(double)(s1[n-i-1]-'0'); 
	for(int i=0;i<n;i++)b[i]=(double)(s2[n-i-1]-'0'); 
	//k表示转化成二进制的位数 
	int k=1,s=2; 
	while((1<<k)<2*n-1)k++,s<<=1; 
	init(k); 
	//FFT 把a的系数表示转化为点值表示 
	fft(a,s,1); 
	//FFT 把b的系数表示转化为点值表示 
	fft(b,s,1); 
	//FFT 两个多项式的点值表示相乘 
	for(int i=0;i<s;i++) a[i]*=b[i]; 
	//IFFT 把这个点值表示转化为系数表示 
	fft(a,s,-1); 
	//保存答案的每一位(注意进位) 
	for(int i=0;i<s;i++) { 
	//取实数四舍五入,此时虚数部分应当为0或由于浮点误差接*0 
	ans[i]+=(int)(a[i].real()+0.5); 
	ans[i+1]+=ans[i]/10; 
	ans[i]%=10; 
	} 
	
	while(!ans[s]&&s>-1)s--; 
	if(s==-1)printf("0"); 
	else for(int i=s;i>=0;i--) 
	printf("%d",ans[i]); return 0; 
}

总结

  • 泰勒展开的空间变化是局部的,因为它是在函数的某个点附*进行*似。这意味着,随着远离该点,*似的精度会下降。

  • 傅里叶展开的空间变化是全局的,因为它在整个函数定义域内进行*似。这意味着,即使远离某个点,*似的精度也相对稳定。

最后一个问题,为什么? 为什么可以使用泰勒级数或傅里叶级数来*似拟合函数?

泰勒级数和傅里叶级数都可以用来拟合函数,背后的数学原理如下:

  1. 泰勒级数:

    • 泰勒级数是利用函数在某一点(通常是原点)的导数来表示函数在该点附*的*似表达式。
    • 根据泰勒公式,任何连续可导的函数 f(x) 都可以表示为沿某点 x=a 展开的幂级数形式。这种展开形式可以用来*似表达函数。可导函数在该点处的值、一阶导数、二阶导数直到n阶导数都可以找到幂级数进行等价,那么二者在该点附*就是可以*似的
    • 泰勒级数利用了函数在某点的泰勒展开,能够逼*函数在该点附*的行为。通过保留足够多的项,可以得到良好的逼*效果。
  2. 傅里叶级数:

    • 傅里叶级数是基于周期性函数可以被一系列正弦和余弦函数的线性组合所表示的原理。
    • 任何满足一定连续条件的周期性函数,都可以表示为一系列正弦和余弦函数的级数形式,这就是傅里叶级数展开。
    • 傅里叶级数利用了周期函数可以被正弦和余弦函数的线性组合表示的性质。通过保留足够多的项,可以得到良好的逼*效果。
    • 希尔伯特空间的完备性意味着,任何L2[0,T]中的函数都可以被这组标准正交基的线性组合所逼*。也就是说,任何周期性函数都可以表示为正弦和余弦函数的傅里叶级数展开形式

在希尔伯特空间L2[0,T]中,元素指的是*方可积函数(square-integrable functions)。

具体来说:

  1. L2[0,T]表示定义在区间[0,T]上的*方可积函数构成的希尔伯特空间。

  2. *方可积函数f(x)满足:

    [0,T]|f(x)|2dx<

    也就是说,函数f(x)的*方在区间[0,T]上可以积分,且积分值是有限的。

  3. 在这个希尔伯特空间中,函数的内积定义为:

    (f,g)=[0,T]f(x)g(x)dx

    这就给L2[0,T]赋予了完备的内积空间结构。

  4. L2[0,T]中的元素可以是各种周期性函数,例如连续函数、间断函数、可微函数等,只要它们的*方在[0,T]上可积即可。

  5. 这个希尔伯特空间为傅里叶分析奠定了基础。因为任何L2[0,T]中的函数都可以表示为正弦和余弦函数的傅里叶级数展开形式。

总之,L2[0,T]中的元素指的就是定义在[0,T]上的*方可积函数,这是傅里叶分析得以展开的关键函数空间。它体现了函数分析中重要的完备性质。

还有其他的变换,Hilbert transform、Wigner distributions、the Radon Transform、our featured transformation

作者:invo

出处:https://www.cnblogs.com/invo/p/18269591

版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。

posted @   Invo1  阅读(118)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
more_horiz
keyboard_arrow_up dark_mode palette
选择主题
点击右上角即可分享
微信分享提示