2011-02-15 10 views
6

Qual è il modo più sicuro per impostare una variabile su + Infinity in Fortran? Al momento sto usando:Infinity in Fortran

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 

ma mi chiedo se c'è un modo migliore?

risposta

7

Se il compilatore supports ISO TR 15580 Aritmetica IEEE fa parte del cosiddetto standard Fortran 2003 di quanto sia possibile utilizzare le procedure dai moduli 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 
0

Non so più sicuro, ma posso offrirti un metodo alternativo. Ho imparato a fare in questo modo:

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 

Se si utilizza valori eccezionali nelle espressioni (non credo che questo è in genere consigliabile) si dovrebbe prestare particolare attenzione al modo in cui il compilatore li gestisce, si potrebbe ottenere un po ' risultati inaspettati altrimenti.

0

non vorrei fare affidamento sul compilatore per supportare lo standard IEEE e fare praticamente quello che hai fatto, con due modifiche:

  1. non vorrei aggiungere huge(1.)+huge(1.), dal momento che in alcuni compilatori si può finire con -huge(1.)+1 --- e questo può causare una perdita di memoria (non so il motivo, ma è un fatto sperimentale, per così dire).

  2. Qui si utilizzano i tipi real. Personalmente preferisco mantenere tutti i miei numeri in virgola mobile come real*8, quindi tutte le costanti float sono qualificate con d0, come questo: huge(1.d0). Questa non è una regola, ovviamente; alcune persone preferiscono usare sia real -s che real*8-s.

+2

'reale * 8' e' doppia precision' ('1.d0') non sono necesarilly lo stesso tipo reale. E, naturalmente, se usare la precisione singola o doppia non è una questione di preferenze personali, ma di argomenti e test matematici. –

1

non sono sicuro se il soffietto soluzione funziona su tutti i compilatori, ma è un bel modo matematico di raggiungere l'infinito come -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 

Funziona bene anche per variabili complesse.

+0

Funzionerà su computer compatibili IEEE, se non si abilita il trapping FPE. Ma se lavori con gli infiniti, sarebbe sciocco farlo. –

0

Questo sembra funzionare per me. Definire un parametro

double precision,parameter :: inf = 1.d0/0.d0 

Quindi utilizzare in caso test.

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(*,*) 

quando si compila con ifort & corsa, ottengo

sng = inf 
dbl1 = inf 
dbl2 = inf