傅里叶级数

一、理论基础

  任何周期函数都可以看成是不同振幅,不同相位的正弦波的叠加。

1. 三角函数系的正交性:

   三角函数系:
在这里插入图片描述

         三角函数系中任意两个不同的函数之积在[-π,π]上的积分为0。

在这里插入图片描述
在这里插入图片描述

2. 将周期函数展开为三角级数

   假设有周期函数 f(x)=f(x+2π),周期为2*PI;则函数可以展开为下面的三角级数:

      在这里插入图片描述

书中展示的公式为: 在这里插入图片描述
以上两个公式本质上是形同的,下面给给出求解上式参数的过程:在这里插入图片描述

在这里插入图片描述

2 求取参数an,bn

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3. 离散傅里叶变换:

在这里插入图片描述

     已知,连续的傅里叶变换公式为:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

4. 快速傅里叶变化(FFT):

   离散傅里叶变换的计算量是巨大的。对一幅 MxN 的图像,他需要M^2 N^2 次的复数乘法和加法。因此,一般使用离散傅里叶变换的快速算法——快速傅里叶变换

4.1 算法思想:

复数域中将一般形式转化为指数形式的公式推导:

在这里插入图片描述

2. n次单位根:

         在这里插入图片描述

n次单位根在复数域相当于是一个:

         幅角为: 2π/n

         长度为: 1

                         的虚数。

在这里插入图片描述

3. n次单位根的性质:

在这里插入图片描述
在这里插入图片描述

4.2.多项式系数表示法:

     在这里插入图片描述

4.3.多项式点值表示法:

  因为n次函数可由n+1个点确定下来(可以将每一个点列一个n次方程)。
在这里插入图片描述
由上面的式子可以唯一的确定一组多项式系数,a0,a1,a2,…an,因此多项式可以使用下面的点值表示法:
       在这里插入图片描述



点值表示法的乘法运算:

  两个多项式P,Q分别取点(x,y1)和(x,y2) ,P*Q就会去点(x,y1*y2);

在这里插入图片描述

DFT(离散傅里叶变换):

  求多项式的点值表示法:

     想要求出一个多项式的点值表示法,需要选出n+1个数分别带入到多项式里面。带入一个数的复杂度是Θ(n) Θ(n)的,那么总复杂度就是Θ(n2) 。因为单位根有下面的性质,所以可以尝试去n次单位根来作为n+1个数。
在这里插入图片描述
在这里插入图片描述
                    在这里插入图片描述
在这里插入图片描述

FFT算法:

