离散傅立叶变换似乎打印错误的答案?

时间:2018-02-21 00:39:21

标签: fortran gfortran

我正在尝试编写一个程序来计算一组给定数据的离散傅立叶变换。我已经采样了一个正弦波,所以我的设置是(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。

谢谢

2 个答案:

答案 0 :(得分:3)

即使这个问题已得到回答和接受,但我所说的程序有很多问题我不得不说......

给出的输入不是正弦波,它是时间的线性函数。有点像基于1的斜坡输入。

对于DFT,通常认为指数来自0:N-1,而不是1:N

对于W,奈奎斯特频率表示为-N/2N/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