Fortran 90/95でInfiniteおよびNaNの値をチェックする標準準拠の方法を探していましたが、思ったよりも難しいことがわかりました。
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()
?
_ieee_arithmatic
_を使用しない簡単な方法は、次のことです。
Infinity:変数infinity = HUGE(dbl_prec_var)
(または、もしあれば、4倍精度変数)を定義します。次に、if(my_var > infinity)
により、変数が無限大かどうかを確認するだけです。
[〜#〜] nan [〜#〜]:これはさらに簡単です。定義上、NANはそれ自体でさえも、何にも等しくありません。変数をそれ自体と比較するだけです:if(my_var /= my_var)
。
コメントするのに十分な担当者がいないので、無限をテストするためのリック・トンプソンの提案について「答え」ます。
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!!!
番号。
NaNを生成/チェックするためのIEEE_ARITHMETICの主要な部分は、特定のアーキテクチャのgfortranのために書くのに十分簡単です。
利用した:
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。
番号。
Fortran 90/95には、規格に準拠した無限大またはNaNのチェック方法も、規格に準拠した方法もありません。 Fortran 90/95では、これらの準数値のいずれかを定義する標準準拠の方法はありません。