如何在apache FFT中使用复系数

时间:2016-11-23 23:06:04

标签: java apache math fft jfreechart

我正在使用Apache Commons库的FFT基本示例。我有两个班:

   public class Fourier {
    private static XYSeries data;
    private static XYSeriesCollection collection;

    Fourier(){
        collection =new XYSeriesCollection();
        createSquare();
        createFourier();
        showGraph();
    }

    private static void createSquare(){
        data=new XYSeries("Dati");
        for(double i=-8;i<8;i+=1d/128){
            data.add(i,((i<-4||(i<4&&i>0)?1:0)));
            //data.add(i,(i<0?i+1:-i+1));
        }
        collection.addSeries(data);
    }

    private static void createFourier(){
        double[] arrayFourier= new double[data.getItemCount()];
        for(int i=0;i<data.getItemCount();i++){
            arrayFourier[i]=data.getDataItem(i).getYValue();
        }
        FastFourierTransformer transformer=new FastFourierTransformer(DftNormalization.STANDARD);
        Complex[] coeff=transformer.transform(arrayFourier, TransformType.INVERSE);
        double norm = 0;
        for(Complex Z: coeff){
            System.out.println(Z.abs()+"\t"+Z.toString());
            norm+=(Z.abs())*(Z.abs());
        }
        System.out.println(norm);

        XYSeries fourier=new XYSeries("Fourier");
        FourierSeries series=new FourierSeries(coeff,8);
        for(double i=data.getMinX();i<data.getMaxX();i+=0.05){
            fourier.add(i,series.getSeries(i));
        }
        collection.addSeries(fourier);

    }

    private static void showGraph(){
        JFreeChart chart = ChartFactory.createXYLineChart("Fourier", "x", "f(x)", collection, PlotOrientation.VERTICAL, true, false, false);
        ChartFrame window=new ChartFrame("Fourier", chart, false);
        window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        window.pack();
        window.setVisible(true);
    }

    public static void main(String[] args) {
        Thread t=new Thread(new Runnable() {

            @Override
            public void run() {
                new Fourier();
                try {
                    Thread.sleep(60000);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                System.exit(0);
            }
        });
        t.start();
    }

}

和另一个

public class FourierSeries {
    Complex[] coeff;
    double T;

    public FourierSeries(Complex[] coeff, double T) {
        this.coeff=coeff;
        this.T=T;
    }

    public double getSeries(double x){
        double k=Math.PI/T;
        double value=0; //primo coefficiente
        int i=0;
        /*for(Complex iter:coeff){
            if (i!=0&&i<coeff.length/2.) {
                if (i % 2 == 0) {
                    value += iter.abs() * Math.cos(k * i * x);
                    System.out.println(iter.abs()+"cos"+i);
                } else {
                    value += iter.abs() * Math.sin(k * i * x); //npari (i dispari) modulo*cos()
                    System.out.println(iter.abs()+"sin"+i);
                }
            }
            i++;
        }*/
        for (Complex iter : coeff) {
            if(i<coeff.length/2.)   
            value+=iter.getReal()*Math.cos(x*k*i)+iter.getImaginary()*Math.sin(x*k*i);
        i++;
        }
        return value;
    }
}

我在createSquare()方法中引入了一个函数(方波)。

我按顺序执行以下操作:

我执行FFT。

你能解释一下transform.transform(array, TransformType)返回的数组是如何组成的吗?

为什么没有正确绘制傅立叶级数?

反向序列是正确的方波,其频率与初始波相同,但在y轴上没有正确缩放。怎么了?这是输出: This is the output

1 个答案:

答案 0 :(得分:2)

在将傅立叶级数的复数形式转换为实数形式时,必须以不同方式处理常数项。或者在有问题的代码的情况下,你必须将非常数系数校正2倍。这样你得到的结果是0.5 +- 0.5,而不是目前的0.5 +- 0.25。< / p>

您正在使用逆变换,其中结果系数可以解释为

f(x) approx sum(m = -N/2+1, N/2-1) c[k]*exp(-i*m*k*x)

对于索引m>=1,您组合了两个复杂的共轭术语对,得到的实数项是c[k]=a+ib

(a+i*b)*exp(-i*m*k*x) + (a-i*b)*exp(+i*m*k*x) 

= 2*a*cos(m*k*x) + 2*b*sin(m*k*x)

你的傅里叶级数计算应该如此

    value = coeff[0].getReal();
    for (int m=1; m<coeff.length/2; m++) {
        value += 2*coeff[m].getReal()*Math.cos(x*k*m) 
               + 2*coeff[m].getImaginary()*Math.sin(x*k*m);
    }