Is there a standard way to check for Infinite and NaN in Fortran 90/95?

和自甴很熟 提交于 2019-11-26 23:26:39

问题


I've been trying to find a standards-compliant way to check for Infinite and NaN values in Fortran 90/95 but it proved harder than I thought.

  • I tried to manually create Inf and NaN variables using the binary representation described in IEEE 754, but I found no such functionality.
  • I am aware of the intrinsic ieee_arithmetic module in Fortran 2003 with the ieee_is_nan() and ieee_is_finite() intrinsic functions. However it's not supported by all the compilers (notably gfortran as of version 4.9).

Defining infinity and NaN at the beginning like pinf = 1. / 0 and nan = 0. / 0 seems hackish to me and IMHO can raise some building problems - for example if some compilers check this in compile time one would have to provide a special flag.

Is there a way I can implement in standard Fortran 90/95?

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

and isnan()?


回答1:


The simple way without using the ieee_arithmatic is to do the following.

Infinity: Define your variable infinity = HUGE(dbl_prec_var) (or, if you have it, a quad precision variable). Then you can simply check to see if your variable is infinity by if(my_var > infinity).

NAN: This is even easier. By definition, NAN is not equal to anything, even itself. Simply compare the variable to itself: if(my_var /= my_var).




回答2:


I don't have enough rep to comment so I'll "answer" regarding Rick Thompson's suggestion for testing infinity.

if (A-1 .eq. A) 

This will also be true if A is a very large floating point number, and 1 is below the precision of A.

A simple test:

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

outputs:

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!!!



回答3:


No.

The salient parts of IEEE_ARITHMETIC for generating/checking for NaN's are easy enough to write for gfortran for a particular architecture.




回答4:


I have used:

  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

This will print 'Got a problem' for number = 0.0D0, 1.0D0/0.0D0, 0.0D0/0.0D0, SQRT(-2.0D0), and also for overflows and underflows such as number = EXP(1.0D800) or number = EXP(-1.0D800). Notice that generally, things like number = EXP(1.0D-800) will just set number = 1.0 and produce a warning at compilation time, but the program will print 'We are OK', which I find acceptable.

OL.




回答5:


No.

Neither is there a standards-compliant way of checking for infinities or NaNs in Fortran 90/95, nor can there be a standards-compliant way. There is no standards-compliant way of defining either of these quasi-numbers in Fortran 90/95.




回答6:


For Inf it seems to work that if (A-1 .eq. A) is true, then A is Inf



来源:https://stackoverflow.com/questions/17389958/is-there-a-standard-way-to-check-for-infinite-and-nan-in-fortran-90-95

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!