在这里插入图片描述
在这里插入图片描述

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace DFT与FFT算法
{
    /// <summary>
    /// 实现复数运算的类
    /// </summary>
    class complex
    {
        //复数为a+bi
        //其中real为实部字段
        private double real;
        /// <summary>
        /// 复数的实部(属性)
        /// </summary>
        public double Real
        {
            get { return real; }
            set { real = value; }
        }
        //image为虚部字段。
        private double image;
        /// <summary>
        /// 复数的虚部(属性)
        /// </summary>
        public double Image
        {
            get { return image; }
            set { image = value; }
        }

        /// <summary>
        /// 默认构造函数
        /// </summary>
        public complex ()
            :this(0,0)
        {
        }
        /// <summary>
        /// 只有实部的构造函数
        /// </summary>
        /// <param name="real"></param>
        public complex(double real)
            : this(real, 0)
        {

        }
        /// <summary>
        /// 由实部和虚部创建的构造函数
        /// </summary>
        /// <param name="real"></param>
        /// <param name="image"></param>
        public complex(double real,double image)
        {
            this.real = real;
            this.image = image;
        }

        /// <summary>
        /// 重载加法符号
        /// </summary>
        /// <param name="c1"></param>
        /// <param name="c2"></param>
        /// <returns></returns>
        public static complex operator +(complex c1,complex c2)
        {
            return new complex(c1.real + c2.real, c1.image + c2.image);
        }
        /// <summary>
        /// 重载减法
        /// </summary>
        /// <param name="c1"></param>
        /// <param name="c2"></param>
        /// <returns></returns>
        public static complex operator -(complex c1, complex c2)
        {
            return new complex(c1.real - c2.real, c1.image - c2.image);
        }
        
        /// <summary>
        /// 重载乘法
        /// </summary>
        /// <param name="c1"></param>
        /// <param name="c2"></param>
        /// <returns></returns>
        public static complex operator *(complex c1, complex c2)
        {
            return new complex(c1.real * c2.real - c1.image * c2.image, c1.image * c2.real + c1.real * c2.image);
        }

        /// <summary>
        /// 复数的模
        /// </summary>
        /// <returns></returns>
        public double ToModul()
        {
            return Math.Sqrt(real * real + image * image);
        }

        /// <summary>
        /// 重载ToString 方法
        /// </summary>
        /// <returns></returns>
        public override string ToString()
        {
           if(Real==0 && Image ==0)
           {
               return string.Format("{0}", 0);
           }
           if(Real==0 && (Image !=1 && Image !=-1))
           {
               return string.Format("{0} i", Image);
           }

           if(Image==0)
           {
                return string.Format("{0}", Real);
           }
           if(Image==1)
           {
               return string.Format("i");
           }
           if (Image == -1)
           {
               return string.Format("- i");
           }
           if (Image < 0)
           {
               return string.Format("{0} - {1} i", Real, -Image);
           }
           return string.Format("{0} + {1} i", Real, Image);
        }

    }
}

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace DFT与FFT算法
{
    /// <summary>
    /// 实现运算
    /// </summary>
    class DFT
    {
        /// <summary>
        /// 求复数数组的模数组
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public static double[] Cmp2Mdl(complex[] input)
        {
            //确定模数组的长度
            double[] output = new double[input.Length];
            //对复数求模
            for(int i=0;i<input.Length;i++)
            {
                if(input[i].Real>0)
                {
                    output[i] = -input[i].ToModul();
                }
                else
                {
                    output[i] = input[i].ToModul();
                }
            }
            return output;
        }

        /// <summary>
        /// 傅里叶变换以及傅里叶反变换
        /// </summary>
        /// <param name="input"></param>
        /// <param name="invert,false FFT变换,true  IFFT变换"></param>
        /// <returns></returns>
        public static complex[] FFT(double[] input,bool invert)
        {
            //由输入序列确定输出序列的长度
            complex[] output = new complex[input.Length];

            ///将输入的实数数组转换为复数数组
            for(int i=0;i<input.Length;i++)
            {
                output[i]=new complex(input[i]);
            }

            //返回FFT或者IFFT序列
            return output = FFT(output, invert);
        }
        /// <summary>
        /// 傅里叶变换以及傅里叶反变换,递归蝶形运算
        /// </summary>
        /// <param name="input"></param>
        /// <param name="invert,false FFT变换,true  IFFT变换"></param>
        /// <returns></returns>
        public static complex[] FFT(complex[] input,bool invert)
        {
            ///如果输入序列只有一个元素,输出这个元素并返回
            if(input.Length==1)
            {
                return new complex[] { input[0]};
            }

            //输入序列的长度
            int length = input.Length;
            //输入序列长度的一半
            int half = length / 2;

            //由输入序列的长度确定输出序列的长度
            complex[] output = new complex[length];

            //正变换旋转因子的基数
            double fac = -2.0 * Math.PI / length;
            //反变换旋转因子的基数是正变换的相反数
            if(invert)
            {
                fac = -fac;
            }

            //序列中下标中为偶数的点
            complex[] evens = new complex[half];

            for(int i=0;i<half;i++)
            {
                evens[i] = input[2 * i];
            }
            //求偶数点FFT或IFFT的结果,递归实现多级蝶形运算
            complex[] evenResult = FFT(evens,invert);

            //序列中下标为奇数的点
            complex[] odds=new complex[half];
            for(int i=0;i<half;i++)
            {
                odds[i] = input[2 * i + 1];
            }
            //求奇数点FFT或IFFT的结果,递归实现多级蝶形运算
            complex[] oddResult = FFT(odds, invert);

            for(int k=0;k<half;k++)
            {
                ///旋转因子
                double fack = fac * k;

                //进行蝶形运算
                complex oddpart = oddResult[k] * new complex(Math.Cos(fack), Math.Sin(fack));
                output[k] = evenResult[k] + oddpart;
                output[k + half] = evenResult[k] - oddpart;
            }

            //返回FFT或IFFT的结果
            return output;
        }

    }

}

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace DFT与FFT算法
{
    class Program
    {
        static void Main(string[] args)
        {
            double[] input = {
                2,3,4,5,6,7,8,9
                //0.0928,0.0353,0.6124,0.6085,0.0158,0.0164,0.1901,0.5869
                             };
            complex[] output_complex = new complex[input.Length];
            output_complex = DFT.FFT(input, false);//正变换
            Console.WriteLine();
            Console.WriteLine("i\treal\timage");
            Console.WriteLine();
            for (int i = 0; i < input.Length; i++)
            {
                Console.WriteLine("{0}\t{1}\t{2}", i, output_complex[i].Real, output_complex[i].Image);
            }

            Console.WriteLine("------------------------------------------");
            output_complex = DFT.FFT(output_complex, true);//反变换
            Console.WriteLine();
            Console.WriteLine("i\treal\timage");
            Console.WriteLine();
            for (int i = 0; i < input.Length; i++)
            {
                Console.WriteLine("{0}\t{1}\t{2}", i, output_complex[i].Real, output_complex[i].Image);
            }
            input = DFT.Cmp2Mdl(output_complex);

            Console.WriteLine("------------------------------------------");

            //反变换完了除以数据长度
            for (int i = 0; i < input.Length; i++)
            {
                input[i] = -input[i] / input.Length;
            }
            foreach (double a in input)
            {
                Console.WriteLine("{0}", a);
            }
            Console.ReadKey();
        }
    }
}

  • 81
    点赞
  • 357
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值