2013-02-24 13 views
6

Sto cercando un modo a prova di proiettile per convertire le variabili di tipo logico in un tipo reale che funzionerà sia in ifort che in gfortran. Le seguenti opere in ifort, ma non in gfortran:Converti il ​​tipo logico in doppio in Fortran

logical :: a 
real :: b 
a = .true. 
b = dble(a) 

L'errore gettato in gfortran è

b = dble(a) 
     1 
Error: 'a' argument of 'dble' intrinsic at (1) must be a numeric type 

Ovviamente, .TRUE. dovrebbe mappare a 1.d0 e .false. a 0.d0. Qual è il modo migliore per farlo?

+0

Per quello che vale, se si attiva il controllo standard ifort dovrebbe lamentarsi. Il motivo per cui funziona è che il processore ha un'estensione che consente la conversione implicita di logico in numero intero, quindi lo standard fornisce la conversione da intero a reale. Si noti che quando si dice "ovviamente" la rappresentazione interna di .TRUE. non assomiglierà assolutamente a un valore reale di 1.0, mentre su * alcuni * processori la rappresentazione interna di .TRUE. è esattamente uguale a un valore intero di 1 (in particolare se la logica predefinita e LOGICAL (C_BOOL) sono la stessa rappresentazione). – IanH

+0

. Vero. = -1 è anche comune (tutti i bit in un numero intero impostato su 1, che nel complemento a 2 = -1). – WaywiserTundish

risposta

6

Non sono sicuro se esiste uno strumento intrinseco che esegue questa operazione. Non so perché ifort lo accetti, e suppongo che sia una funzionalità specifica del compilatore.

un'opzione per questo, in particolare dal momento che si desidera che questo sia a prova di proiettile, è quello di creare la propria funzione.

non ho ancora testato, ma il seguente potrebbe funzionare:

double precision function logic2dbl(a) 
    logical, intent(in) :: a 

    if (a) then 
    logic2dbl = 1.d0 
    else 
    logic2dbl = 0.d0 
    end if 
end function logic2dbl 
+0

Si dovrebbe restituire il valore come nome della funzione: 'logic2dbl = ...'. – sigma

+0

Inoltre, è necessario sostituire .eq. con .eqv. Accetterò quando la risposta è sintatticamente corretta! – Guillochon

8

Oltre a scrivere una funzione per gestire questa situazione, si potrebbe anche utilizzare direttamente la funzione di unione intrinseca: b = merge(1.d0, 0.d0, a). Oppure puoi scrivere una subroutine di assegnazione definita che esegue questa operazione, in modo che tu possa semplicemente digitare b = a.

0

In gfortran, sto utilizzando il TRANSFER intrinseco per quel tipo di lavoro. Supponendo un numero intero variabile my_int quindi:

my_int = transfer(.false.,my_int) 

il risultato di my_int è 0 come previsto.

+2

OP chiede variabili reali ... – lodo

+1

'realvar = transfer (logico, 1)' (basta inserire un intero letterale 1 per lo stampo) funziona (o sembra). Non sono sicuro di quanto questo sia portatile, dato il commento @WaywiserTundish – agentp