分类: 教育/科学 >> 学习帮助
问题描述:
追20分
解析:
快速傅里叶变换 要用C++ 才行吧 你可以用MATLAB来实现更方便点啊
此FFT 是用VC60编写,由FFTCPP;STDAFXH和STDAFXCPP三个文件组成,编译成功。程序可以用文件输入和输出为文件。文件格式为TXT文件。测试结果如下:
输入文件:8TXT 或手动输入
8 N
1
2
3
4
5
6
7
8
输出结果为:或保存为TXT文件。(8OUTTXT)
8
(36,0)
(-4,965685)
(-4,4)
(-4,165685)
(-4,0)
(-4,-165685)
(-4,-4)
(-4,-965685)
下面为FFTCPP文件:
FFTcpp : 定义控制台应用程序的入口点。
#include "stdafxh"
#include <iostream>
#include <plex>
#include <bitset>
#include <vector>
#include <conioh>
#include <string>
#include <fstream>
using namespace std;
bool inputData(unsigned long &, vector<plex<double> >&); 手工输入数据
void FFT(unsigned long &, vector<plex<double> >&); FFT变换
void display(unsigned long &, vector<plex<double> >&); 显示结果
bool readDataFromFile(unsigned long &, vector<plex<double> >&); 从文件中读取数据
bool saveResultToFile(unsigned long &, vector<plex<double> >&); 保存结果至文件中
const double PI = 31415926;
int _tmain(int argc, _TCHAR argv[])
{
vector<plex<double> > vecList; 有限长序列
unsigned long ulN = 0; N
char chChoose = ' '; 功能选择
功能循环
while(chChoose != 'Q' && chChoose != 'q')
{
显示选择项
cout << "\nPlease chose a function" << endl;
cout << "\t1Input data manually, press 'M':" << endl;
cout << "\t2Read data from file, press 'F':" << endl;
cout << "\t3Quit, press 'Q'" << endl;
cout << "Please chose:";
输入选择
chChoose = getch();
判断
switch(chChoose)
{
case 'm': 手工输入数据
case 'M':
if(inputData(ulN, vecList))
{
FFT(ulN, vecList);
display(ulN, vecList);
saveResultToFile(ulN, vecList);
}
break;
case 'f': 从文档读取数据
case 'F':
if(readDataFromFile(ulN, vecList))
{
FFT(ulN, vecList);
display(ulN, vecList);
saveResultToFile(ulN, vecList);
}
break;
}
}
return 0;
}
bool Is2Power(unsigned long ul) 判断是否是2的整数次幂
{
if(ul < 2)
return false;
while( ul > 1 )
{
if( ul % 2 )
return false;
ul /= 2;
}
return true;
}
bool inputData(unsigned long & ulN, vector<plex<double> >& vecList)
{
题目
cout<< "\n\n\n==============================Input Data===============================" << endl;
输入N
cout<< "\nInput N:";
cin>>ulN;
if(!Is2Power(ulN)) 验证N的有效性
{
cout<< "N is invalid (N must like 2, 4, 8, ), please retry" << endl;
return false;
}
输入各元素
vecListclear(); 清空原有序列
plex<double> c;
for(unsigned long i = 0; i < ulN; i++)
{
cout << "Input x(" << i << "):";
cin >> c;
vecListpush_back(c);
}
return true;
}
bool readDataFromFile(unsigned long & ulN, vector<plex<double> >& vecList) 从文件中读取数据
{
题目
cout<< "\n\n\n===============Read Data From File==============" << endl;
输入文件名
string strfilename;
cout << "Input filename:" ;
cin >> strfilename;
打开文件
cout << "open file " << strfilename << "" <<endl;
ifstream loadfile;
loadfileopen(strfilenamec_str());
if(!loadfile)
{
cout << "\tfailed" << endl;
return false;
}
else
{
cout << "\tsucceed" << endl;
}
vecListclear();
读取N
loadfile >> ulN;
if(!loadfile)
{
cout << "can't get N" << endl;
return false;
}
else
{
cout << "N = " << ulN << endl;
}
读取元素
plex<double> c;
for(unsigned long i = 0; i < ulN; i++)
{
loadfile >> c;
if(!loadfile)
{
cout << "can't get enough infomation" << endl;
return false;
}
else
cout << "x(" << i << ") = " << c << endl;
vecListpush_back(c);
}
关闭文件
loadfileclose();
return true;
}
bool saveResultToFile(unsigned long & ulN, vector<plex<double> >& vecList) 保存结果至文件中
{
询问是否需要将结果保存至文件
char chChoose = ' ';
cout << "Do you want to save the result to file (y/n):";
chChoose = _getch();
if(chChoose != 'y' && chChoose != 'Y')
{
return true;
}
输入文件名
string strfilename;
cout << "\nInput file name:" ;
cin >> strfilename;
cout << "Save result to file " << strfilename << "" << endl;
打开文件
ofstream savefile(strfilenamec_str());
if(!savefile)
{
cout << "can't open file" << endl;
return false;
}
写入N
savefile << ulN << endl;
写入元素
for(vector<plex<double> >::iterator i = vecListbegin(); i < vecListend(); i++)
{
savefile << i << endl;
}
写入完毕
cout << "save succeed" << endl;
关闭文件
savefileclose();
return true;
}
void FFT(unsigned long & ulN, vector<plex<double> >& vecList)
{
得到幂数
unsigned long ulPower = 0; 幂数
unsigned long ulN1 = ulN - 1;
while(ulN1 > 0)
{
ulPower++;
ulN1 /= 2;
}
反序
bitset<sizeof(unsigned long) 8> bsIndex; 二进制容器
unsigned long ulIndex; 反转后的序号
unsigned long ulK;
for(unsigned long p = 0; p < ulN; p++)
{
ulIndex = 0;
ulK = 1;
bsIndex = bitset<sizeof(unsigned long) 8>(p);
for(unsigned long j = 0; j < ulPower; j++)
{
ulIndex += bsIndextest(ulPower - j - 1) ulK : 0;
ulK = 2;
}
if(ulIndex > p)
{
plex<double> c = vecList[p];
vecList[p] = vecList[ulIndex];
vecList[ulIndex] = c;
}
}
计算旋转因子
vector<plex<double> > vecW;
for(unsigned long i = 0; i < ulN / 2; i++)
{
vecWpush_back(plex<double>(cos(2 i PI / ulN) , -1 sin(2 i PI / ulN)));
}
for(unsigned long m = 0; m < ulN / 2; m++)
{
cout<< "\nvW[" << m << "]=" << vecW[m];
}
计算FFT
unsigned long ulGroupLength = 1; 段的长度
unsigned long ulHalfLength = 0; 段长度的一半
unsigned long ulGroupCount = 0; 段的数量
plex<double> cw; WH(x)
plex<double> c1; G(x) + WH(x)
plex<double> c2; G(x) - WH(x)
for(unsigned long b = 0; b < ulPower; b++)
{
ulHalfLength = ulGroupLength;
ulGroupLength = 2;
for(unsigned long j = 0; j < ulN; j += ulGroupLength)
{
for(unsigned long k = 0; k < ulHalfLength; k++)
{
cw = vecW[k ulN / ulGroupLength] vecList[j + k + ulHalfLength];
c1 = vecList[j + k] + cw;
c2 = vecList[j + k] - cw;
vecList[j + k] = c1;
vecList[j + k + ulHalfLength] = c2;
}
}
}
}
void display(unsigned long & ulN, vector<plex<double> >& vecList)
{
cout << "\n\n===========================Display The Result=========================" << endl;
for(unsigned long d = 0; d < ulN;d++)
{
cout << "X(" << d << ")\t\t\t = " << vecList[d] << endl;
}
}
下面为STDAFXH文件:
stdafxh : 标准系统包含文件的包含文件,
或是常用但不常更改的项目特定的包含文件
#pragma once
#include <iostream>
#include <tcharh>
TODO: 在此处引用程序要求的附加头文件
下面为STDAFXCPP文件:
stdafxcpp : 只包括标准包含文件的源文件
FFTpch 将成为预编译头
stdafxobj 将包含预编译类型信息
#include "stdafxh"
TODO: 在 STDAFXH 中
引用任何所需的附加头文件,而不是在此文件中引用
clc;
clear all;
%输入f、N、T、是否补零(补几个零)
f=input('Input frequency of the signal: f\n');
N=input('Input number of pointsl: N\n');
T=input('Input sampling time: T\n');
flag=input('Add zero too sampling signal or not yes=1 no=0\n');
if(flag)
ZeroNum=input('Input nmber of zeros\n');
else
ZeroNum=0;
end
%生成信号,signal是原信号。signal为采样信号。
fs=1/T;
t=0:000001:T(N+ZeroNum-1);
signal=sin(2pift);
t2=0:T:T(N+ZeroNum-1);
signal2=sin(2pift2);
if (flag)
signal2=[signal2 zeros(1, ZeroNum)];
end
%画出原信号及采样信号。
figure;
subplot(2,1,1);
plot(t,signal);
xlabel('Time(s)');
ylabel('Amplitude(volt)');
title('Singnal');
hold on;
subplot(2,1,1);
stem(t2,signal2,'r');
axis([0 T(N+ZeroNum) -1 1]);
%作FFT变换,计算其幅值,归一化处理,并画出频谱。
Y = fft(signal2,N);
Pyy = Y conj(Y) ;
Pyy=(Pyy/sum(Pyy))2;
f=0:fs/(N-1):fs/2;4
subplot(2,1,2);
bar(f,Pyy(1:N/2));
xlabel('Frequency(Hz)');
ylabel('Amplitude');
title('Frequency compnents of signal');
axis([0 fs/2 0 ceil(max(Pyy))])
grid on;
你好,这是我的回答,希望可以帮到你。
1)结果讨论
一,如果对信号进行同样点数N的FFT变换,采样频率fs越高,则可以分析越高频的信号;与此同时,采样频率越低,对于低频信号的频谱分辨率则越好。
二,假设采样点不在正弦信号的波峰、波谷、以及0电压处,频谱则会产生泄露(leakage)。
三,对于同样的采样率fs,提高FFT的点数N,则可提高频谱的分辨率。
四,如果采样频率fs小于2倍信号频率2fs(奈圭斯特定理),则频谱分析结果会出错。
五,对于(二)中泄露现象,可以通过在信号后面补零点解决。
2)程序及注解如下
%清除命令窗口及变量
clc;
clear all;
%输入f、N、T、是否补零(补几个零)
f=input('Input frequency of the signal: f\n');
N=input('Input number of pointsl: N\n');
T=input('Input sampling time: T\n');
flag=input('Add zero too sampling signal or not yes=1 no=0\n');
if(flag)
ZeroNum=input('Input nmber of zeros\n');
else
ZeroNum=0;
end
%生成信号,signal是原信号。signal为采样信号。
fs=1/T;
t=0:000001:T(N+ZeroNum-1);
signal=sin(2pift);
t2=0:T:T(N+ZeroNum-1);
signal2=sin(2pift2);
if (flag)
signal2=[signal2 zeros(1, ZeroNum)];
end
%画出原信号及采样信号。
figure;
subplot(2,1,1);
plot(t,signal);
xlabel('Time(s)');
ylabel('Amplitude(volt)');
title('Singnal');
hold on;
subplot(2,1,1);
stem(t2,signal2,'r');
axis([0 T(N+ZeroNum) -1 1]);
%作FFT变换,计算其幅值,归一化处理,并画出频谱。
Y = fft(signal2,N);
Pyy = Y conj(Y) ;
Pyy=(Pyy/sum(Pyy))2;
f=0:fs/(N-1):fs/2;4
subplot(2,1,2);
bar(f,Pyy(1:N/2));
xlabel('Frequency(Hz)');
ylabel('Amplitude');
title('Frequency compnents of signal');
axis([0 fs/2 0 ceil(max(Pyy))])
grid on;
祝你好运!
我可以帮助你,你先设置我最佳答案后,我百度Hii教你。
以上就是关于求FFT的c语言程序全部的内容,包括:求FFT的c语言程序、频率抽取法FFT的程序、求用C语言实现FFT变换的程序(见下面)等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)