我正在尝试编写一个程序来计算一组给定数据的离散傅立叶变换。我已经采样了一个正弦波,所以我的设置是(pi / 2,2 * pi,3 * pi / 2,2 * pi)。这是我的计划:
program DFT
implicit none
integer :: k, N, x, y, j, r, l
integer, parameter :: dp = selected_real_kind(15,300)
real, allocatable,dimension(:) :: h, rst
integer, dimension(:,:), allocatable :: W
real(kind=dp) :: pi
open(unit=100, file="dft.dat",status='replace')
N = 4
allocate(h(N))
allocate(rst(N))
allocate(W(-N/2:N/2,1:N))
pi = 3.14159265359
do k=1,N
h(k) = k*(pi*0.5)
end do
do j = -N/2,N/2
do k = 1, N
W(j,k) = EXP((2.0_dp*pi*cmplx(0.0_dp,1.0_dp)*j*k)/N)
end do
end do
rst = matmul(W,h)
!print *, h, w
write(100,*) rst
end program
这将打印出的数组为:
0.00000000 0.00000000 15.7079639 0.00000000 0.00000000
使用在线计算器,结果应为:
15.7+0j -3.14+3.14j -3.14+0j -3.14-3.14j
我不确定为什么rst首次输入时间太长。
有人能发现为什么它会在3/4的结果中打印0?我注意到实际答案和结果都出现了15.7。
谢谢
答案 0 :(得分:3)
即使这个问题已得到回答和接受,但我所说的程序有很多问题我不得不说......
给出的输入不是正弦波,它是时间的线性函数。有点像基于1的斜坡输入。
对于DFT,通常认为指数来自0:N-1
,而不是1:N
。
对于W
,奈奎斯特频率表示为-N/2
和N/2
两次。再次对行0:N-1
,BTW进行编号是正常的,这就是为什么在rst
向量中有额外输出的原因。
pi
是双精度,但仅初始化为12位有效数字。很难判断你的pi
价值是否有拼写错误,这就是为什么许多人会使用4*atan(1.0_dp)
或acos(-1.0_dp)
的原因。
请注意,h(N)
实际上最终将作为零时间输入,这是整个世界将DFT向量从零开始索引的一个原因。
表达式cmplx(0.0_dp,1.0_dp)
有点徒劳,因为如果第三个可选CMPLX
参数不存在,KIND=
内在函数总是返回单个精度结果。作为一个复杂的文字,(0.0_dp,1.0_dp)
将是双精度。但是,您也可以使用(0,1)
因为它在单精度中可以完全表示,并且当它乘以左侧增长的乘积时会转换为双精度。 2.0_dp
也可以成功地表示为2
,而且杂乱程度较低。
表达式EXP((2.0_dp*pi*cmplx(0.0_dp,1.0_dp)*j*k)/N)
适用于逆DFT,无视标准化。因此,我会以EXP(-2*pi*(0,1)*j*k/N)
更清晰,更正确地写出整件事。然后输出应该与在线计算器打印出的内容直接相当。
答案 1 :(得分:2)
Fortran为您执行复杂的数字,但您必须将适当的变量声明为复杂的。尝试
complex, allocatable,dimension(:) :: rst
complex, dimension(:,:), allocatable :: W