fft
fft函数参数说明:
参考:https://blog.csdn.net/yga_airspace/article/details/86688278
核心代码:
// 输入初始数据切片pr,切片长度n,在pr上操作,返回fft后的pr
func fft(pr []float64, n int)[]float64{
k:=int(Floor(Log2(float64(n))))
var pi =make([]float64,n)
var fi =make([]float64,n)
var fr =make([]float64,n)
var it, m,is,i, j, nv, l0 int
var p,q,s,vr,vi,poddr,poddi float64
for it=0; it<=n-1; it++{
m=it;
is=0;
for i=0; i<=k-1; i++{
j=m/2;
is=2*is+(m-2*j);
m=j;
}
fr[it]=pr[is];
fi[it]=pi[is];
}
pr[0]=1.0;
pi[0]=0.0;
p=2*Pi/float64(n);
pr[1]=Cos(p); //将w=e^-j2pi/n用欧拉公式表示
pi[1]=-Sin(p);
for i=2; i<=n-1; i++{
p=pr[i-1]*pr[1];
q=pi[i-1]*pi[1];
s=(pr[i-1]+pi[i-1])*(pr[1]+pi[1]);
pr[i]=p-q; pi[i]=s-p-q;
}
for it=0; it<=n-2; it=it+2{
vr=fr[it];
vi=fi[it];
fr[it]=vr+fr[it+1];
fi[it]=vi+fi[it+1];
fr[it+1]=vr-fr[it+1];
fi[it+1]=vi-fi[it+1];
}
m=n/2;
nv=2;
for l0=k-2; l0>=0; l0--{ //蝴蝶操作
m=m/2;
nv=2*nv;
for it=0; it<=(m-1)*nv; it=it+nv{
for j = 0; j <= (nv/2)-1; j++{
p = pr[m*j] * fr[it+j+nv/2]
q = pi[m*j] * fi[it+j+nv/2]
s = pr[m*j] + pi[m*j]
s = s * (fr[it+j+nv/2] + fi[it+j+nv/2])
poddr = p - q
poddi = s - p - q
fr[it+j+nv/2] = fr[it+j] - poddr
fi[it+j+nv/2] = fi[it+j] - poddi
fr[it+j] = fr[it+j] + poddr
fi[it+j] = fi[it+j] + poddi
}
}
}
for i=0; i<=n-1; i++{
pr[i]=Sqrt(fr[i]*fr[i]+fi[i]*fi[i]); //幅值计算
}
return pr
}
测试:
package main
import (
"fmt"
. "math"
"time"
)
const n0 =1024
func main(){
var i int
var pr,t [n0]float64
for i=0; i<n0; i++ { //生成输入信号
t[i] = float64(i)*0.001
pr[i]=1.2+2.7*Cos(2*Pi*33*t[i])+5*Cos(2*Pi*200*t[i]+Pi/2);
}
now :=time.Now()
fft(pr[0:n0],n0); //调用FFT函数
for i=0; i<n0; i++{
fmt.Printf("%v\t%f\n",i,pr[i]); //输出结果
}
fmt.Print(now,"\n",time.Now())
}
应用fft 编写kuiper 的function
stream输入格式
1. 两个参数:前者是double[64],记录输入,后者是int n=64,记录输入个数
2. 一个参数:double[64],记录输入
3. 一个参数:doulbe,当数量达到64是,停止
第二种好一点,第一种多了一个多余的参数,第三种要接收64次。
把数据量改小一点,fft函数,输入 pr:=float64{1,2},应该是输出3,1。
所以stream:
type input struct {
pr []float64
n int
}
//校验输入格式
func (f *input) Validate(args []interface{}) error{
if len(args) != 1{
return fmt.Errorf("echo function only supports 1 parameter but got %d", len(args))
}
return nil
}
//处理
func (f *input) Exec(args []interface{}) (interface{}, bool) {
m :=args[0].(input)
result :=fft(m.pr,m.n)
return result,true
}
//是不是xx函数
func (f *input) IsAggregate() bool {
return false
}
//测试
func main(){
pr1 := make([]float64,64)
input1 := input{pr1}
'''
//args是一个包含一个元素的切片,元素是一个input struct,struct包含一个float64数组
var arg, t [64]float64
for i:=0; i<64; i++ { //生成输入信号
t[i] = float64(i)*0.001
arg[i]=1.2+2.7*Cos(2*Pi*33*t[i])+5*Cos(2*Pi*200*t[i]+Pi/2);
}
argtype :=input{arg[0:64]}
var args []interface{}
args= append(args,argtype)
'''
ret,_:=input1.Exec(args)//ret是一个float64数组
for _,i:= range ret.([]float64){
println(i)
}
}
//或者改成如下:
for _,i:= range ret.(input).pr{//ret是一个结构,包含folat64数组
//对印的E
func (f *input) Exec(args []interface{}) (interface{}, bool) {
m :=args[0].(input)
result :=fft(m.pr,len(m.pr))
output:=input{result}
return output,true
}
//exec方法返回的是一个空接口,所以返回结构也可以,返回float数组也行。