FFT实现(java),验证(matlab)

java代码

compex类

public class Complex {
    private double a, b;
    public Complex(){
        this.a = 0.0;
        this.b = 0.0;
    }
    public Complex(double a, double b){
        this.a = a;
        this.b = b;
    }
    public Complex(Complex C){
        this.a = C.a;
        this.b = C.b;
    }
    public double getRealPart(){ //返回实部
        return a;
    } // 获取实部
    public double getImaginaryPart(){
        return b;
    } //获取虚部
    public String toString(){
        if(b != 0) {
            if (a == 0)
                return b + "i";
            else
                return a + "+" + b + "i";
        }
        else
            return a + "";

    }  //字符串表示复数
    public Complex plus(Complex C){
        if (C == null){
            System.out.println("对象为null");
            return new Complex();
        }
        return new Complex(this.a + C.a, this.b + C.b);
    } // 加法
    public Complex minus(Complex C){
        if (C == null){
            System.out.println("对象为null");
            return new Complex();
        }
        return new Complex(this.a - C.a, this.b - C.b);
    } // 减法
    public Complex multiply(Complex C){
        if (C == null){
            System.out.println("对象为null");
            return new Complex();
        }
        double newa = this.a * C.a - this.b * C.b;
        double newb = this.a * C.b + this.b * C.a;
        return new Complex(newa, newb);
    } // 乘法
    public Complex divide(Complex C){
        if (C == null){
            System.out.println("对象为null");
            return new Complex();
        }
        if(C.a == 0 && b == 0){
            System.out.println("除数不能为0!");
            return new Complex();
        }
        double newa = (this.a * C.a + this.b * C.b) / (C.a * C.a + C.b * C.b);
        double newb = (this.a * C.a - this.b * C.b) / (C.a * C.a + C.b * C.b);
        return new Complex(newa, newb);
    } // 除法

    public static void main(String[] args) {
        Complex x = new Complex(3,4);
        Complex y = new Complex(5,7);
        System.out.println("x:" + x.toString());
        System.out.println("y:" + y.toString());
        System.out.println("(x+y) = " + x.plus(y).toString());
        System.out.println("(x-y) = " + x.minus(y).toString());
        System.out.println("(x*y) = " + x.multiply(y).toString());
        System.out.println("(x/y) = " + x.divide(y).toString());
    }


}

 

FFT

import java.io.*;

public class FFT {
    public static void CreateSignal(int length, Complex[] x){
        double Fs = 1000; // 采样频率
        double T = 1 / Fs; // 采样周期
        System.out.println("产生幅值为 0.7 的 50 Hz正弦量和幅值为 1 的 120 Hz正弦量(一共"+length+"个)");
        for (int i = 0; i < length; i++) {
            // 产生幅值为0.7的50Hz正弦量和幅值为1的120 Hz正弦量。
            double S = 0.7 * Math.sin(2 * Math.PI * 50 * i * T) + Math.sin(2 * Math.PI * 120 * i * T);
            x[i] = new Complex(S, 0);
        }
    }
    public static Complex[] dft(Complex[] x) {
        int n = x.length;

        if (n == 1)  // exp(-2pi*j) = cos(-2pi)+j * sin(-2pi) = 1
            return x;

        Complex[] result = new Complex[n];
        for (int i = 0; i < n; i++) {
            result[i] = new Complex();
            for (int k = 0; k < n; k++) {
                double p = -2 * k * Math.PI * i / n ;
                // 欧拉公式e^(-j (2pi * k * i) / N) = cos(-2pi * k * i / N) + i*sin(-2pi * k * i/ N)
                Complex e = new Complex(Math.cos(p), Math.sin(p));
                result[i] = result[i].plus(x[k].multiply(e));
            }
        }
        return result;
    }
    public static Complex[] fft(Complex[] x) {
        int n = x.length;
        if (n == 1)
            return x;

        // 信号数为奇数不满足对称性,使用dft计算
        if (n % 2 != 0)
            return dft(x);

        // 取下标为偶数的信号
        Complex[] even = new Complex[n / 2];
        for (int i = 0; i < n / 2; i++) {
            even[i] = x[2 * i];
        }
        Complex[] evenValue = fft(even);

        // 取下标为奇数的信号
        Complex[] odd = new Complex[n / 2];
        for (int i = 0; i < n / 2; i++) {
            odd[i] = x[2 * i + 1];
        }
        Complex[] oddValue = fft(odd);

        // 相加
        Complex[] result = new Complex[n];
        for (int i = 0; i < n / 2; i++) {
            double p = -2 * Math.PI * i / n ;
            Complex e = new Complex(Math.cos(p), Math.sin(p));
            result[i] = evenValue[i].plus(e.multiply(oddValue[i]));
            result[i + n / 2] = evenValue[i].minus(e.multiply(oddValue[i]));
        }
        return result;
    }
    public static void writeText(String filename,Complex[]result) {
        try {
            File writeName = new File(filename); // 相对路径,如果没有则要建立一个新文件
            writeName.createNewFile(); // 创建新文件,有同名的文件的话直接覆盖
            try (FileWriter writer = new FileWriter(writeName);
                 BufferedWriter out = new BufferedWriter(writer)
            ) {
                for (int i = 0; i < result.length; i++) {
                    out.write(result[i].toString()+"\n"); // \r\n即为换行
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        System.out.println("数据写入成功!");
    }

    public static void main(String[] args) {
        int length = 1500;
        Complex[] x = new Complex[length];
        Complex[] result;
        CreateSignal(length, x);

        long start1 = System.currentTimeMillis();
        result = dft(x);
        long end1 = System.currentTimeMillis();

        long start2 = System.currentTimeMillis();
        result = fft(x);
        long end2 = System.currentTimeMillis();


        System.out.println("FFT结果:");
        for (int i = 0; i < length; i++) {
            System.out.println("第"+(i+1)+"个数据:"+result[i].toString());
        }
        System.out.println("------------------------------------------------");

        System.out.println("DFT运行时间: " + (end1 - start1) + "ms");
        System.out.println("FFT运行时间: " + (end2 - start2) + "ms");

        String filename = "C:\\Users\\xxx\\Desktop\\算法课程\\xxx\\shuju.txt";
        writeText(filename, result);

    }
}

 

结果

 

 

 

 

 验证(matlab)

clc
clear
close all;
Fs = 1000;                   
T = 1/Fs;             
L = 1500;          
t = (0:L-1)*T; 
S = 0.7*sin(2*pi*50*t) + sin(2*pi*120*t);

%matlab fft函数
Y = fft(S);
%导入java产生的数据
file = fopen('shuju.txt');
p = textscan(file,'%s');
pp =[str2double(p{:})]';

P2 = abs(Y/L);
P1 = P2(1:L/2+1);
P1(2:end-1) = 2*P1(2:end-1);
f = Fs*(0:(L/2))/L;
subplot(1,2,1)
plot(f,P1) 
hold on;
title('FFT of Matlab')
xlabel('f (Hz)')
ylabel('|P1(f)|')

X2 = abs(pp/L);
X1 = X2(1:L/2+1);
X1(2:end-1) = 2*X1(2:end-1);
f1 = Fs*(0:(L/2))/L;
subplot(1,2,2);
plot(f1,X1) 
title('FFT of Java')
xlabel('f (Hz)')
ylabel('|X1(f)|')
hold off;

结果:

 

 

 

 

posted @ 2020-04-12 14:52  德狗咬不过狗  阅读(711)  评论(0编辑  收藏  举报