2011-02-15 20 views
6

Jaki jest najbezpieczniejszy sposób ustawienia zmiennej na + Nieskończoność w Fortranie? W tej chwili używam:Nieskończoność w Fortranie

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 

ale zastanawiam się, czy istnieje lepszy sposób?

Odpowiedz

7

Jeśli twój kompilator supports Arytmetyka ISO TR 15580 IEEE, która jest częścią tak zwanego standardu Fortran 2003, możesz użyć procedur z modułów 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

Nie wiem o najbezpieczniejszym, ale mogę zaoferować alternatywną metodę. Nauczyłam się robić to w ten sposób:

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 

Jeśli używasz wyjątkowe wartości w wyrażeniach (I nie sądzę, że to jest ogólnie wskazane) należy zwrócić szczególną uwagę na to, jak kompilator obsługuje je, można uzyskać pewne nieoczekiwane wyniki w przeciwnym razie.

0

nie będę polegać na kompilator obsługuje standard IEEE i nie dość dużo, co zrobiłeś, z dwoma zmianami:

  1. nie będę dodawać huge(1.)+huge(1.), ponieważ w niektórych kompilatorów was mogą kończy się na -huge(1.)+1 --- i może to spowodować wyciek pamięci (nie znam przyczyny, ale jest to fakt eksperymentalny, że tak powiem).

  2. Używasz tutaj typów real. Osobiście wolę zachować wszystkie liczby zmiennoprzecinkowe jako real*8, stąd wszystkie stałe zmiennopozycyjne są kwalifikowane przez d0, podobnie jak poniżej: huge(1.d0). Oczywiście nie jest to regułą; niektórzy ludzie wolą używać obu: real -s i real*8 -s.

+2

'real * 8' i' double precision' ('1.d0') nie są necesarilly samo prawdziwy rodzaj. I oczywiście, czy używać pojedynczej czy podwójnej precyzji nie jest kwestią osobistych preferencji, ale matematycznych argumentów i testów. –

1

Nie jestem pewien, czy mieszek rozwiązanie działa na wszystkich kompilatorów, ale jest to miły matematyczny sposób dotarcia do nieskończoności jako -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 

Dobrze działa również w przypadku zmiennych złożonych.

+0

Będzie działać na urządzeniach zgodnych z IEEE, jeśli nie włączysz pułapkowania FPE. Ale jeśli pracujesz z nieskończonościami, byłoby głupio to robić. –

0

To wydaje się działać dla mnie. zdefiniować parametr

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

następnie używać go w razie prób.

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

Kiedy skompilowany z ifort & metę, mam

sng = inf 
dbl1 = inf 
dbl2 = inf 
Powiązane problemy