Esiste una migliore assegnazione a doppia precisione in Fortran 90?

In Fortran 90 (usando gfortran su Mac OS X) se assegno un valore a una variabile a precisione doppia senza virare esplicitamente su un tipo, la precisione non “prende”. Quello che voglio dire è che se eseguo il seguente programma:

program sample_dp implicit none integer, parameter :: sp = kind(1.0) integer, parameter :: dp = kind(1.0d0) real(sp) :: a = 0. real(dp) :: b = 0., c = 0., d = 0.0_dp, e = 0_dp ! assign values a = 0.12345678901234567890 b = 0.12345678901234567890 c = DBLE(0.12345678901234567890) d = 0.12345678901234567890_dp write(*,101) a, b, c, d 101 format(1x, 'Single precision: ', T27, F17.15, / & 1x, 'Double precisison: ', T27, F17.15, / & 1x, 'Double precision (DBLE): ', T27, F17.15, / & 1x, 'Double precision (_dp): ', T27, F17.15) end program 

Ottengo il risultato:

 Single precision: 0.123456791043282 Double precision: 0.123456791043282 Double precision (DBLE): 0.123456791043282 Double precision (_dp): 0.123456789012346 

Il singolo risultato di precisione inizia a arrotondare all’8 ° decimale come previsto, ma solo la variabile di precisione doppia che ho assegnato esplicitamente con _dp mantiene tutte le 16 cifre di precisione. Ciò sembra strano, come mi aspetterei (sono relativamente nuovo a Fortran) che una variabile a doppia precisione sarebbe automaticamente a doppia precisione. C’è un modo migliore per assegnare le variabili a doppia precisione, o devo digitarli esplicitamente come sopra?

Un vero non contrassegnato come doppia precisione verrà considerato come una precisione singola. Solo perché qualche tempo dopo lo assegni a una doppia variabile di precisione, o lo converti in doppia precisione, ciò non significa che il valore sarà ‘magicamente’ una precisione doppia. Non guarda avanti per vedere come verrà utilizzato il valore.

Ci sono diverse domande che collegano qui, quindi è bene specificare alcuni dettagli in modo più esplicito con esempi, specialmente per i principianti.

Come affermato da MRAB nella sua risposta corretta, un’espressione viene sempre valutata senza alcun contesto, quindi

  0.12345678901234567890 

è un letterale flottante di precisione (singolo) predefinito, indipendentemente da dove appare. Lo stesso vale per i numeri in virgola mobile nella forma esponenziale

  0.12345678901234567890E0 

è anche un numero di precisione predefinito.

Se si vuole usare una costante a doppia precisione, si può usare D invece di E nel modulo sopra. Anche se una costante di precisione doppia viene assegnata a una variabile di precisione predefinita, viene prima trattata come un doppio numero di precisione e quindi viene convertita alla precisione predefinita.

Il modo in cui stai usando nella tua domanda (utilizzando la notazione gentile e diverse costanti gentili) è più generale e più moderno, ma il principio è lo stesso.

  0.12345678901234567890_sp 

è un numero di tipo sp e

  0.12345678901234567890_dp 

è un numero di tipo dp e non importa dove appaiono.

Come mostra il tuo esempio, non si tratta solo di assegnazione. Nella linea

  c = DBLE(0.12345678901234567890) 

prima il numero 0.12345678901234567890 è la precisione predefinita. Quindi viene convertito in doppia precisione da DBLE , ma ciò avviene dopo che alcune cifre sono già perse. Quindi questo nuovo numero di doppia precisione è assegnato a c .