web-dev-qa-db-ja.com

Fortran 90/95でInfiniteおよびNaNをチェックする標準的な方法はありますか?

Fortran 90/95でInfiniteおよびNaNの値をチェックする標準準拠の方法を探していましたが、思ったよりも難しいことがわかりました。

  • IEEE 754に記載されているバイナリ表現を使用して、InfおよびNaN変数を手動で作成しようとしましたが、そのような機能は見つかりませんでした。
  • Fortranの組み込み関数_ieee_arithmetic_と、ieee_is_nan()およびieee_is_finite()組み込み関数を知っています。ただし、すべてのコンパイラでサポートされているわけではありません( 特にgfortran バージョン4.9以降)。

_pinf = 1. / 0_や_nan = 0. / 0_のように最初に無限大とNaNを定義すると、私にとってはハックのように見えます。

標準のFortran 90/95で実装できる方法はありますか?

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

およびisnan()

20
astrojuanlu

_ieee_arithmatic_を使用しない簡単な方法は、次のことです。

Infinity:変数infinity = HUGE(dbl_prec_var)(または、もしあれば、4倍精度変数)を定義します。次に、if(my_var > infinity)により、変数が無限大かどうかを確認するだけです。

[〜#〜] nan [〜#〜]:これはさらに簡単です。定義上、NANはそれ自体でさえも、何にも等しくありません。変数をそれ自体と比較するだけです:if(my_var /= my_var)

22
Kyle Kanos

コメントするのに十分な担当者がいないので、無限をテストするためのリック・トンプソンの提案について「答え」ます。

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!!!
3
Ethan Gutmann

番号。

NaNを生成/チェックするためのIEEE_ARITHMETICの主要な部分は、特定のアーキテクチャのgfortranのために書くのに十分簡単です。

2
IanH

利用した:

  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などのオーバーフローとアンダーフローに対して「問題を解決しました」を出力します。 = EXP(-1.0D800)。通常、number = EXP(1.0D-800)のようなものは、number = 1.0に設定し、コンパイル時に警告を生成しますが、プログラムは 'We are OK'を出力します。

OL。

1
Otto Linsuain

番号。

Fortran 90/95には、規格に準拠した無限大またはNaNのチェック方法も、規格に準拠した方法もありません。 Fortran 90/95では、これらの準数値のいずれかを定義する標準準拠の方法はありません。