计算化学公社

标题: Fortran书中关于复数的坑 [打印本页]

作者
Author:
beefly    时间: 2021-3-6 17:03
标题: Fortran书中关于复数的坑
本帖最后由 beefly 于 2021-3-6 17:11 编辑

在Fortran语言中,复数的声明有以下三种形式:
第一种:complex(kind=n) a
第二种:complex(n) a
第三种:complex*n a
其中n=4或8。

但是在不同的Fortran书中,对这三种形式的解释是不一样的。

首先是彭国伦的《Fortran 95程序设计》
(, 下载次数 Times of downloads: 89)
这里讲得不够明确:从FORTRAN 77继承下来的第二、三种形式的精度在Fortran后续版本中是否做了修改?给人的感觉,在n相同的情况下,三种声明复数的形式应当具有相同的精度。

接下来是白海波的《Fortran程序设计权威指南》
(, 下载次数 Times of downloads: 89)
这里讲得很明确,三种形式完全等价。

此外还有一些书只介绍第一种声明复数的形式。这以Chapman的《Fortran程序设计》为代表。

按照以上两本书中的说法,在实际的复数运算中会遇到各种问题。例如,LAPACK库(严格遵守FORTRAN 77标准)中的复数声明全部为“complex*16 a”这种形式。难道LAPACK库用了四精度复数?当然不可能!

为了验证书中的说法是否正确,准备了以下小程序(test.f90),分别在浮点数和复数情况下打印不同精度的pi。为了保证精度,pi是用四精度浮点数计算的。
  1. call test_real()
  2. call test_cplx()
  3. end

  4. subroutine test_real()
  5. real(kind=16) :: a16
  6. real(kind=4)  :: a4
  7. real(kind=8)  :: a8
  8. real(16) b16
  9. real(8) b8
  10. real(4) b4
  11. real*16 c16
  12. real*8 c8
  13. real*4 c4

  14. ! pi
  15. a16=acos(-1.0q0)
  16. b16=a16
  17. c16=a16
  18. a8=a16
  19. b8=a16
  20. c8=a16
  21. a4=a16
  22. b4=a16
  23. c4=a16

  24. write(*,"(f38.34)")a16,b16,c16,a8,b8,c8,a4,b4,c4

  25. return
  26. end

  27. subroutine test_cplx()
  28. complex(kind=16) :: a16
  29. complex(kind=4)  :: a4
  30. complex(kind=8)  :: a8
  31. complex(16) b16
  32. complex(8) b8
  33. complex(4) b4
  34. complex*16 c16
  35. complex*8 c8
  36. !complex*4 c4

  37. ! pi + i * pi
  38. a16=(1.q0,1.q0)*acos(-1.0q0)
  39. b16=a16
  40. c16=a16
  41. a8=a16
  42. b8=a16
  43. c8=a16
  44. a4=a16
  45. b4=a16
  46. !c4=a16

  47. write(*,"(2f38.34)")a16,b16,c16,a8,b8,c8,a4,b4  !,c4

  48. return
  49. end
复制代码
用gfortran或ifort(不支持pgf90)编译后运行。

总结:



作者
Author:
wxhwbh    时间: 2021-3-6 19:10
之前吃过这个亏,后来同组的同学就测试过这个,结论是用real*n,complex(n),complex*2n才是匹配的
作者
Author:
Warm_Cloud    时间: 2021-3-6 22:36
统一用kind最保险
作者
Author:
snljty2    时间: 2022-6-17 09:35
关于这个complex(kind=8),看有些代码里也用double complex表示,同时也有用double precision表示real(kind=8)的。作为C语言习惯用户,感觉还是double这个词看着比较亲切。另外这个double好像只是在主流PC平台上默认是kind=8,而且也可以通过编译器选项比如dbl, -r8等指定。




欢迎光临 计算化学公社 (http://bbs.keinsci.com/) Powered by Discuz! X3.3