Question
Quel est le moyen le plus sûr de définir une variable sur + Infinity dans FORTRAN? Pour le moment, j'utilise:
program test
implicit none
print *,infinity()
contains
real function infinity()
implicit none
real :: x
x = huge(1.)
infinity = x + x
end function infinity
end program test
Mais je me demande s'il y a une meilleure façon?
La solution
Si votre compilateur les soutiens ISO TR 15580 IEEE Arithmétique qui fait partie de la norme dite FORTRAN 2003 que vous pouvez utiliser les procédures des modules IEEE_ *.
PROGRAM main
USE ieee_arithmetic
IMPLICIT NONE
REAL :: r
IF (ieee_support_inf(r)) THEN
r = ieee_value(r, ieee_negative_inf)
END IF
PRINT *, r
END PROGRAM main
Autres conseils
Je ne compterais pas sur le compilateur pour soutenir la norme IEEE et faire à peu près ce que vous avez fait, avec deux changements:
Je n'aimerais pas
huge(1.)+huge(1.)
, car sur certains compilateurs, vous pouvez vous retrouver avec-huge(1.)+1
--- Et cela peut provoquer une fuite de mémoire (je ne connais pas la raison, mais c'est un fait expérimental, pour ainsi dire).Vous utilisez
real
types ici. Je préfère personnellement garder tous mes nombres à virgule flottante commereal*8
, par conséquent, toutes les constantes flottantes sont qualifiées avecd0
, comme ça:huge(1.d0)
. Ce n'est pas une règle, bien sûr; Certaines personnes préfèrent utiliser les deuxreal
-le sablereal*8
-S.
Je ne sais pas pour la plus sûre, mais je peux vous offrir une méthode alternative. J'ai appris à le faire de cette façon:
PROGRAM infinity
IMPLICIT NONE
INTEGER :: inf
REAL :: infi
EQUIVALENCE (inf,infi) !Stores two variable at the same address
DATA inf/z'7f800000'/ !Hex for +Infinity
WRITE(*,*)infi
END PROGRAM infinity
Si vous utilisez des valeurs exceptionnelles dans les expressions (je ne pense pas que cela soit généralement conseillé), vous devez prêter une attention particulière à la façon dont votre compilateur les gère, vous pourriez obtenir des résultats inattendus autrement.
Je ne sais pas si la solution ci-dessous fonctionne sur tous les compilateurs, mais c'est une belle façon mathématique d'atteindre l'infini comme -log (0).
program test
implicit none
print *,infinity()
contains
real function infinity()
implicit none
real :: x
x = 0
infinity=-log(x)
end function infinity
end program test
Fonctionne également bien pour des variables complexes.
Cela semble fonctionner pour moi. Définir un paramètre
double precision,parameter :: inf = 1.d0/0.d0
Ensuite, utilisez-le dans les tests.
real :: sng
double precision :: dbl1,dbl2
sng = 1.0/0.0
dbl1 = 1.d0/0.d0
dbl2 = -log(0.d0)
if(sng == inf) write(*,*)"sng = inf"
if(dbl1 == inf) write(*,*)"dbl1 = inf"
if(dbl2 == inf) write(*,*)"dbl2 = inf"
read(*,*)
Lorsqu'il est compilé avec Ifort & Run, je reçois
sng = inf
dbl1 = inf
dbl2 = inf