26

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

  • 我尝试使用 IEEE 754 中描述的二进制表示手动创建 Inf 和 NaN 变量,但我发现没有这样的功能。
  • 我知道ieee_arithmeticFortran 2003 中的内在模块具有ieee_is_nan()ieee_is_finite()内在功能。但是,并非所有编译器都支持它(尤其是 gfortran 4.9 版)。

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

有没有一种方法可以在标准 Fortran 90/95 中实现?

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

isnan()

4

8 回答 8

30

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

Infinity:定义您的变量infinity = HUGE(dbl_prec_var)(或者,如果有的话,一个四精度变量)。然后您可以简单地检查您的变量是否为无穷大if(my_var > infinity)

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

于 2013-06-30T14:50:34.447 回答
4

我没有足够的代表发表评论,所以我会“回答”关于 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!!!
于 2014-12-31T16:55:34.480 回答
2

不。

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

于 2013-06-30T11:47:34.750 回答
2

我用过:

  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

这将为 number = 0.0D0、1.0D0/0.0D0、0.0D0/0.0D0、SQRT(-2.0D0) 以及 number = EXP(1.0D800) 或 number 等上溢和下溢打印“遇到问题” =经验(-1.0D800)。请注意,一般来说,像 number = EXP(1.0D-800) 这样的东西只会设置 number = 1.0 并在编译时产生警告,但程序会打印“我们没事”,我认为这是可以接受的。

OL。

于 2016-05-23T14:26:19.690 回答
0

不。

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

于 2013-06-30T15:43:20.157 回答
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)    
于 2020-08-21T07:12:03.900 回答
0

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

program test
implicit none
real :: res
integer :: i

do i=1,1000000
    res=-log((1.+(10**(-real(i))))-1.)
    print*,i,res
    if ((1./res)==0.) then
        exit
    end if
end do

end program

有你的无限检查。无需复杂化。

于 2020-01-03T17:33:01.977 回答
-2

对于 Inf,如果 (A-1 .eq. A) 为真,则 A 为 Inf 似乎可行

于 2014-11-12T15:35:23.523 回答