每次使用包含模块时是否评估 Fortran 命名常量?

Are Fortran named constants evaluated each time the containing module is used?

假设我定义了参数 pi = -acos(-1.0) 并将其保存在模块中。当我在另一个程序中使用这个模块时,pi 的值每次都是从函数 ACOS 计算出来的吗?

如果是这样,是否最好将 pi = -3.1415.... 定义为我需要的任何精度?

不是,参数是在编译时计算的。两种方法的性能应该是一样的。

此外,如果您想知道两个选项中哪个更快,答案几乎总是“试试看”。如果您关心您的代码 运行 速度如何,您应该使用代码分析器来准确地为您的代码计时并找出导致它变慢的原因。

N.B。虽然速度应该相同,但存在精度问题。如果您使用 acos(-1.0) 定义 pi,它只会精确到默认的单精度。如果你想这样定义 pi,你应该使用 acos(-1.0_dp),其中 dp 定义了你需要的浮点精度。

如果您在模块中定义了命名常量,那么它的值必须由常量表达式给出。在 compile/execute 模块中,通常会在编译模块本身时评估此常量表达式,而不是在最终引用它时。

无论哪种方式,使用模块的东西都不可能影响该模块中命名常量值的计算。

对于问题的示例,ACOS(-1.0) 是使用编译时默认的真实类型进行评估的。如果将其更改为

module pidef
  use, intrinsic :: iso_fortran_env, only : piprec => real64
  implicit none
  real(piprec), parameter :: pi = ACOS(-1.0_piprec)
end module

然后常量表达式在 范围内使用 piprec 的值 。作为常量表达式,每个值都必须在那时明确定义。不会像

这样的东西
program piuse
  use, intrinsic :: iso_fortran_env, only : piprec => real32
  use pidef
  implicit none
end program

将以某种方式使用 real32 计算 pi。同样,在编译模块后,也无法在模块的常量表达式中引用稍后全局定义的变量。