首页 新闻 会员 周边

共轭对称复序列的快速傅里叶反变换

0
[已解决问题] 解决于 2023-07-25 15:21

这个程序和书上的一样,存在错误!运算结果与书上实列结果不符!能否更正!谢谢你!

redstone8415的主页 redstone8415 | 菜鸟二级 | 园豆:202
提问于:2023-07-20 16:25
< >
分享
最佳答案
0

很抱歉你遇到了问题。关于共轭对称复序列的快速傅里叶反变换(IFFT),在实现中确实可能会出现一些细微的错误。这里我提供一个简单的C#实现来进行参考。请注意,这只是一个基本的示例,实际应用中可能需要根据具体的情况进行调整。

csharp
Copy code
using System;
using System.Numerics;

public class FFT
{
// 快速傅里叶反变换
public static Complex[] IFFT(Complex[] input)
{
int N = input.Length;

    // 反转输入序列
    Complex[] reversedInput = new Complex[N];
    for (int i = 0; i < N; i++)
    {
        int reversedIndex = ReverseBits(i, N);
        reversedInput[reversedIndex] = input[i];
    }

    // 做傅里叶变换
    Complex[] output = FFT(reversedInput);

    // 取共轭并缩放
    for (int i = 0; i < N; i++)
    {
        output[i] = Complex.Conjugate(output[i]) / N;
    }

    return output;
}

// 傅里叶变换(快速傅里叶变换)
public static Complex[] FFT(Complex[] input)
{
    int N = input.Length;

    if (N == 1)
    {
        return new Complex[] { input[0] };
    }

    // 奇偶分解
    Complex[] even = new Complex[N / 2];
    Complex[] odd = new Complex[N / 2];
    for (int k = 0; k < N / 2; k++)
    {
        even[k] = input[2 * k];
        odd[k] = input[2 * k + 1];
    }

    // 递归计算奇偶分量的DFT
    Complex[] q = FFT(even);
    Complex[] r = FFT(odd);

    // 合并子问题的解
    Complex[] output = new Complex[N];
    for (int k = 0; k < N / 2; k++)
    {
        Complex t = Complex.FromPolarCoordinates(1, -2 * Math.PI * k / N) * r[k];
        output[k] = q[k] + t;
        output[k + N / 2] = q[k] - t;
    }

    return output;
}

// 计算反转位
private static int ReverseBits(int x, int N)
{
    int result = 0;
    for (int i = 0; i < N; i++)
    {
        result = (result << 1) | (x & 1);
        x >>= 1;
    }
    return result;
}

}

public class Program
{
public static void Main()
{
Complex[] input = new Complex[]
{
new Complex(1, 0),
new Complex(2, 0),
new Complex(3, 0),
new Complex(4, 0)
};

    Complex[] output = FFT.IFFT(input);

    Console.WriteLine("IFFT Result:");
    foreach (Complex value in output)
    {
        Console.WriteLine(value);
    }
}

}
这是一个简单的共轭对称复序列的快速傅里叶反变换的示例程序,你可以根据自己的需求进行调整和扩展。如果问题仍然存在,请提供更多的细节,我将尽力帮助你解决。

Regenerate response

奖励园豆:5
Technologyforgood | 大侠五级 |园豆:5992 | 2023-07-23 23:20

谢谢!我测试一下!谢谢你的热忱!

redstone8415 | 园豆:202 (菜鸟二级) | 2023-07-24 06:32


数组越界:reversedindex=8, >N=4!

redstone8415 | 园豆:202 (菜鸟二级) | 2023-07-24 09:16

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Numerics;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Windows.Forms.DataVisualization.Charting;

namespace real_sequence_conjugate_symmetry_inverse_transformation_F
{
public partial class Form1 : Form
{

    public Form1()
    {
        InitializeComponent();
    }

