Y a-t-il un moyen standard de vérifier pour Infinite et NaN dans Fortran 90/95?
j'ai essayé de trouver un moyen conforme aux normes pour vérifier les valeurs infinies et NaN dans Fortran 90/95 mais il s'est avéré plus difficile que je pensais.
- j'ai essayé de créer manuellement des variables Inf et NaN en utilisant la représentation binaire décrite dans IEEE 754, mais je n'ai trouvé aucune fonctionnalité de ce genre.
- je suis conscient de la valeur intrinsèque
ieee_arithmetic
module Fortran 2003 avec l'ieee_is_nan()
etieee_is_finite()
fonctions intrinsèques. Cependant il n'est pas soutenu par tous les compilateurs ( notamment gfortran à partir de la version 4.9).
la Définition de l'infini et NaN au début comme pinf = 1. / 0
et nan = 0. / 0
me semble hackish et IMHO peut soulever quelques problèmes de construction - par exemple, si certains compilateurs vérifient cela dans le temps de compilation, il faudrait fournir un drapeau spécial.
y a-t-il un moyen que je puisse implémenter dans le standard Fortran 90/95?
function isinf(x)
! Returns .true. if x is infinity, .false. otherwise
...
end function isinf
et <!--6?
6 réponses
la manière simple sans utiliser le ieee_arithmatic
est de faire ce qui suit.
Infini: Définissez votre variable infinity = HUGE(dbl_prec_var)
(ou, si vous l'avez, un quad précision variable). Ensuite, vous pouvez simplement vérifier pour voir si votre variable est l'infini par if(my_var > infinity)
.
NAN: C'est encore plus facile. Par définition, NAN n'est pas égal à quoi que ce soit, même à lui-même. Comparez simplement la variable à elle-même:if(my_var /= my_var)
.
Je n'ai pas assez de réputation pour commenter donc je vais "répondre" à la suggestion de Rick Thompson pour tester l'infini.
if (A-1 .eq. A)
cela sera aussi vrai si A est un nombre de point flottant très grand, et 1
est inférieur à la précision de A.
Un test simple:
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
sorties:
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!!!
Non.
les parties saillantes de IEEE_ARITHMETIC for generating / checking for Nan's sont assez faciles à écrire pour gfortran pour une architecture particulière.
j'ai utilisé:
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
ceci affichera 'Got a problem' pour nombre = 0.0D0, 1.0D0 / 0.0D0, 0.0D0 / 0.0D0, SQRT (-2.0D0), ainsi que pour les débordements et les sous-écoulements tels que number = EXP(1.0D800) ou nombre = EXP(-1.0D800). Notez que généralement, des choses comme number = EXP(1.0 D-800) vont juste définir number = 1.0 et produire un avertissement au moment de la compilation, mais le programme va imprimer "nous sommes OK", ce que je trouve acceptable.
OL.
Non.
il n'existe pas non plus de méthode de vérification conforme aux normes pour les infinités ou les NaNs dans Fortran 90/95, pas plus qu'il ne peut y avoir de méthode conforme aux normes. Il n'existe aucune façon conforme aux normes de définir l'un ou l'autre de ces quasi-nombres dans le Fortran 90/95.
Inf il semble fonctionner que si (A-1 .eq. A) est vrai, alors A est Inf