【问题标题】:Positive/Negative Infinity Constants in FortranFortran 中的正/负无穷大常数
【发布时间】:2018-05-31 23:00:42
【问题描述】:

如何在 Fortran 2008 中获得负无穷和正无穷的常量(或 parameters,我想)?我尝试了以下代码:

program inf
  use, intrinsic :: ieee_arithmetic

  real(8), parameter :: inf_pos = ieee_value(0d0, ieee_positive_inf)
  real(8), parameter :: inf_neg = ieee_value(0d0, ieee_negative_inf)
end program inf

但是,我收到以下错误:

$ gfortran inf.f08
inf.f08:4:22:

   real(8) :: inf_pos = ieee_value(0d0, ieee_positive_inf)
                  1
Error: Function ‘ieee_value’ in initialization expression at (1) must be an intrinsic function
inf.f08:5:22:

   real(8) :: inf_neg = ieee_value(0d0, ieee_negative_inf)
                  1
Error: Function ‘ieee_value’ in initialization expression at (1) must be an intrinsic function

尽管文档另有说明,但 gfortran 似乎认为 ieee_value() 不是内在的。

有什么办法可以得到我想要做的吗?

【问题讨论】:

  • 哪个文档说ieee_value 是一个内在函数?不是,如果您指出这一点,我们可以为您解决这部分问题。
  • This question 谈论 NaN。虽然我不会将这些问题与重复问题联系起来,但短期内您可以阅读足够的内容。
  • pleiades.ucsc.edu/doc/intel/composer_xe/14.0/compiler_f/… 这个页面似乎暗示了这一点。但无论如何,这既不是这里也不是那里
  • @francescalus 不会使用 transfer() 在大小端架构中不可移植?
  • 哦,是的。唉,如果你想要命名常量,你没有很多其他选择。不仅是字节顺序,还有表示的所有其他方面)。

标签: floating-point fortran gfortran ieee-754


【解决方案1】:

我将首先看看为什么你不能使用ieee_value 来为你想要的命名常量提供值,然后我会给出坏消息。两者都很有趣(对我来说)。

ieee_value 不是一个内在的过程。这是一个内在模块中的过程,但正如 Fortran 2008 标准注释(注释 13.25):

标准内在模块中定义的类型和过程本身并不是内在的。

gfortran 正确地注意到 ieee_value 不能用于初始化(常量)表达式。

现在,如果您需要使用“无限”值初始化命名常量,则有一些不可移植的选项:1

  • 类似于this question about NaNs,您可以计算出所需的位模式并使用transfer进行初始化;
  • 您可能是able 来编写“溢出”初始化表达式。

您可以使用构建系统和预处理器解决此问题的不可移植性。

总而言之,您可能不需要有一个无限的命名常量。 IEEE 模块很容易提供“此值是否无限?”或“将此值设置为无限”的程序。您的编译器可能还具有“将变量初始化为无穷大”作为编译时选项。


1 在初始化表达式之外,使用ieee_value 的限制要宽松得多。

【讨论】:

    【解决方案2】:

    我想出的有点不雅的解决方案是简化总是返回正无穷和负无穷大的定义函数

    program inf
      use, intrinsic :: ieee_arithmetic
    
      print *, inf_pos()
      print *, inf_neg()
    
    contains
      pure function inf_pos() result(r)
        real(8) :: r
        r = ieee_value(0d0, ieee_positive_inf)
      end function inf_pos
    
      pure function inf_neg() result(r)
        real(8) :: r
        r = ieee_value(0d0, ieee_negative_inf)
      end function inf_neg
    end program inf
    

    【讨论】:

    • 在这种情况下最好在模块中定义全局变量(最好应用“protected”属性)
    【解决方案3】:

    以下将产生 + 和 - Infinity,但是,必须执行并且不能直接在变量声明中作为初始化接受:

    program testinf
    implicit none
    double precision :: x, xiplus, xineg   
    x       = HUGE(x)
    xiplus  = 2 * x     ! yields +Infinity
    xineg   =-2 * x     ! yields -Infinity
    write(*,*)x , xiplus, xineg 
    end program testinf
    

    【讨论】:

      猜你喜欢
      • 2011-06-27
      • 1970-01-01
      • 2015-03-22
      • 2013-11-29
      • 2017-08-19
      • 2012-02-09
      • 2012-05-13
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多