    public class FFT_IFFT
    {    
        public static Complex[] IFFT(Complex[] x)
        {
            int N = x.Length;
            // 如果输入序列长度为1,则直接返回
            if (N == 1)
            {
                return new Complex[] { x[0] };
            }
            // 计算偶数和奇数部分
            Complex[] even = new Complex[N / 2];
            Complex[] odd = new Complex[N / 2];
            for (int k = 0; k < N / 2; k++)
            {
                even[k] = x[2 * k];
                odd[k] = x[2 * k + 1];
            }
            // 递归计算偶数和奇数部分的傅里叶反变换
            Complex[] q = IFFT(even);
            Complex[] r = IFFT(odd);

            // 计算结果
            Complex[] IFFToutput = new Complex[N];
            for (int k = 0; k < N / 2; k++)
            {
                double kth = -2 * k * Math.PI / N;
                Complex wk = new Complex(Math.Cos(kth), Math.Sin(kth));
                IFFToutput[k] = q[k] + wk * r[k];
                IFFToutput[k + N / 2] = q[k] - wk * r[k];
            }
            return IFFToutput;
        }
        // 傅里叶变换(快速傅里叶变换)
        public static Complex[] FFT(Complex[] input)
        {
            int N = input.Length;

            if (N == 1)
            {
                return new Complex[] { input[0] };
            }

            // 奇偶分解
            Complex[] even = new Complex[N / 2];
            Complex[] odd = new Complex[N / 2];
            for (int k = 0; k < N / 2; k++)
            {
                even[k] = input[2 * k];
                odd[k] = input[2 * k + 1];
            }

            // 递归计算奇偶分量的DFT
            Complex[] q = FFT(even);
            Complex[] r = FFT(odd);

            // 合并子问题的解
            Complex[] FFToutput = new Complex[N];
            for (int k = 0; k < N / 2; k++)
            {
                Complex t = Complex.FromPolarCoordinates(1, -2 * Math.PI * k / N) * r[k];
                FFToutput[k] = q[k] + t;
                FFToutput[k + N / 2] = q[k] - t;
            }

            return FFToutput;
        }
        // 计算反转位
        private static int ReverseBits(int x, int N)
        {
            int result = 0;
            for (int i = 0; i < N; i++)
            {
                result = (result << 1) | (x & 1);
                x >>= 1;
            }
            return result;
        }
    }
    private void btCreaatData_Click(object sender, EventArgs e)
    {
        textBox1.Clear();
        Original_Data.Series[0].Points.Clear();
        textBox1.Clear();
        FFT_Result.Series[0].Points.Clear();
        textBox1.Clear();
        IFFT_Result.Series[0].Points.Clear();
        int i, N = 32;
        Complex[] x = new Complex[N];
        for (i = 0; i < N; i++)
        {
            x[i] = new Complex(Math.Round((Math.Exp(-i / 15.0) * Math.Sin(6.2831853 * i / 16.0)), 8), 0);
        }
        Console.WriteLine("Original Sewuence:\n");
        for (i = 0; i < N; i++)
        {
            this.Original_Data.Series[0].Points.AddXY(x[i].Real, x[i].Imaginary);
            textBox1.AppendText(x[i].Real.ToString("f3") + "  J " + x[i].Imaginary.ToString("f3") + "\t\n");
        }
        Complex[] FFT_output = FFT_IFFT.FFT(x);
        for (i = 0; i < N; i++)
        {
            this.FFT_Result.Series[0].Points.AddXY(FFT_output[i].Real, FFT_output[i].Imaginary);
            textBox2.AppendText(FFT_output[i].Real.ToString("f3") + "  J " + FFT_output[i].Imaginary.ToString("f3") + "\t\n");
        }
        Complex[] IFFT_output = FFT_IFFT.IFFT(FFT_output);
        Console.WriteLine("IFFT Result Output:\n");
        for (i = 0; i < N; i++)
        {
            this.IFFT_Result.Series[0].Points.AddXY(IFFT_output[i].Real, IFFT_output[i].Imaginary);
            textBox3.AppendText(IFFT_output[i].Real.ToString("f3") + "  J " + IFFT_output[i].Imaginary.ToString("f3") + "\t\n");
        }
    }
}

}

redstone8415 | 园豆:202 (菜鸟二级) | 2023-07-25 09:56

实序列,FFT后好像有共轭对称性,IFFT完全错误,没有变回实序列!

redstone8415 | 园豆:202 (菜鸟二级) | 2023-07-25 09:59

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Numerics;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Windows.Forms.DataVisualization.Charting;

