有没有一种标准方法可以检查Fortran 90/95中的Infinite和NaN?

时间:2013-06-30 11:36:47

标签: fortran fortran95

我一直试图找到符合标准的方法来检查Fortran 90/95中的无限和NaN值,但事实证明它比我想象的更难。

  • 我尝试使用IEEE 754中描述的二进制表示手动创建Inf和NaN变量,但我没有找到这样的功能。
  • 我知道Fortran 2003中具有ieee_arithmeticieee_is_nan()内在函数的内在ieee_is_finite()模块。但是,从版本4.9开始,所有编译器都不支持它(notably gfortran。)

在开头定义无穷大和NaN,如pinf = 1. / 0nan = 0. / 0似乎对我来说是骇人听闻的,恕我直言会引发一些构建问题 - 例如,如果某些编译器在编译时检查这个问题,则必须提供一个特别旗帜。

我有没有办法在标准的Fortran 90/95中实现?

function isinf(x)
! Returns .true. if x is infinity, .false. otherwise
...
end function isinf

isnan()

8 个答案:

答案 0 :(得分:21)

不使用ieee_arithmatic的简单方法是执行以下操作。

无限:定义变量infinity = HUGE(dbl_prec_var)(或者,如果有的话,定义四元精度变量)。然后,您只需通过if(my_var > infinity)检查您的变量是否为无穷大。

NAN :这更容易。根据定义,NAN不等于任何东西,甚至本身。只需将变量与自身进行比较:if(my_var /= my_var)

答案 1 :(得分:3)

我没有足够的代表评论所以我会“回答”关于Rick Thompson关于测试无限的建议。

if (A-1 .eq. A) 

如果A是一个非常大的浮点数,并且1低于A的精度,则也是如此。

一个简单的测试:

subroutine test_inf_1(A)
    real, intent(in) :: A
    print*, "Test (A-1 == A)"
    if (A-1 .eq. A) then
        print*, "    INFINITY!!!"
    else
        print*, "    NOT infinite"
    endif
end subroutine

subroutine test_inf_2(A)
    real, intent(in) :: A
    print*, "Test (A > HUGE(A))"
    if (A > HUGE(A)) then
        print*, "    INFINITY!!!"
    else
        print*, "    NOT infinite"
    endif
end subroutine


program test
    real :: A,B

    A=10
    print*, "A = ",A
    call test_inf_1(A)
    call test_inf_2(A)
    print*, ""

    A=1e20
    print*, "A = ",A
    call test_inf_1(A)
    call test_inf_2(A)
    print*, ""

    B=0.0 ! B is necessary to trick gfortran into compiling this
    A=1/B
    print*, "A = ",A
    call test_inf_1(A)
    call test_inf_2(A)
    print*, ""

end program test

输出:

A =    10.0000000    
Test (A-1 == A)
    NOT infinite
Test (A > HUGE(A))
    NOT infinite

A =    1.00000002E+20
Test (A-1 == A)
    INFINITY!!!
Test (A > HUGE(A))
    NOT infinite

A =          Infinity
Test (A-1 == A)
    INFINITY!!!
Test (A > HUGE(A))
    INFINITY!!!

答案 2 :(得分:2)

没有

用于生成/检查NaN的IEEE_ARITHMETIC的显着部分很容易为特定体系结构的gfortran编写。

答案 3 :(得分:1)

我用过:

  PROGRAM MYTEST
  USE, INTRINSIC :: IEEE_ARITHMETIC, ONLY: IEEE_IS_FINITE      
  DOUBLE PRECISION :: number, test
  number = 'the expression to test'
  test = number/number
  IF (IEEE_IS_FINITE(test)) THEN
     WRITE(*,*) 'We are OK'
  ELSE
     WRITE(*,*) 'Got a problem'
  END IF         
     WRITE(*,*) number, test
  END PROGRAM MYTEST

这将打印出来'遇到问题'数字= 0.0D0,1.0D0 / 0.0D0,0.0D0 / 0.0D0,SQRT(-2.0D0),以及数字= EXP(1.0D800)或数字= EXP(-1.0D800)等溢出和下溢。请注意,通常,数字= EXP(1.0D-800)之类的东西只会设置数字= 1.0并在编译时产生警告,但是程序会打印“我们没事”,我认为这是可以接受的。

OL。

答案 4 :(得分:0)

没有

在Fortran 90/95中也没有符合标准的检查无穷大或NaN的方法,也没有符合标准的方法。在Fortran 90/95中没有符合标准的方法来定义这些准数字。

答案 5 :(得分:0)

对于Fortran,1 / infinity = 0 因此,将您的变量除以零 即

Access-Control-Allow-Origin: '*'

有您的无限大检查。无需并发症。

答案 6 :(得分:0)

测试NaN都不起作用,例如,如果测试真正的s2p以查看是否为NaN,则

if(isnan(s2p)) 

在gfortran中也不起作用

if(s2p.ne.s2p). 

唯一起作用的是

if(.not.s2p<1.and..not.s2p>1)  

尽管可以确保您可能要添加

if(.not.s2p<1.and..not.s2p>1.and..not.s2p==1)    

答案 7 :(得分:-2)

对于Inf,似乎有效的是,如果(A-1 .eq.A)为真,则A为Inf