基于 Excel VBA 实现 DFT

离散傅里叶变换(DFT)的计算公式如下:

                 

DFT 将时域内的周期离散信号变换为频域内的离散周期信号。

1 实现的功能

利用 Excel VBA 编写了一个自定义的 DFT(Xn, Index=True) 函数,该函数返回数组。第一个输入参数是时域信号,要求在 Excel 表中以列的形式存在;第二个布尔型参数默认为 True,返回变换后的实部数组;取 False 时,返回虚部数组。

因为直接采用公式计算离散傅里叶变换,所以当数据量增多时,计算量较大。因此,处理很多数据时,建议利用其它工具。测试时,输入数据个数为720时,计算大概需要 3 秒(电脑型号较老,CPU为 Intel i5-3337U)。

2 使用方法

没有为函数增加许多判断,以应对不同的使用场景。使用具体步骤如下:

1) 输入数据为列的形式,如下图所示,选中 Data 列任意一个数据后,利用 Ctrl + ↓ 定位到最后一个数据,然后平移至 DFT VBA Real 列,随便输入一个数定位用。

2)按 Ctrl + ↑,回到 DFT VBA Real 列的第一个单元格(表头)。选中下一个单元格(B2),按 Ctrl + Shift + ↓,选中多个单元格(步骤1) 的作用在此体现),输入公式  =DFT(A2:A721),其中 A2:A721 同样可以按 Ctrl + Shift + ↓ 选中。

3)按 Ctrl + Shift + Enter  进行数组运算(不能输花括号)。

3 具体代码

因为计算结果是对称的,所以只计算了前 N/2+1 个频率点,剩余的点在 Excel 表格中最后以 0 的形式出现(也可以增加循环,由前 N/2+1 的点的结果直接得到)。

Function DFT(Xn As Range, Optional Index As Boolean = True)
' 用公式直接计算 DFT
' 要求数据都是按列填入表格

PI = 3.141592653
Dim TempArray()

N = Xn.Count '统计输入的数据个数
ReDim TempArray(0 To N - 1) '动态改变数组长度

If Not Index Then '第二个参数输入 0 计算虚部,否则均计算实部

    For i = 0 To N / 2 '计算一半,另一半对称,取0处理
        temp = 0
        For j = 1 To N
            Angle = 2 * PI / N * (j - 1) * i
            temp = temp - Xn.Cells(j, 1).Value * Sin(Angle)
            'Xn对应单元格范围(一列数据),Cells()方法获得具体某个单元格,Value获得数值
        Next j
        TempArray(i) = temp / N '这里可以乘以2,得到单边谱
    Next i
    
    
Else '计算实部

    For i = 0 To N / 2
        temp = 0
        For j = 1 To N
            Angle = 2 * PI / N * (j - 1) * i
            temp = temp + Xn.Cells(j, 1).Value * Cos(Angle)
        Next j
        TempArray(i) = temp / N
    Next i
    
End If

DFT = Application.WorksheetFunction.Transpose(TempArray) '转置,变成列向量

End Function

4 改进思考

采用数组的方式操作过程稍微有点麻烦,既要选中数组的输出范围,也要选择输入单元格范围,考虑采用子过程宏结合自定义功能区按钮的方式实现:选中时域数据,点击DFT按钮,在时域数据的右侧得到变换后的数据。但是此时就不能像调用函数一样,在自己需要的位置得到结果了。

或许可以采用下述思路:

1)读取当前选中的单元格范围内的数据,将值保存到一个数组并统计个数。

2)用 Cells(1,1).Offset(0,1) 定位到第一个输入数据右侧的单元格,并在该单元格填入第一个实部。

3)利用循环,每次向下偏移一个单元格,并计算对应数据。可以计算 N 个结果,也可以计算 N/2+1 个结果。采用后者时,不会出现剩下都是 0 的情况。

4)用 Cells(1,1).Offset(0,2) 定位到需要计算虚部的初始位置,重复计算实部的步骤。

5)有了实部和虚部,便可进一步计算模长和相角。

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值