namespace real_sequence_conjugate_symmetry_inverse_transformation_F
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private static Complex[] FFT(Complex[] input)
{
///输入序列的长度
int length = input.Length;
///输入序列的长度的一半
int half = length / 2;
///输入序列只有一个元素,输出这个元素并返回
if (input.Length == 1)
{
return new Complex[] { input[0] };
}
///有输入序列的长度确定输出序列的长度
Complex[] output = new Complex[length];
///正变换旋转因子的基数
double fac = -2.0 * Math.PI / length;

        ///序列中下标为偶数的点
        Complex[] evens = new Complex[half];
        for (int i = 0; i < half; i++)
        {
            evens[i] = input[2 * i];
        }
        ///求偶数点FFT或IFFT的结果,递归实现多级蝶形运算
        Complex[] evenResult = FFT(evens);
        ///序列中下标为奇数的点
        Complex[] odds = new Complex[half];
        for (int i = 0; i < half; i++)
        {
            odds[i] = input[2 * i + 1];
        }
        ///求偶数点FFT或IFFT的结果,递归实现多级蝶形运算
        Complex[] oddResult = FFT(odds);
        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的结果
        return output;
    }

    private static Complex[] IFFT(Complex[] input)
    {
        ///输入序列的长度
        int length = input.Length;
        ///输入序列的长度的一半
        int half = length / 2;
        ///输入序列只有一个元素,输出这个元素并返回
        if (input.Length == 1)
        {
            return new Complex[] { input[0] };
        }
        ///有输入序列的长度确定输出序列的长度
        Complex[] output = new Complex[length];
        ///正变换旋转因子的基数
        double fac = 2.0 * Math.PI / length;

        ///序列中下标为偶数的点
        Complex[] evens = new Complex[half];
        for (int i = 0; i < half; i++)
        {
            evens[i] = input[2 * i];
        }
        ///求偶数点FFT或IFFT的结果,递归实现多级蝶形运算
        Complex[] evenResult = IFFT(evens);
        ///序列中下标为奇数的点
        Complex[] odds = new Complex[half];
        for (int i = 0; i < half; i++)
        {
            odds[i] = input[2 * i + 1];
        }
        ///求偶数点IFFT的结果,递归实现多级蝶形运算
        Complex[] oddResult = IFFT(odds);
        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;
        }
        ///返回IFFT的结果
        return output;
    }


    private void btCreaatData_Click(object sender, EventArgs e)
    {
        textBox1.Clear();
        Original_Date.Series[0].Points.Clear();
        textBox2.Clear();
        FFT_Result.Series[0].Points.Clear();
        textBox3.Clear();
        IFFT_Result.Series[0].Points.Clear();
        int i, N = 32;
        Complex[] x = new Complex[N];
        for (i = 0; i < N; i++)
        {
            x[i] = new Complex(Math.Round((Math.Exp(-i / 15.0) * Math.Sin(6.2831853 * i / 16.0)), 8), 0);
        }
        Console.WriteLine("Original Sewuence:\n");
        for (i = 0; i < N; i++)
        {
            this.Original_Date.Series[0].Points.AddXY(x[i].Real, x[i].Imaginary);
            textBox1.AppendText(x[i].Real.ToString("f3") + "  J " + x[i].Imaginary.ToString("f3") + "\t\n");
        }
        Complex[] FFT_output =FFT(x);
        for (i = 0; i < N; i++)
        {
            this.FFT_Result.Series[0].Points.AddXY(FFT_output[i].Real, FFT_output[i].Imaginary);
            textBox2.AppendText(FFT_output[i].Real.ToString("f3") + "  J " + FFT_output[i].Imaginary.ToString("f3") + "\t\n");
        }
        Complex[] IFFT_output =/* FFT_IFFT.I*/IFFT(FFT_output);
        Console.WriteLine("IFFT Result Output:\n");
        for (i = 0; i < N; i++)
        {
            this.IFFT_Result.Series[0].Points.AddXY(IFFT_output[i].Real/N, IFFT_output[i].Imaginary/N);
            textBox3.AppendText((IFFT_output[i].Real/N).ToString("f3") + "  J " + (IFFT_output[i].Imaginary/N).ToString("f3") + "\t\n");

        }
    }
}

}


OK! 实序例FFT后共轭对称,IFFT后与原实序列一致!

redstone8415 | 园豆:202 (菜鸟二级) | 2023-07-25 15:18
其他回答(1)
0

下面是一个使用C#实现共轭对称复序列的快速傅里叶反变换的示例代码:

using System;
using System.Numerics;

public class FFT
{
    // 快速傅里叶反变换
    public static Complex[] IFFT(Complex[] x)
    {
        int N = x.Length;

        // 如果输入序列长度为1,则直接返回
        if (N == 1)
        {
            return new Complex[] { x[0] };
        }

        // 计算偶数和奇数部分
        Complex[] even = new Complex[N / 2];
        Complex[] odd = new Complex[N / 2];
        for (int k = 0; k < N / 2; k++)
        {
            even[k] = x[2 * k];
            odd[k] = x[2 * k + 1];
        }

        // 递归计算偶数和奇数部分的傅里叶反变换
        Complex[] q = IFFT(even);
        Complex[] r = IFFT(odd);

        // 计算结果
        Complex[] y = new Complex[N];
        for (int k = 0; k < N / 2; k++)
        {
            double kth = -2 * k * Math.PI / N;
            Complex wk = new Complex(Math.Cos(kth), Math.Sin(kth));
            y[k] = q[k] + wk * r[k];
            y[k + N / 2] = q[k] - wk * r[k];
        }

        return y;
    }

    // 打印复数序列
    public static void PrintComplexArray(Complex[] array)
    {
        foreach (Complex num in array)
        {
            Console.WriteLine(num);
        }
    }

    // 测试代码
    public static void Main(string[] args)
    {
        Complex[] x = new Complex[] { new Complex(1, 0), new Complex(2, 0), new Complex(3, 0), new Complex(4, 0) };

        Console.WriteLine("原始序列:");
        PrintComplexArray(x);

        Complex[] y = IFFT(x);

        Console.WriteLine("反变换结果:");
        PrintComplexArray(y);
    }
}

以上代码实现了共轭对称复序列的快速傅里叶反变换。在测试代码中,我们定义了一个长度为4的复数序列,并对其进行反变换。可以根据需要修改输入序列 x 的长度和元素值。运行代码后,将会输出原始序列和反变换结果。

请注意,上述代码仅实现了共轭对称复序列的快速傅里叶反变换,如果需要处理其他类型的序列,可能需要进行相应的修改。

lanedm | 园豆:2381 (老鸟四级) | 2023-07-22 11:55
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册