Fortran - Guida rapida

Fortran, come derivato da Formula Translating System, è un linguaggio di programmazione imperativo per tutti gli usi. Viene utilizzato per il calcolo numerico e scientifico.

Fortran è stato originariamente sviluppato da IBM negli anni '50 per applicazioni scientifiche e ingegneristiche. Fortran ha governato quest'area di programmazione per molto tempo ed è diventato molto popolare per il calcolo ad alte prestazioni, perché.

Supporta -

  • Analisi numerica e calcolo scientifico
  • Programmazione strutturata
  • Programmazione di array
  • Programmazione modulare
  • Programmazione generica
  • Calcolo ad alte prestazioni su supercomputer
  • Programmazione orientata agli oggetti
  • Programmazione concorrente
  • Grado ragionevole di portabilità tra i sistemi informatici

Fatti su Fortran

  • Fortran è stato creato da un team, guidato da John Backus in IBM nel 1957.

  • Inizialmente il nome era scritto in maiuscolo, ma gli standard e le implementazioni attuali richiedono solo che la prima lettera sia maiuscola.

  • Fortran sta per FORmula TRANslator.

  • Sviluppato originariamente per calcoli scientifici, aveva un supporto molto limitato per stringhe di caratteri e altre strutture necessarie per la programmazione generica.

  • Successive estensioni e sviluppi lo hanno trasformato in un linguaggio di programmazione di alto livello con un buon grado di portabilità.

  • Le versioni originali, Fortran I, II e III sono considerate obsolete ora.

  • La versione più vecchia ancora in uso è Fortran IV e Fortran 66.

  • Le versioni più comunemente utilizzate oggi sono: Fortran 77, Fortran 90 e Fortran 95.

  • Fortran 77 ha aggiunto le stringhe come tipo distinto.

  • Fortran 90 ha aggiunto vari tipi di threading e elaborazione diretta degli array.

Configurazione di Fortran in Windows

G95 è il compilatore multi-architettura GNU Fortran, utilizzato per configurare Fortran in Windows. La versione per Windows emula un ambiente unix usando MingW sotto Windows. L'installer si occupa di questo e aggiunge automaticamente g95 alla variabile PATH di Windows.

Puoi ottenere la versione stabile di G95 da qui

Come utilizzare G95

Durante l'installazione, g95viene automaticamente aggiunto alla variabile PATH se selezioni l'opzione "CONSIGLIATO". Ciò significa che puoi semplicemente aprire una nuova finestra del prompt dei comandi e digitare "g95" per visualizzare il compilatore. Trova alcuni comandi di base di seguito per iniziare.

Suor n Comando e descrizione
1

g95 –c hello.f90

Compila hello.f90 in un file oggetto denominato hello.o

2

g95 hello.f90

Compila hello.f90 e lo collega per produrre un eseguibile a.out

3

g95 -c h1.f90 h2.f90 h3.f90

Compila più file di origine. Se tutto va bene, vengono creati i file oggetto h1.o, h2.o e h3.o

4

g95 -o hello h1.f90 h2.f90 h3.f90

Compila più file sorgente e li collega insieme a un file eseguibile denominato "ciao"

Opzioni della riga di comando per G95

-c Compile only, do not run the linker.
-o Specify the name of the output file, either an object file or the executable.

È possibile specificare più file di origine e oggetto contemporaneamente. I file Fortran sono indicati da nomi che terminano in ".f", ".F", ".for", ".FOR", ".f90", ".F90", ".f95", ".F95", ". f03 "e" .F03 ". È possibile specificare più file di origine. Anche i file oggetto possono essere specificati e saranno collegati per formare un file eseguibile.

Un programma Fortran è costituito da una raccolta di unità di programma come un programma principale, moduli e sottoprogrammi o procedure esterni.

Ogni programma contiene un programma principale e può contenere o meno altre unità di programma. La sintassi del programma principale è la seguente:

program program_name
implicit none      

! type declaration statements      
! executable statements  

end program program_name

Un semplice programma in Fortran

Scriviamo un programma che aggiunge due numeri e stampa il risultato:

program addNumbers

! This simple program adds two numbers
   implicit none

! Type declarations
   real :: a, b, result

! Executable statements
   a = 12.0
   b = 15.0
   result = a + b
   print *, 'The total is ', result

end program addNumbers

Quando compili ed esegui il programma sopra, produce il seguente risultato:

The total is 27.0000000

Si prega di notare che -

  • Tutti i programmi Fortran iniziano con la parola chiave program e terminare con la parola chiave end program, seguito dal nome del programma.

  • Il implicit noneconsente al compilatore di verificare che tutti i tipi di variabile siano dichiarati correttamente. Devi sempre usareimplicit none all'inizio di ogni programma.

  • I commenti in Fortran iniziano con il punto esclamativo (!), Poiché tutti i caratteri successivi (tranne in una stringa di caratteri) vengono ignorati dal compilatore.

  • Il print * comando visualizza i dati sullo schermo.

  • Il rientro delle righe di codice è una buona pratica per mantenere leggibile un programma.

  • Fortran consente sia lettere maiuscole che minuscole. Fortran non fa distinzione tra maiuscole e minuscole, ad eccezione dei valori letterali stringa.

Nozioni di base

Il basic character set di Fortran contiene -

  • le lettere A ... Z e a ... z
  • le cifre 0 ... 9
  • il carattere di sottolineatura (_)
  • i caratteri speciali =: + blank - * / () [],. $ '! "% &; <>?

Tokenssono costituiti da caratteri nel set di caratteri di base. Un token può essere una parola chiave, un identificatore, una costante, una stringa letterale o un simbolo.

Le dichiarazioni del programma sono fatte di gettoni.

Identificatore

Un identificatore è un nome utilizzato per identificare una variabile, una procedura o qualsiasi altro elemento definito dall'utente. Un nome in Fortran deve seguire le seguenti regole:

  • Non può essere più lungo di 31 caratteri.

  • Deve essere composto da caratteri alfanumerici (tutte le lettere dell'alfabeto e le cifre da 0 a 9) e trattini bassi (_).

  • Il primo carattere di un nome deve essere una lettera.

  • I nomi non fanno distinzione tra maiuscole e minuscole

Parole chiave

Le parole chiave sono parole speciali, riservate alla lingua. Queste parole riservate non possono essere utilizzate come identificatori o nomi.

La tabella seguente elenca le parole chiave di Fortran:

Le parole chiave non I / O
allocabile allocare assegnare Incarico bloccare i dati
chiamata Astuccio personaggio Comune complesso
contiene Continua ciclo dati deallocare
predefinito fare doppia precisione altro altrimenti se
altrove dati del blocco finale fine fare funzione di fine finisci se
fine interfaccia modulo finale fine programma fine selezionare fine subroutine
tipo di fine fine dove iscrizione equivalenza Uscita
esterno funzione vai a Se implicito
in dentro fuori numero intero intento interfaccia
intrinseco genere len logico modulo
Lista di nomi annullare solo operatore opzionale
su parametro pausa puntatore privato
programma pubblico vero ricorsivo risultato
ritorno Salva seleziona caso fermare sottoprogramma
bersaglio poi genere genere() uso
Dove Mentre
Le parole chiave correlate all'I / O
backspace vicino endfile formato chiedere informazioni
Aperto Stampa leggere riavvolgere Scrivi

Fortran fornisce cinque tipi di dati intrinseci, tuttavia, puoi anche derivare i tuoi tipi di dati. I cinque tipi intrinseci sono:

  • Tipo intero
  • Tipo reale
  • Tipo complesso
  • Tipo logico
  • Tipo di carattere

Tipo intero

I tipi interi possono contenere solo valori interi. L'esempio seguente estrae il valore più grande che può essere contenuto in un normale numero intero di quattro byte:

program testingInt
implicit none

   integer :: largeval
   print *, huge(largeval)
   
end program testingInt

Quando compili ed esegui il programma sopra, produce il seguente risultato:

2147483647

Nota che il file huge()la funzione fornisce il numero più grande che può essere contenuto dal tipo di dati intero specifico. È inoltre possibile specificare il numero di byte utilizzando ilkindspecificatore. Il seguente esempio lo dimostra:

program testingInt
implicit none

   !two byte integer
   integer(kind = 2) :: shortval
   
   !four byte integer
   integer(kind = 4) :: longval
   
   !eight byte integer
   integer(kind = 8) :: verylongval
   
   !sixteen byte integer
   integer(kind = 16) :: veryverylongval
   
   !default integer 
   integer :: defval
        
   print *, huge(shortval)
   print *, huge(longval)
   print *, huge(verylongval)
   print *, huge(veryverylongval)
   print *, huge(defval)
   
end program testingInt

Quando compili ed esegui il programma sopra, produce il seguente risultato:

32767
2147483647
9223372036854775807
170141183460469231731687303715884105727
2147483647

Tipo reale

Memorizza i numeri in virgola mobile, come 2.0, 3.1415, -100.876, ecc.

Tradizionalmente ci sono due diversi tipi reali, l'impostazione predefinita real tipo e double precision genere.

Tuttavia, Fortran 90/95 fornisce un maggiore controllo sulla precisione dei tipi di dati reali e interi tramite kind specificatore, che studieremo nel capitolo sui numeri.

L'esempio seguente mostra l'uso del tipo di dati reale:

program division   
implicit none  

   ! Define real variables   
   real :: p, q, realRes 
   
   ! Define integer variables  
   integer :: i, j, intRes  
   
   ! Assigning  values   
   p = 2.0 
   q = 3.0    
   i = 2 
   j = 3  
   
   ! floating point division
   realRes = p/q  
   intRes = i/j
   
   print *, realRes
   print *, intRes
   
end program division

Quando compili ed esegui il programma sopra, produce il seguente risultato:

0.666666687    
0

Tipo complesso

Viene utilizzato per memorizzare numeri complessi. Un numero complesso ha due parti, la parte reale e la parte immaginaria. Due unità di memorizzazione numeriche consecutive memorizzano queste due parti.

Ad esempio, il numero complesso (3.0, -5.0) è uguale a 3.0 - 5.0i

Discuteremo i tipi complessi in modo più dettagliato, nel capitolo Numeri.

Tipo logico

Ci sono solo due valori logici: .true. e .false.

Tipo di carattere

Il tipo di carattere memorizza caratteri e stringhe. La lunghezza della stringa può essere specificata dallo specificatore len. Se non viene specificata alcuna lunghezza, è 1.

For example,

character (len = 40) :: name  
name = “Zara Ali”

L'espressione, name(1:4) darebbe la sottostringa "Zara".

Digitazione implicita

Le versioni precedenti di Fortran consentivano una funzionalità chiamata tipizzazione implicita, ovvero non è necessario dichiarare le variabili prima dell'uso. Se una variabile non viene dichiarata, la prima lettera del suo nome ne determinerà il tipo.

I nomi delle variabili che iniziano con i, j, k, l, m o n, sono considerati per variabili intere e gli altri sono variabili reali. Tuttavia, è necessario dichiarare tutte le variabili poiché è una buona pratica di programmazione. Per questo inizi il tuo programma con l'affermazione -

implicit none

Questa istruzione disattiva la digitazione implicita.

Una variabile non è altro che un nome dato a un'area di memoria che i nostri programmi possono manipolare. Ogni variabile dovrebbe avere un tipo specifico, che determina la dimensione e il layout della memoria della variabile; l'intervallo di valori che possono essere memorizzati all'interno di quella memoria; e l'insieme di operazioni che possono essere applicate alla variabile.

Il nome di una variabile può essere composto da lettere, cifre e il carattere di sottolineatura. Un nome in Fortran deve seguire le seguenti regole:

  • Non può essere più lungo di 31 caratteri.

  • Deve essere composto da caratteri alfanumerici (tutte le lettere dell'alfabeto e le cifre da 0 a 9) e trattini bassi (_).

  • Il primo carattere di un nome deve essere una lettera.

  • I nomi non fanno distinzione tra maiuscole e minuscole.

In base ai tipi di base spiegati nel capitolo precedente, di seguito sono riportati i tipi di variabili:

Suor n Tipo e descrizione
1

Integer

Può contenere solo valori interi.

2

Real

Memorizza i numeri in virgola mobile.

3

Complex

Viene utilizzato per memorizzare numeri complessi.

4

Logical

Memorizza valori booleani logici.

5

Character

Memorizza caratteri o stringhe.

Dichiarazione di variabili

Le variabili vengono dichiarate all'inizio di un programma (o sottoprogramma) in un'istruzione di dichiarazione del tipo.

La sintassi per la dichiarazione delle variabili è la seguente:

type-specifier :: variable_name

Per esempio

integer :: total  	
real :: average 
complex :: cx  
logical :: done 
character(len = 80) :: message ! a string of 80 characters

Successivamente puoi assegnare valori a queste variabili, come,

total = 20000  
average = 1666.67   
done = .true.   
message = “A big Hello from Tutorials Point” 
cx = (3.0, 5.0) ! cx = 3.0 + 5.0i

Puoi anche usare la funzione intrinseca cmplx, per assegnare valori a una variabile complessa -

cx = cmplx (1.0/2.0, -7.0) ! cx = 0.5 – 7.0i 
cx = cmplx (x, y) ! cx = x + yi

Esempio

L'esempio seguente mostra la dichiarazione, l'assegnazione e la visualizzazione delle variabili sullo schermo:

program variableTesting
implicit none

   ! declaring variables
   integer :: total      
   real :: average 
   complex :: cx  
   logical :: done 
   character(len=80) :: message ! a string of 80 characters
   
   !assigning values
   total = 20000  
   average = 1666.67   
   done = .true.   
   message = "A big Hello from Tutorials Point" 
   cx = (3.0, 5.0) ! cx = 3.0 + 5.0i

   Print *, total
   Print *, average
   Print *, cx
   Print *, done
   Print *, message
   
end program variableTesting

Quando il codice precedente viene compilato ed eseguito, produce il seguente risultato:

20000
1666.67004    
(3.00000000, 5.00000000 )
T
A big Hello from Tutorials Point

Le costanti si riferiscono ai valori fissi che il programma non può alterare durante la sua esecuzione. Questi valori fissi vengono anche chiamatiliterals.

Le costanti possono essere di qualsiasi tipo di dati di base come una costante intera, una costante mobile, una costante di carattere, una costante complessa o una stringa letterale. Ci sono solo due costanti logiche:.true. e .false.

Le costanti vengono trattate come variabili regolari, tranne per il fatto che i loro valori non possono essere modificati dopo la loro definizione.

Costanti e valori letterali denominati

Esistono due tipi di costanti:

  • Costanti letterali
  • Costanti denominate

Una costante letterale ha un valore, ma nessun nome.

Ad esempio, di seguito sono riportate le costanti letterali:

genere Esempio
Costanti intere 0 1-1 300 123456789
Costanti reali 0,0 1,0 -1,0 123,456 7,1E + 10 -52,715E-30
Costanti complesse (0,0, 0,0) (-123.456E + 30, 987.654E-29)
Costanti logiche .vero. .false.
Costanti dei caratteri

"PQR" "a" "123'abc $% # @!"

" una citazione "" "

'PQR' 'a' '123 "abc $% # @!'

'un apostrofo' ''

Una costante con nome ha un valore oltre che un nome.

Le costanti denominate dovrebbero essere dichiarate all'inizio di un programma o di una procedura, proprio come una dichiarazione di tipo di variabile, indicandone il nome e il tipo. Le costanti denominate vengono dichiarate con l'attributo del parametro. Per esempio,

real, parameter :: pi = 3.1415927

Esempio

Il seguente programma calcola lo spostamento dovuto al movimento verticale sotto gravità.

program gravitationalDisp

! this program calculates vertical motion under gravity 
implicit none  

   ! gravitational acceleration
   real, parameter :: g = 9.81   
   
   ! variable declaration
   real :: s ! displacement   
   real :: t ! time  
   real :: u ! initial speed  
   
   ! assigning values 
   t = 5.0   
   u = 50  
   
   ! displacement   
   s = u * t - g * (t**2) / 2  
   
   ! output 
   print *, "Time = ", t
   print *, 'Displacement = ',s  
   
end program gravitationalDisp

Quando il codice precedente viene compilato ed eseguito, produce il seguente risultato:

Time = 5.00000000    
Displacement = 127.374992

Un operatore è un simbolo che dice al compilatore di eseguire specifiche manipolazioni matematiche o logiche. Fortran fornisce i seguenti tipi di operatori:

  • Operatori aritmetici
  • Operatori relazionali
  • Operatori logici

Esaminiamo tutti questi tipi di operatori uno per uno.

Operatori aritmetici

La tabella seguente mostra tutti gli operatori aritmetici supportati da Fortran. Assumi variabileA detiene 5 e variabile B tiene 3 poi -

Mostra esempi

Operatore Descrizione Esempio
+ Operatore di addizione, aggiunge due operandi. A + B darà 8
- Operatore di sottrazione, sottrae il secondo operando dal primo. A - B darà 2
* Operatore di moltiplicazione, moltiplica entrambi gli operandi. A * B darà 15
/ Operatore di divisione, divide il numeratore per il de-numeratore. A / B darà 1
** Operatore di esponenziazione, eleva un operando alla potenza dell'altro. A ** B darà 125

Operatori relazionali

La tabella seguente mostra tutti gli operatori relazionali supportati da Fortran. Assumi variabileA detiene 10 e variabile B detiene 20, quindi -

Mostra esempi

Operatore Equivalente Descrizione Esempio
== .eq. Controlla se i valori di due operandi sono uguali o meno, in caso affermativo la condizione diventa vera. (A == B) non è vero.
/ = .ne. Controlla se i valori di due operandi sono uguali o meno, se i valori non sono uguali la condizione diventa vera. (A! = B) è vero.
> .gt. Controlla se il valore dell'operando sinistro è maggiore del valore dell'operando destro, in caso affermativo la condizione diventa vera. (A> B) non è vero.
< .lt. Controlla se il valore dell'operando sinistro è inferiore al valore dell'operando destro, in caso affermativo la condizione diventa vera. (A <B) è vero.
> = .ge. Controlla se il valore dell'operando sinistro è maggiore o uguale al valore dell'operando destro, in caso affermativo la condizione diventa vera. (A> = B) non è vero.
<= .le. Controlla se il valore dell'operando sinistro è minore o uguale al valore dell'operando destro, in caso affermativo la condizione diventa vera. (A <= B) è vero.

Operatori logici

Gli operatori logici in Fortran funzionano solo sui valori logici .true. e .false.

La tabella seguente mostra tutti gli operatori logici supportati da Fortran. Supponiamo che la variabile A contenga .true. e la variabile B vale .false. , quindi -

Mostra esempi

Operatore Descrizione Esempio
.e. Chiamato operatore AND logico. Se entrambi gli operandi sono diversi da zero, la condizione diventa vera. (A. E. B) è falso.
.o. Chiamato Operatore OR logico. Se uno dei due operandi è diverso da zero, la condizione diventa vera. (A. Or. B) è vero.
.non. Chiamato operatore NOT logico. Utilizzare per invertire lo stato logico del suo operando. Se una condizione è vera, l'operatore NOT logico la renderà falsa. ! (A. E. B) è vero.
.eqv. Chiamato operatore EQUIVALENTE logico. Utilizzato per verificare l'equivalenza di due valori logici. (A .eqv. B) è falso.
.neqv. Chiamato operatore logico NON EQUIVALENTE. Utilizzato per verificare la non equivalenza di due valori logici. (A .neqv. B) è vero.

Precedenza degli operatori in Fortran

La precedenza degli operatori determina il raggruppamento dei termini in un'espressione. Ciò influisce sul modo in cui viene valutata un'espressione. Alcuni operatori hanno la precedenza maggiore di altri; ad esempio, l'operatore di moltiplicazione ha una precedenza maggiore dell'operatore di addizione.

Ad esempio, x = 7 + 3 * 2; qui, x è assegnato 13, non 20 perché l'operatore * ha una precedenza maggiore di +, quindi viene prima moltiplicato per 3 * 2 e poi somma in 7.

Qui, gli operatori con la precedenza più alta vengono visualizzati nella parte superiore della tabella, quelli con la priorità più bassa in fondo. All'interno di un'espressione, verranno valutati per primi gli operatori con precedenza più alta.

Mostra esempi

Categoria Operatore Associatività
NOT logico e segno negativo .non. (-) Da sinistra a destra
Esponenziazione ** Da sinistra a destra
Moltiplicativo * / Da sinistra a destra
Additivo + - Da sinistra a destra
Relazionale <<=>> = Da sinistra a destra
Uguaglianza == / = Da sinistra a destra
AND logico .e. Da sinistra a destra
OR logico .o. Da sinistra a destra
Incarico = Da destra a sinistra

Le strutture decisionali richiedono che il programmatore specifichi una o più condizioni che devono essere valutate o testate dal programma, insieme a una o più istruzioni da eseguire, se la condizione è determinata essere vera, e, facoltativamente, altre istruzioni da eseguire se condizione è determinata essere falsa.

Di seguito è riportata la forma generale di una tipica struttura decisionale presente nella maggior parte dei linguaggi di programmazione:

Fortran fornisce i seguenti tipi di costrutti per il processo decisionale.

Suor n Dichiarazione e descrizione
1 Se ... allora costruisci

Un if… then… end if istruzione consiste in un'espressione logica seguita da una o più istruzioni.

2 Se ... allora ... altrimenti costruisci

Un if… then L'istruzione può essere seguita da un opzionale else statement, che viene eseguito quando l'espressione logica è falsa.

3 if ... else if ... else Istruzione

Un if Il costrutto dell'istruzione può avere uno o più opzionali else-ifcostruisce. Quando ilif condizione fallisce, immediatamente seguita else-ifviene eseguito. Quando ilelse-if fallisce anche il suo successore else-if viene eseguita l'istruzione (se presente) e così via.

4 nidificato se costrutto

Puoi usarne uno if o else if dichiarazione dentro un'altra if o else if dichiarazione (i).

5 selezionare il costrutto del caso

UN select case consente di verificare l'uguaglianza di una variabile rispetto a un elenco di valori.

6 costrutto select case annidato

Puoi usarne uno select case dichiarazione dentro un'altra select case dichiarazione (i).

Potrebbe esserci una situazione in cui è necessario eseguire un blocco di codice più volte. In generale, le istruzioni vengono eseguite in sequenza: la prima istruzione in una funzione viene eseguita per prima, seguita dalla seconda e così via.

I linguaggi di programmazione forniscono varie strutture di controllo che consentono percorsi di esecuzione più complicati.

Un'istruzione loop ci consente di eseguire un'istruzione o un gruppo di istruzioni più volte e la seguente è la forma generale di un'istruzione loop nella maggior parte dei linguaggi di programmazione:

Fortran fornisce i seguenti tipi di costrutti di ciclo per gestire i requisiti di ciclo. Fare clic sui seguenti collegamenti per verificarne i dettagli.

Suor n Tipo e descrizione del loop
1 fare il ciclo

Questo costrutto consente di eseguire un'istruzione o una serie di istruzioni in modo iterativo, mentre una data condizione è vera.

2 fare mentre il ciclo

Ripete un'istruzione o un gruppo di istruzioni finché una determinata condizione è vera. Verifica la condizione prima di eseguire il corpo del ciclo.

3 loop annidati

È possibile utilizzare uno o più costrutti di loop all'interno di qualsiasi altro costrutto di loop.

Dichiarazioni di controllo del loop

Le istruzioni di controllo del ciclo cambiano l'esecuzione dalla sua sequenza normale. Quando l'esecuzione esce da un ambito, tutti gli oggetti automatici creati in tale ambito vengono eliminati.

Fortran supporta le seguenti istruzioni di controllo. Fare clic sui seguenti collegamenti per verificarne i dettagli.

Suor n Dichiarazione di controllo e descrizione
1 Uscita

Se viene eseguita l'istruzione exit, il ciclo viene chiuso e l'esecuzione del programma continua alla prima istruzione eseguibile dopo l'istruzione end do.

2 ciclo

Se viene eseguita un'istruzione di ciclo, il programma prosegue dall'inizio dell'iterazione successiva.

3 fermare

Se desideri che l'esecuzione del tuo programma si fermi, puoi inserire un'istruzione stop

I numeri in Fortran sono rappresentati da tre tipi di dati intrinseci:

  • Tipo intero
  • Tipo reale
  • Tipo complesso

Tipo intero

I tipi interi possono contenere solo valori interi. L'esempio seguente estrae il valore più grande che potrebbe essere contenuto in un normale numero intero di quattro byte:

program testingInt
implicit none

   integer :: largeval
   print *, huge(largeval)
   
end program testingInt

Quando compili ed esegui il programma sopra, produce il seguente risultato:

2147483647

Si prega di notare che il file huge()la funzione fornisce il numero più grande che può essere contenuto dal tipo di dati intero specifico. È inoltre possibile specificare il numero di byte utilizzando ilkindspecificatore. Il seguente esempio lo dimostra:

program testingInt
implicit none

   !two byte integer
   integer(kind = 2) :: shortval
   
   !four byte integer
   integer(kind = 4) :: longval
   
   !eight byte integer
   integer(kind = 8) :: verylongval
   
   !sixteen byte integer
   integer(kind = 16) :: veryverylongval
   
   !default integer 
   integer :: defval
        
   print *, huge(shortval)
   print *, huge(longval)
   print *, huge(verylongval)
   print *, huge(veryverylongval)
   print *, huge(defval)
   
end program testingInt

Quando compili ed esegui il programma sopra, produce il seguente risultato:

32767
2147483647
9223372036854775807
170141183460469231731687303715884105727
2147483647

Tipo reale

Memorizza i numeri in virgola mobile, come 2.0, 3.1415, -100.876, ecc.

Tradizionalmente ce n'erano due diversi real tipi: il tipo reale predefinito e double precision genere.

Tuttavia, Fortran 90/95 fornisce un maggiore controllo sulla precisione dei tipi di dati reali e interi tramite kind specificatore, che studieremo a breve.

L'esempio seguente mostra l'uso del tipo di dati reale:

program division   
implicit none

   ! Define real variables   
   real :: p, q, realRes 
   
   ! Define integer variables  
   integer :: i, j, intRes  
   
   ! Assigning  values   
   p = 2.0 
   q = 3.0    
   i = 2 
   j = 3  
   
   ! floating point division
   realRes = p/q  
   intRes = i/j
   
   print *, realRes
   print *, intRes
   
end program division

Quando compili ed esegui il programma sopra, produce il seguente risultato:

0.666666687    
0

Tipo complesso

Viene utilizzato per memorizzare numeri complessi. Un numero complesso ha due parti: la parte reale e la parte immaginaria. Due unità di memorizzazione numeriche consecutive memorizzano queste due parti.

Ad esempio, il numero complesso (3.0, -5.0) è uguale a 3.0 - 5.0i

La funzione generica cmplx()crea un numero complesso. Produce un risultato le cui parti reali e immaginarie sono a precisione singola, indipendentemente dal tipo di argomenti di input.

program createComplex
implicit none

   integer :: i = 10
   real :: x = 5.17
   print *, cmplx(i, x)
   
end program createComplex

Quando compili ed esegui il programma sopra, produce il seguente risultato:

(10.0000000, 5.17000008)

Il seguente programma dimostra l'aritmetica dei numeri complessi:

program ComplexArithmatic
implicit none

   complex, parameter :: i = (0, 1)   ! sqrt(-1)   
   complex :: x, y, z 
   
   x = (7, 8); 
   y = (5, -7)   
   write(*,*) i * x * y
   
   z = x + y
   print *, "z = x + y = ", z
   
   z = x - y
   print *, "z = x - y = ", z 
   
   z = x * y
   print *, "z = x * y = ", z 
   
   z = x / y
   print *, "z = x / y = ", z 
   
end program ComplexArithmatic

Quando compili ed esegui il programma sopra, produce il seguente risultato:

(9.00000000, 91.0000000)
z = x + y = (12.0000000, 1.00000000)
z = x - y = (2.00000000, 15.0000000)
z = x * y = (91.0000000, -9.00000000)
z = x / y = (-0.283783793, 1.20270276)

La portata, la precisione e la dimensione dei numeri

L'intervallo sui numeri interi, la precisione e la dimensione dei numeri in virgola mobile dipende dal numero di bit allocati al tipo di dati specifico.

La tabella seguente mostra il numero di bit e l'intervallo per i numeri interi:

Numero di bit Valore massimo Motivo
64 9.223.372.036.854.774.807 (2 ** 63) –1
32 2.147.483.647 (2 ** 31) –1

La tabella seguente mostra il numero di bit, il valore più piccolo e più grande e la precisione per i numeri reali.

Numero di bit Valore massimo Valore minimo Precisione
64 0,8 E + 308 0,5E – 308 15-18
32 1.7E + 38 0.3E – 38 6-9

I seguenti esempi lo dimostrano:

program rangePrecision
implicit none

   real:: x, y, z
   x = 1.5e+40
   y = 3.73e+40
   z = x * y 
   print *, z
   
end program rangePrecision

Quando compili ed esegui il programma sopra, produce il seguente risultato:

x = 1.5e+40
          1
Error : Real constant overflows its kind at (1)
main.f95:5.12:

y = 3.73e+40
           1
Error : Real constant overflows its kind at (1)

Ora usiamo un numero più piccolo -

program rangePrecision
implicit none

   real:: x, y, z
   x = 1.5e+20
   y = 3.73e+20
   z = x * y 
   print *, z
   
   z = x/y
   print *, z
   
end program rangePrecision

Quando compili ed esegui il programma sopra, produce il seguente risultato:

Infinity
0.402144760

Ora guardiamo l'underflow -

program rangePrecision
implicit none

   real:: x, y, z
   x = 1.5e-30
   y = 3.73e-60
   z = x * y 
   print *, z
   
   z = x/y
   print *, z

end program rangePrecision

Quando compili ed esegui il programma sopra, produce il seguente risultato:

y = 3.73e-60
           1
Warning : Real constant underflows its kind at (1)

Executing the program....
$demo 

0.00000000E+00
Infinity

Il Kind Specifier

Nella programmazione scientifica, spesso è necessario conoscere la portata e la precisione dei dati della piattaforma hardware su cui si sta lavorando.

La funzione intrinseca kind() consente di interrogare i dettagli delle rappresentazioni dei dati dell'hardware prima di eseguire un programma.

program kindCheck
implicit none
   
   integer :: i 
   real :: r 
   complex :: cp 
   print *,' Integer ', kind(i) 
   print *,' Real ', kind(r) 
   print *,' Complex ', kind(cp) 
   
end program kindCheck

Quando compili ed esegui il programma sopra, produce il seguente risultato:

Integer 4
Real 4
Complex 4

Puoi anche controllare il tipo di tutti i tipi di dati:

program checkKind
implicit none

   integer :: i 
   real :: r 
   character :: c 
   logical :: lg 
   complex :: cp 
   
   print *,' Integer ', kind(i) 
   print *,' Real ', kind(r) 
   print *,' Complex ', kind(cp)
   print *,' Character ', kind(c) 
   print *,' Logical ', kind(lg)
   
end program checkKind

Quando compili ed esegui il programma sopra, produce il seguente risultato:

Integer 4
Real 4
Complex 4
Character 1
Logical 4

Il linguaggio Fortran può trattare i caratteri come caratteri singoli o stringhe contigue.

I caratteri possono essere qualsiasi simbolo preso dal set di caratteri di base, cioè dalle lettere, dai decimali, dal trattino basso e da 21 caratteri speciali.

Una costante di carattere è una stringa di caratteri a valore fisso.

Il tipo di dati intrinseco charactermemorizza caratteri e stringhe. La lunghezza della stringa può essere specificata dalenspecificatore. Se non viene specificata alcuna lunghezza, è 1. È possibile fare riferimento a singoli caratteri all'interno di una stringa riferendosi alla posizione; il carattere più a sinistra è nella posizione 1.

Dichiarazione del personaggio

La dichiarazione di un tipo di carattere dati è la stessa di altre variabili -

type-specifier :: variable_name

Per esempio,

character :: reply, sex

puoi assegnare un valore come,

reply = ‘N’ 
sex = ‘F’

L'esempio seguente dimostra la dichiarazione e l'uso del tipo di dati carattere -

program hello
implicit none

   character(len = 15) :: surname, firstname 
   character(len = 6) :: title 
   character(len = 25)::greetings
   
   title = 'Mr. ' 
   firstname = 'Rowan ' 
   surname = 'Atkinson'
   greetings = 'A big hello from Mr. Bean'
   
   print *, 'Here is ', title, firstname, surname
   print *, greetings
   
end program hello

Quando compili ed esegui il programma sopra, produce il seguente risultato:

Here is Mr. Rowan Atkinson       
A big hello from Mr. Bean

Concatenazione di caratteri

L'operatore di concatenazione //, concatena i caratteri.

Il seguente esempio lo dimostra:

program hello
implicit none

   character(len = 15) :: surname, firstname 
   character(len = 6) :: title 
   character(len = 40):: name
   character(len = 25)::greetings
   
   title = 'Mr. ' 
   firstname = 'Rowan ' 
   surname = 'Atkinson'
   
   name = title//firstname//surname
   greetings = 'A big hello from Mr. Bean'
   
   print *, 'Here is ', name
   print *, greetings
   
end program hello

Quando compili ed esegui il programma sopra, produce il seguente risultato:

Here is Mr.Rowan Atkinson       
A big hello from Mr.Bean

Alcune funzioni dei caratteri

La tabella seguente mostra alcune funzioni dei caratteri di uso comune insieme alla descrizione:

Suor n Descrizione della funzione
1

len(string)

Restituisce la lunghezza di una stringa di caratteri

2

index(string,sustring)

Trova la posizione di una sottostringa in un'altra stringa, restituisce 0 se non viene trovata.

3

achar(int)

Converte un numero intero in un carattere

4

iachar(c)

Converte un carattere in un numero intero

5

trim(string)

Restituisce la stringa con gli spazi finali rimossi.

6

scan(string, chars)

Cerca nella "stringa" da sinistra a destra (a meno che back = .true.) La prima occorrenza di qualsiasi carattere contenuto in "chars". Restituisce un numero intero che fornisce la posizione di quel carattere, o zero se nessuno dei caratteri in "chars" è stato trovato.

7

verify(string, chars)

Esamina la "stringa" da sinistra a destra (a meno che back = .true.) Alla ricerca della prima occorrenza di qualsiasi carattere non contenuto in "chars". Restituisce un numero intero che fornisce la posizione di quel carattere, o zero se sono stati trovati solo i caratteri in "chars"

8

adjustl(string)

Giustifica a sinistra i caratteri contenuti nella "stringa"

9

adjustr(string)

Giustifica a destra i caratteri contenuti nella "stringa"

10

len_trim(string)

Restituisce un numero intero uguale alla lunghezza di "stringa" (len (stringa)) meno il numero di spazi vuoti finali

11

repeat(string,ncopy)

Restituisce una stringa di lunghezza uguale a "ncopy" moltiplicata per la lunghezza di "stringa" e contenente "ncopy" copie concatenate di "stringa"

Esempio 1

Questo esempio mostra l'uso di index funzione -

program testingChars
implicit none

   character (80) :: text 
   integer :: i 
   
   text = 'The intrinsic data type character stores characters and   strings.'
   i=index(text,'character') 
   
   if (i /= 0) then
      print *, ' The word character found at position ',i 
      print *, ' in text: ', text 
   end if
   
end program testingChars

Quando compili ed esegui il programma sopra, produce il seguente risultato:

The word character found at position 25
in text : The intrinsic data type character stores characters and strings.

Esempio 2

Questo esempio dimostra l'uso di trim funzione -

program hello
implicit none

   character(len = 15) :: surname, firstname 
   character(len = 6) :: title 
   character(len = 25)::greetings
   
   title = 'Mr.' 
   firstname = 'Rowan' 
   surname = 'Atkinson'
   
   print *, 'Here is', title, firstname, surname
   print *, 'Here is', trim(title),' ',trim(firstname),' ', trim(surname)
   
end program hello

Quando compili ed esegui il programma sopra, produce il seguente risultato:

Here isMr.   Rowan          Atkinson       
 Here isMr. Rowan Atkinson

Esempio 3

Questo esempio dimostra l'uso di achar funzione -

program testingChars
implicit none

   character:: ch
   integer:: i
   
   do i = 65, 90
      ch = achar(i)
      print*, i, ' ', ch
   end do
   
end program testingChars

Quando compili ed esegui il programma sopra, produce il seguente risultato:

65  A
66  B
67  C
68  D
69  E
70  F
71  G
72  H
73  I
74  J
75  K
76  L
77  M
78  N
79  O
80  P
81  Q
82  R
83  S
84  T
85  U
86  V
87  W
88  X
89  Y
90  Z

Controllo dell'ordine lessicale dei caratteri

Le seguenti funzioni determinano la sequenza lessicale dei caratteri:

Suor n Descrizione della funzione
1

lle(char, char)

Confronta se il primo carattere è lessicalmente minore o uguale al secondo

2

lge(char, char)

Confronta se il primo carattere è lessicalmente maggiore o uguale al secondo

3

lgt(char, char)

Confronta se il primo carattere è lessicalmente maggiore del secondo

4

llt(char, char)

Confronta se il primo carattere è lessicalmente inferiore al secondo

Example 4

La seguente funzione dimostra l'uso:

program testingChars
implicit none

   character:: a, b, c
   a = 'A'
   b = 'a'
   c = 'B'
   
   if(lgt(a,b)) then
      print *, 'A is lexically greater than a'
   else
      print *, 'a is lexically greater than A'
   end if
   
   if(lgt(a,c)) then
      print *, 'A is lexically greater than B'
   else
      print *, 'B is lexically greater than A'
   end if  
   
   if(llt(a,b)) then
      print *, 'A is lexically less than a'
   end if
   
   if(llt(a,c)) then
      print *, 'A is lexically less than B'
   end if
   
end program testingChars

Quando compili ed esegui il programma sopra, produce il seguente risultato:

a is lexically greater than A
B is lexically greater than A
A is lexically less than a
A is lexically less than B

Il linguaggio Fortran può trattare i caratteri come caratteri singoli o stringhe contigue.

Una stringa di caratteri può essere lunga solo un carattere o potrebbe anche essere di lunghezza zero. In Fortran, le costanti dei caratteri sono fornite tra una coppia di virgolette doppie o singole.

Il tipo di dati intrinseco charactermemorizza caratteri e stringhe. La lunghezza della stringa può essere specificata dalen specifier. Se non viene specificata alcuna lunghezza, è 1. È possibile fare riferimento a singoli caratteri all'interno di una stringa riferendosi alla posizione; il carattere più a sinistra è nella posizione 1.

Dichiarazione di stringa

La dichiarazione di una stringa è la stessa delle altre variabili -

type-specifier :: variable_name

Per esempio,

Character(len = 20) :: firstname, surname

puoi assegnare un valore come,

character (len = 40) :: name  
name = “Zara Ali”

L'esempio seguente dimostra la dichiarazione e l'uso del tipo di dati carattere -

program hello
implicit none

   character(len = 15) :: surname, firstname 
   character(len = 6) :: title 
   character(len = 25)::greetings
   
   title = 'Mr.' 
   firstname = 'Rowan' 
   surname = 'Atkinson'
   greetings = 'A big hello from Mr. Beans'
   
   print *, 'Here is', title, firstname, surname
   print *, greetings
   
end program hello

Quando compili ed esegui il programma sopra, produce il seguente risultato:

Here isMr.   Rowan          Atkinson       
A big hello from Mr. Bean

Concatenazione di stringhe

L'operatore di concatenazione //, concatena le stringhe.

Il seguente esempio lo dimostra:

program hello
implicit none

   character(len = 15) :: surname, firstname 
   character(len = 6) :: title 
   character(len = 40):: name
   character(len = 25)::greetings
   
   title = 'Mr.' 
   firstname = 'Rowan' 
   surname = 'Atkinson'
   
   name = title//firstname//surname
   greetings = 'A big hello from Mr. Beans'
   
   print *, 'Here is', name
   print *, greetings
   
end program hello

Quando compili ed esegui il programma sopra, produce il seguente risultato:

Here is Mr. Rowan Atkinson       
A big hello from Mr. Bean

Estrazione di sottostringhe

In Fortran, puoi estrarre una sottostringa da una stringa indicizzando la stringa, fornendo l'indice iniziale e finale della sottostringa tra parentesi. Questo è chiamato identificatore di estensione.

L'esempio seguente mostra come estrarre la sottostringa 'world' dalla stringa 'hello world' -

program subString

   character(len = 11)::hello
   hello = "Hello World"
   print*, hello(7:11)
   
end program subString

Quando compili ed esegui il programma sopra, produce il seguente risultato:

World

Esempio

L'esempio seguente utilizza l'estensione date_and_timefunzione per fornire la stringa di data e ora. Utilizziamo specificatori di estensione per estrarre separatamente le informazioni su anno, data, mese, ora, minuti e secondi.

program  datetime
implicit none

   character(len = 8) :: dateinfo ! ccyymmdd
   character(len = 4) :: year, month*2, day*2

   character(len = 10) :: timeinfo ! hhmmss.sss
   character(len = 2)  :: hour, minute, second*6

   call  date_and_time(dateinfo, timeinfo)

   !  let’s break dateinfo into year, month and day.
   !  dateinfo has a form of ccyymmdd, where cc = century, yy = year
   !  mm = month and dd = day

   year  = dateinfo(1:4)
   month = dateinfo(5:6)
   day   = dateinfo(7:8)

   print*, 'Date String:', dateinfo
   print*, 'Year:', year
   print *,'Month:', month
   print *,'Day:', day

   !  let’s break timeinfo into hour, minute and second.
   !  timeinfo has a form of hhmmss.sss, where h = hour, m = minute
   !  and s = second

   hour   = timeinfo(1:2)
   minute = timeinfo(3:4)
   second = timeinfo(5:10)

   print*, 'Time String:', timeinfo
   print*, 'Hour:', hour
   print*, 'Minute:', minute
   print*, 'Second:', second   
   
end program  datetime

Quando compili ed esegui il programma sopra, fornisce le informazioni dettagliate su data e ora -

Date String: 20140803
Year: 2014
Month: 08
Day: 03
Time String: 075835.466
Hour: 07
Minute: 58
Second: 35.466

Corde da taglio

Il trim la funzione accetta una stringa e restituisce la stringa di input dopo aver rimosso tutti gli spazi finali.

Esempio

program trimString
implicit none

   character (len = *), parameter :: fname="Susanne", sname="Rizwan"
   character (len = 20) :: fullname 
   
   fullname = fname//" "//sname !concatenating the strings
   
   print*,fullname,", the beautiful dancer from the east!"
   print*,trim(fullname),", the beautiful dancer from the east!"
   
end program trimString

Quando compili ed esegui il programma sopra, produce il seguente risultato:

Susanne Rizwan      , the beautiful dancer from the east!
 Susanne Rizwan, the beautiful dancer from the east!

Regolazione delle corde sinistra e destra

La funzione adjustl prende una stringa e la restituisce rimuovendo gli spazi iniziali e aggiungendoli come spazi finali.

La funzione adjustr prende una stringa e la restituisce rimuovendo gli spazi finali e aggiungendoli come spazi iniziali.

Esempio

program hello
implicit none

   character(len = 15) :: surname, firstname 
   character(len = 6) :: title 
   character(len = 40):: name
   character(len = 25):: greetings
   
   title = 'Mr. ' 
   firstname = 'Rowan' 
   surname = 'Atkinson'
   greetings = 'A big hello from Mr. Beans'
   
   name = adjustl(title)//adjustl(firstname)//adjustl(surname)
   print *, 'Here is', name
   print *, greetings
   
   name = adjustr(title)//adjustr(firstname)//adjustr(surname)
   print *, 'Here is', name
   print *, greetings
   
   name = trim(title)//trim(firstname)//trim(surname)
   print *, 'Here is', name
   print *, greetings
   
end program hello

Quando compili ed esegui il programma sopra, produce il seguente risultato:

Here is Mr. Rowan  Atkinson           
A big hello from Mr. Bean
Here is Mr. Rowan Atkinson    
A big hello from Mr. Bean
Here is Mr.RowanAtkinson                        
A big hello from Mr. Bean

Ricerca di una sottostringa in una stringa

La funzione index accetta due stringhe e controlla se la seconda stringa è una sottostringa della prima stringa. Se il secondo argomento è una sottostringa del primo argomento, restituisce un numero intero che è l'indice iniziale della seconda stringa nella prima stringa, altrimenti restituisce zero.

Esempio

program hello
implicit none

   character(len=30) :: myString
   character(len=10) :: testString
   
   myString = 'This is a test'
   testString = 'test'
   
   if(index(myString, testString) == 0)then
      print *, 'test is not found'
   else
      print *, 'test is found at index: ', index(myString, testString)
   end if
   
end program hello

Quando compili ed esegui il programma sopra, produce il seguente risultato:

test is found at index: 11

Gli array possono memorizzare una raccolta sequenziale di dimensioni fisse di elementi dello stesso tipo. Un array viene utilizzato per memorizzare una raccolta di dati, ma spesso è più utile pensare a un array come una raccolta di variabili dello stesso tipo.

Tutti gli array sono costituiti da posizioni di memoria contigue. L'indirizzo più basso corrisponde al primo elemento e l'indirizzo più alto all'ultimo elemento.

Numeri (1) Numeri (2) Numeri (3) Numeri (4) ...

Gli array possono essere unidimensionali (come i vettori), bidimensionali (come le matrici) e Fortran consente di creare array fino a 7 dimensioni.

Dichiarazione di array

Gli array vengono dichiarati con l'estensione dimension attributo.

Ad esempio, per dichiarare una matrice unidimensionale denominata numero, di numeri reali contenenti 5 elementi, scrivi,

real, dimension(5) :: numbers

Si fa riferimento ai singoli elementi degli array specificandone i pedici. Il primo elemento di un array ha un pedice di uno. La serie di numeri contiene cinque variabili reali: numeri (1), numeri (2), numeri (3), numeri (4) e numeri (5).

Per creare una matrice bidimensionale di numeri interi 5 x 5 denominata matrice, scrivi:

integer, dimension (5,5) :: matrix

Puoi anche dichiarare un array con un limite inferiore esplicito, ad esempio:

real, dimension(2:6) :: numbers
integer, dimension (-3:2,0:4) :: matrix

Assegnazione di valori

Puoi assegnare valori a singoli membri, come,

numbers(1) = 2.0

oppure puoi usare un loop,

do i  =1,5
   numbers(i) = i * 2.0
end do

Agli elementi di array unidimensionali possono essere assegnati direttamente valori utilizzando un simbolo a mano breve, chiamato costruttore di array, come

numbers = (/1.5, 3.2,4.5,0.9,7.2 /)

please note that there are no spaces allowed between the brackets ‘( ‘and the back slash ‘/’

Esempio

L'esempio seguente mostra i concetti discussi sopra.

program arrayProg

   real :: numbers(5) !one dimensional integer array
   integer :: matrix(3,3), i , j !two dimensional real array
   
   !assigning some values to the array numbers
   do i=1,5
      numbers(i) = i * 2.0
   end do
   
   !display the values
   do i = 1, 5
      Print *, numbers(i)
   end do
   
   !assigning some values to the array matrix
   do i=1,3
      do j = 1, 3
         matrix(i, j) = i+j
      end do
   end do
   
   !display the values
   do i=1,3
      do j = 1, 3
         Print *, matrix(i,j)
      end do
   end do
   
   !short hand assignment
   numbers = (/1.5, 3.2,4.5,0.9,7.2 /)
   
   !display the values
   do i = 1, 5
      Print *, numbers(i)
   end do
   
end program arrayProg

Quando il codice precedente viene compilato ed eseguito, produce il seguente risultato:

2.00000000    
 4.00000000    
 6.00000000    
 8.00000000    
 10.0000000    
         2
         3
         4
         3
         4
         5
         4
         5
         6
 1.50000000    
 3.20000005    
 4.50000000    
0.899999976    
 7.19999981

Alcuni termini correlati agli array

La tabella seguente fornisce alcuni termini relativi agli array:

Termine Senso
Rango È il numero di dimensioni di un array. Ad esempio, per la matrice denominata matrice, il rango è 2 e per la matrice denominata numeri, il rango è 1.
Estensione È il numero di elementi lungo una dimensione. Ad esempio, i numeri della matrice hanno estensione 5 e la matrice denominata matrice ha estensione 3 in entrambe le dimensioni.
Forma La forma di una matrice è una matrice intera unidimensionale, contenente il numero di elementi (l'estensione) in ciascuna dimensione. Ad esempio, per la matrice dell'array, la forma è (3, 3) e i numeri dell'array è (5).
Taglia È il numero di elementi contenuti in un array. Per la matrice di array, è 9 e per i numeri di array è 5.

Passaggio di array alle procedure

È possibile passare un array a una procedura come argomento. Il seguente esempio dimostra il concetto:

program arrayToProcedure      
implicit none      

   integer, dimension (5) :: myArray  
   integer :: i
   
   call fillArray (myArray)      
   call printArray(myArray)
   
end program arrayToProcedure


subroutine fillArray (a)      
implicit none      

   integer, dimension (5), intent (out) :: a
   
   ! local variables     
   integer :: i     
   do i = 1, 5         
      a(i) = i      
   end do  
   
end subroutine fillArray 


subroutine printArray(a)

   integer, dimension (5) :: a  
   integer::i
   
   do i = 1, 5
      Print *, a(i)
   end do
   
end subroutine printArray

Quando il codice precedente viene compilato ed eseguito, produce il seguente risultato:

1
2
3
4
5

Nell'esempio precedente, le subroutine fillArray e printArray possono essere chiamate solo con array con dimensione 5. Tuttavia, per scrivere subroutine che possono essere utilizzate per array di qualsiasi dimensione, è possibile riscriverle utilizzando la seguente tecnica:

program arrayToProcedure      
implicit  none    

   integer, dimension (10) :: myArray  
   integer :: i
   
   interface 
      subroutine fillArray (a)
         integer, dimension(:), intent (out) :: a 
         integer :: i         
      end subroutine fillArray      

      subroutine printArray (a)
         integer, dimension(:) :: a 
         integer :: i         
      end subroutine printArray   
   end interface 
   
   call fillArray (myArray)      
   call printArray(myArray)
   
end program arrayToProcedure


subroutine fillArray (a)      
implicit none      
   integer,dimension (:), intent (out) :: a      
   
   ! local variables     
   integer :: i, arraySize  
   arraySize = size(a)
   
   do i = 1, arraySize         
      a(i) = i      
   end do  
   
end subroutine fillArray 


subroutine printArray(a)
implicit none

   integer,dimension (:) :: a  
   integer::i, arraySize
   arraySize = size(a)
   
   do i = 1, arraySize
     Print *, a(i)
   end do
   
end subroutine printArray

Tieni presente che il programma utilizza l'estensione size funzione per ottenere la dimensione dell'array.

Quando il codice precedente viene compilato ed eseguito, produce il seguente risultato:

1
2
3
4
5
6
7
8
9
10

Sezioni array

Finora ci siamo riferiti all'intero array, Fortran fornisce un modo semplice per fare riferimento a diversi elementi, o una sezione di un array, usando una singola istruzione.

Per accedere a una sezione della matrice, è necessario fornire il limite inferiore e superiore della sezione, nonché un passo (incremento), per tutte le dimensioni. Questa notazione è chiamata asubscript triplet:

array ([lower]:[upper][:stride], ...)

Quando non vengono menzionati limiti inferiore e superiore, il valore predefinito è le estensioni dichiarate e il valore di stride predefinito è 1.

Il seguente esempio dimostra il concetto:

program arraySubsection

   real, dimension(10) :: a, b
   integer:: i, asize, bsize
   
   a(1:7) = 5.0 ! a(1) to a(7) assigned 5.0
   a(8:) = 0.0  ! rest are 0.0 
   b(2:10:2) = 3.9
   b(1:9:2) = 2.5
   
   !display
   asize = size(a)
   bsize = size(b)
   
   do i = 1, asize
      Print *, a(i)
   end do
   
   do i = 1, bsize
      Print *, b(i)
   end do
   
end program arraySubsection

Quando il codice precedente viene compilato ed eseguito, produce il seguente risultato:

5.00000000    
5.00000000    
5.00000000    
5.00000000    
5.00000000    
5.00000000    
5.00000000    
0.00000000E+00
0.00000000E+00
0.00000000E+00
2.50000000    
3.90000010    
2.50000000    
3.90000010    
2.50000000    
3.90000010    
2.50000000    
3.90000010    
2.50000000    
3.90000010

Funzioni intrinseche degli array

Fortran 90/95 fornisce diverse procedure intrinseche. Possono essere suddivisi in 7 categorie.

  • Moltiplicazione di vettori e matrici

  • Reduction

  • Inquiry

  • Construction

  • Reshape

  • Manipulation

  • Location

UN dynamic array è un array, la cui dimensione non è nota in fase di compilazione, ma sarà nota in fase di esecuzione.

Gli array dinamici vengono dichiarati con l'attributo allocatable.

Per esempio,

real, dimension (:,:), allocatable :: darray

Il rango dell'array, cioè le dimensioni deve essere menzionato tuttavia, per allocare memoria a tale array, si utilizza il allocate funzione.

allocate ( darray(s1,s2) )

Dopo aver utilizzato l'array, nel programma, la memoria creata dovrebbe essere liberata utilizzando l'estensione deallocate funzione

deallocate (darray)

Esempio

L'esempio seguente mostra i concetti discussi sopra.

program dynamic_array 
implicit none 

   !rank is 2, but size not known   
   real, dimension (:,:), allocatable :: darray    
   integer :: s1, s2     
   integer :: i, j     
   
   print*, "Enter the size of the array:"     
   read*, s1, s2      
   
   ! allocate memory      
   allocate ( darray(s1,s2) )      
   
   do i = 1, s1           
      do j = 1, s2                
         darray(i,j) = i*j               
         print*, "darray(",i,",",j,") = ", darray(i,j)           
      end do      
   end do      
   
   deallocate (darray)  
end program dynamic_array

Quando il codice precedente viene compilato ed eseguito, produce il seguente risultato:

Enter the size of the array: 3,4
darray( 1 , 1 ) = 1.00000000    
darray( 1 , 2 ) = 2.00000000    
darray( 1 , 3 ) = 3.00000000    
darray( 1 , 4 ) = 4.00000000    
darray( 2 , 1 ) = 2.00000000    
darray( 2 , 2 ) = 4.00000000    
darray( 2 , 3 ) = 6.00000000    
darray( 2 , 4 ) = 8.00000000    
darray( 3 , 1 ) = 3.00000000    
darray( 3 , 2 ) = 6.00000000    
darray( 3 , 3 ) = 9.00000000    
darray( 3 , 4 ) = 12.0000000

Dichiarazione sull'uso dei dati

Il data può essere usata per inizializzare più di un array o per inizializzare la sezione dell'array.

La sintassi della dichiarazione dei dati è:

data variable / list / ...

Esempio

Il seguente esempio dimostra il concetto:

program dataStatement
implicit none

   integer :: a(5), b(3,3), c(10),i, j
   data a /7,8,9,10,11/ 
   
   data b(1,:) /1,1,1/ 
   data b(2,:)/2,2,2/ 
   data b(3,:)/3,3,3/ 
   data (c(i),i = 1,10,2) /4,5,6,7,8/ 
   data (c(i),i = 2,10,2)/5*2/
   
   Print *, 'The A array:'
   do j = 1, 5                
      print*, a(j)           
   end do 
   
   Print *, 'The B array:'
   do i = lbound(b,1), ubound(b,1)
      write(*,*) (b(i,j), j = lbound(b,2), ubound(b,2))
   end do

   Print *, 'The C array:' 
   do j = 1, 10                
      print*, c(j)           
   end do      
   
end program dataStatement

Quando il codice precedente viene compilato ed eseguito, produce il seguente risultato:

The A array:
           7
           8
           9
          10
          11
 The B array:
           1           1           1
           2           2           2
           3           3           3
 The C array:
           4
           2
           5
           2
           6
           2
           7
           2
           8
           2

Uso dell'istruzione Where

Il whereL'istruzione consente di utilizzare alcuni elementi di un array in un'espressione, a seconda del risultato di una condizione logica. Consente l'esecuzione dell'espressione, su un elemento, se la condizione data è vera.

Esempio

Il seguente esempio dimostra il concetto:

program whereStatement
implicit none

   integer :: a(3,5), i , j
   
   do i = 1,3
      do j = 1, 5                
         a(i,j) = j-i          
      end do 
   end do
   
   Print *, 'The A array:'
   
   do i = lbound(a,1), ubound(a,1)
      write(*,*) (a(i,j), j = lbound(a,2), ubound(a,2))
   end do
   
   where( a<0 ) 
      a = 1 
   elsewhere
      a = 5
   end where
  
   Print *, 'The A array:'
   do i = lbound(a,1), ubound(a,1)
      write(*,*) (a(i,j), j = lbound(a,2), ubound(a,2))
   end do   
   
end program whereStatement

Quando il codice precedente viene compilato ed eseguito, produce il seguente risultato:

The A array:
           0           1           2           3           4
          -1           0           1           2           3
          -2          -1           0           1           2
 The A array:
           5           5           5           5           5
           1           5           5           5           5
           1           1           5           5           5

Fortran consente di definire i tipi di dati derivati. Un tipo di dati derivato è anche chiamato struttura e può essere costituito da oggetti dati di diversi tipi.

I tipi di dati derivati ​​vengono utilizzati per rappresentare un record. Ad esempio, se desideri tenere traccia dei tuoi libri in una biblioteca, potresti voler tenere traccia dei seguenti attributi di ogni libro:

  • Title
  • Author
  • Subject
  • ID libro

Definizione di un tipo di dati derivato

Per definire un dato derivato type, il tipo e end typevengono utilizzate le istruzioni. . L'istruzione type definisce un nuovo tipo di dati, con più di un membro per il programma. Il formato dell'istruzione del tipo è questo:

type type_name      
   declarations
end type

Ecco il modo in cui dichiareresti la struttura del libro:

type Books
   character(len = 50) :: title
   character(len = 50) :: author
   character(len = 150) :: subject
   integer :: book_id
end type Books

Accesso ai membri della struttura

Un oggetto di un tipo di dati derivato è chiamato struttura.

Una struttura di tipo Libri può essere creata in un'istruzione di dichiarazione del tipo come:

type(Books) :: book1

È possibile accedere ai componenti della struttura utilizzando il carattere di selezione dei componenti (%) -

book1%title = "C Programming"
book1%author = "Nuha Ali"
book1%subject = "C Programming Tutorial"
book1%book_id = 6495407

Note that there are no spaces before and after the % symbol.

Esempio

Il seguente programma illustra i concetti di cui sopra:

program deriveDataType

   !type declaration
   type Books
      character(len = 50) :: title
      character(len = 50) :: author
      character(len = 150) :: subject
      integer :: book_id
   end type Books
   
   !declaring type variables
   type(Books) :: book1 
   type(Books) :: book2 
   
   !accessing the components of the structure
   
   book1%title = "C Programming"
   book1%author = "Nuha Ali"
   book1%subject = "C Programming Tutorial"
   book1%book_id = 6495407 
   
   book2%title = "Telecom Billing"
   book2%author = "Zara Ali"
   book2%subject = "Telecom Billing Tutorial"
   book2%book_id = 6495700
  
   !display book info
   
   Print *, book1%title 
   Print *, book1%author 
   Print *, book1%subject 
   Print *, book1%book_id  
   
   Print *, book2%title 
   Print *, book2%author 
   Print *, book2%subject 
   Print *, book2%book_id  

end program deriveDataType

Quando il codice precedente viene compilato ed eseguito, produce il seguente risultato:

C Programming                                     
 Nuha Ali                                          
 C Programming Tutorial            
   6495407
 Telecom Billing                                   
 Zara Ali                                          
 Telecom Billing Tutorial            
   6495700

Matrice di strutture

Puoi anche creare array di un tipo derivato -

type(Books), dimension(2) :: list

È possibile accedere ai singoli elementi dell'array come:

list(1)%title = "C Programming"
list(1)%author = "Nuha Ali"
list(1)%subject = "C Programming Tutorial"
list(1)%book_id = 6495407

Il seguente programma illustra il concetto:

program deriveDataType

   !type declaration
   type Books
      character(len = 50) :: title
      character(len = 50) :: author
      character(len = 150) :: subject
      integer :: book_id
   end type Books
   
   !declaring array of books
   type(Books), dimension(2) :: list 
    
   !accessing the components of the structure
   
   list(1)%title = "C Programming"
   list(1)%author = "Nuha Ali"
   list(1)%subject = "C Programming Tutorial"
   list(1)%book_id = 6495407 
   
   list(2)%title = "Telecom Billing"
   list(2)%author = "Zara Ali"
   list(2)%subject = "Telecom Billing Tutorial"
   list(2)%book_id = 6495700
  
   !display book info
   
   Print *, list(1)%title 
   Print *, list(1)%author 
   Print *, list(1)%subject 
   Print *, list(1)%book_id  
   
   Print *, list(1)%title 
   Print *, list(2)%author 
   Print *, list(2)%subject 
   Print *, list(2)%book_id  

end program deriveDataType

Quando il codice precedente viene compilato ed eseguito, produce il seguente risultato:

C Programming                                     
Nuha Ali                                          
C Programming Tutorial               
   6495407
C Programming                                     
Zara Ali                                          
Telecom Billing Tutorial                                      
   6495700

Nella maggior parte dei linguaggi di programmazione, una variabile puntatore memorizza l'indirizzo di memoria di un oggetto. Tuttavia, in Fortran, un puntatore è un oggetto dati che ha più funzionalità rispetto alla semplice memorizzazione dell'indirizzo di memoria. Contiene più informazioni su un particolare oggetto, come tipo, rango, estensioni e indirizzo di memoria.

Un puntatore è associato a un obiettivo tramite allocazione o assegnazione del puntatore.

Dichiarazione di una variabile puntatore

Una variabile pointer viene dichiarata con l'attributo pointer.

I seguenti esempi mostrano la dichiarazione di variabili puntatore:

integer, pointer :: p1 ! pointer to integer  
real, pointer, dimension (:) :: pra ! pointer to 1-dim real array  
real, pointer, dimension (:,:) :: pra2 ! pointer to 2-dim real array

Un puntatore può puntare a -

  • Un'area di memoria allocata dinamicamente.

  • Un oggetto dati dello stesso tipo del puntatore, con l'estensione target attributo.

Allocare spazio per un puntatore

Il allocateL'istruzione consente di allocare spazio per un oggetto puntatore. Ad esempio:

program pointerExample
implicit none

   integer, pointer :: p1
   allocate(p1)
   
   p1 = 1
   Print *, p1
   
   p1 = p1 + 4
   Print *, p1
   
end program pointerExample

Quando il codice precedente viene compilato ed eseguito, produce il seguente risultato:

1
5

È necessario svuotare lo spazio di archiviazione allocato da deallocate istruzione quando non è più necessaria ed evitare l'accumulo di spazio di memoria inutilizzato e inutilizzabile.

Obiettivi e associazione

Un obiettivo è un'altra variabile normale, con spazio riservato per esso. Una variabile di destinazione deve essere dichiarata contarget attributo.

Associare una variabile puntatore a una variabile di destinazione utilizzando l'operatore di associazione (=>).

Riscriviamo l'esempio precedente, per dimostrare il concetto:

program pointerExample
implicit none

   integer, pointer :: p1
   integer, target :: t1 
   
   p1=>t1
   p1 = 1
   
   Print *, p1
   Print *, t1
   
   p1 = p1 + 4
   
   Print *, p1
   Print *, t1
   
   t1 = 8
   
   Print *, p1
   Print *, t1
   
end program pointerExample

Quando il codice precedente viene compilato ed eseguito, produce il seguente risultato:

1
1
5
5
8
8

Un puntatore può essere -

  • Undefined
  • Associated
  • Disassociated

Nel programma sopra, abbiamo associatedil puntatore p1, con il target t1, utilizzando l'operatore =>. La funzione associata verifica lo stato di associazione di un puntatore.

Il nullify istruzione dissocia un puntatore da un obiettivo.

Nullify non svuota i bersagli in quanto potrebbe esserci più di un puntatore che punta allo stesso bersaglio. Tuttavia, lo svuotamento del puntatore implica anche l'annullamento.

Esempio 1

Il seguente esempio dimostra i concetti:

program pointerExample
implicit none

   integer, pointer :: p1
   integer, target :: t1 
   integer, target :: t2
   
   p1=>t1
   p1 = 1
   
   Print *, p1
   Print *, t1
   
   p1 = p1 + 4
   Print *, p1
   Print *, t1
   
   t1 = 8
   Print *, p1
   Print *, t1
   
   nullify(p1)
   Print *, t1
   
   p1=>t2
   Print *, associated(p1)
   Print*, associated(p1, t1)
   Print*, associated(p1, t2)
   
   !what is the value of p1 at present
   Print *, p1
   Print *, t2
   
   p1 = 10
   Print *, p1
   Print *, t2
   
end program pointerExample

Quando il codice precedente viene compilato ed eseguito, produce il seguente risultato:

1
1
5
5
8
8
8
T
F
T
952754640
952754640
10
10

Tieni presente che ogni volta che esegui il codice, gli indirizzi di memoria saranno diversi.

Esempio 2

program pointerExample
implicit none

   integer, pointer :: a, b
   integer, target :: t
   integer :: n
   
   t = 1
   a => t
   t = 2
   b => t
   n = a + b
   
   Print *, a, b, t, n 
   
end program pointerExample

Quando il codice precedente viene compilato ed eseguito, produce il seguente risultato:

2  2  2  4

Finora abbiamo visto che possiamo leggere i dati dalla tastiera usando il read * e visualizzare l'output sullo schermo utilizzando il print*dichiarazione, rispettivamente. Questa forma di input-output èfree format I / O, e si chiama list-directed input Output.

L'I / O semplice in formato libero ha la forma:

read(*,*) item1, item2, item3...
print *, item1, item2, item3
write(*,*) item1, item2, item3...

Tuttavia, l'I / O formattato offre maggiore flessibilità sul trasferimento dei dati.

Input output formattato

L'output di input formattato ha la sintassi come segue:

read fmt, variable_list 
print fmt, variable_list 
write fmt, variable_list

Dove,

  • fmt è la specifica del formato

  • lista-variabili è una lista delle variabili da leggere da tastiera o da scrivere sullo schermo

La specifica del formato definisce il modo in cui vengono visualizzati i dati formattati. Consiste in una stringa, contenente un elenco di fileedit descriptors tra parentesi.

Un edit descriptor specifica il formato esatto, ad esempio larghezza, cifre dopo il punto decimale ecc., in cui vengono visualizzati caratteri e numeri.

Per esempio

Print "(f6.3)", pi

La tabella seguente descrive i descrittori:

Descrittore Descrizione Esempio
io

Viene utilizzato per l'output di numeri interi. Questo assume la forma 'rIw.m' dove i significati di r, w e m sono riportati nella tabella sottostante. I valori interi sono giusti fi cati correttamente nei loro campi. Se la larghezza del campo non è abbastanza grande da contenere un numero intero, il campo viene riempito con asterischi.

print "(3i5)", i, j, k
F

Viene utilizzato per l'output di numeri reali. Questo assume la forma "rFw.d" dove i significati di r, wed sono riportati nella tabella sottostante. I valori reali sono giustamente giustificati nei loro campi. Se la larghezza del campo non è abbastanza grande da contenere il numero reale, il campo viene riempito con asterischi.

print "(f12.3)", pi
E

Viene utilizzato per l'output reale in notazione esponenziale. L'istruzione descrittiva "E" assume la forma "rEw.d" dove i significati di r, wed sono forniti nella tabella sottostante. I valori reali sono giustamente giustificati nei loro campi. Se la larghezza del campo non è abbastanza grande da contenere il numero reale, il campo viene riempito con asterischi.

Si noti che, per stampare un numero reale con tre cifre decimali, è necessaria una larghezza di campo di almeno dieci. Uno per il segno della mantissa, due per lo zero, quattro per la mantissa e due per l'esponente stesso. In generale, w ≥ d + 7.

print "(e10.3)", 123456.0 restituisce '0.123e + 06'
ES

Viene utilizzato per l'output reale (notazione scientifica). Questo assume la forma "rESw.d" dove i significati di r, w e d sono riportati nella tabella sottostante. Il descrittore "E" sopra descritto differisce leggermente dalla ben nota "notazione scientifica" tradizionale. La notazione scientifica ha la mantissa nell'intervallo da 1.0 a 10.0 a differenza del descrittore E che ha la mantissa nell'intervallo da 0.1 a 1.0. I valori reali sono giustamente giustificati nei loro campi. Se la larghezza del campo non è abbastanza grande da contenere il numero reale, il campo viene riempito con asterischi. Anche qui, il campo della larghezza deve soddisfare l'espressione w ≥ d + 7

print "(es10.3)", 123456.0 restituisce "1.235e + 05"
UN

Viene utilizzato per l'output dei caratteri. Questo assume la forma "rAw" dove i significati di r e w sono riportati nella tabella sottostante. I tipi di carattere sono giustamente giustificati nei loro campi. Se la larghezza del campo non è abbastanza grande da contenere la stringa di caratteri, il campo viene riempito con i primi caratteri "w" della stringa.

print "(a10)", str
X

Viene utilizzato per l'output di spazio. Questo assume la forma "nX" dove "n" è il numero di spazi desiderati.

print "(5x, a10)", str
/

Descrittore barra: utilizzato per inserire righe vuote. Questo assume la forma "/" e forza il successivo output di dati su una nuova riga.

print "(/, 5x, a10)", str

I seguenti simboli vengono utilizzati con i descrittori di formato:

Suor n Simbolo e descrizione
1

c

Numero di colonna

2

d

Numero di cifre a destra della cifra decimale per input o output reali

3

m

Numero minimo di cifre da visualizzare

4

n

Numero di spazi da saltare

5

r

Conteggio ripetizioni: il numero di volte in cui utilizzare un descrittore o un gruppo di descrittori

6

w

Larghezza campo: il numero di caratteri da utilizzare per l'input o l'output

Esempio 1

program printPi

   pi = 3.141592653589793238 
   
   Print "(f6.3)", pi 
   Print "(f10.7)", pi
   Print "(f20.15)", pi 
   Print "(e16.4)", pi/100 
   
end program printPi

Quando il codice precedente viene compilato ed eseguito, produce il seguente risultato:

3.142
3.1415927
3.141592741012573
0.3142E-01

Esempio 2

program printName
implicit none

   character (len = 15) :: first_name
   print *,' Enter your first name.' 
   print *,' Up to 20 characters, please'
   
   read *,first_name 
   print "(1x,a)",first_name
   
end program printName

Quando il codice precedente viene compilato ed eseguito, produce il seguente risultato: (supponiamo che l'utente inserisca il nome Zara)

Enter your first name.
Up to 20 characters, please
Zara

Esempio 3

program formattedPrint
implicit none

   real :: c = 1.2786456e-9, d = 0.1234567e3 
   integer :: n = 300789, k = 45, i = 2
   character (len=15) :: str="Tutorials Point"
   
   print "(i6)", k 
   print "(i6.3)", k 
   print "(3i10)", n, k, i 
   print "(i10,i3,i5)", n, k, i 
   print "(a15)",str 
   print "(f12.3)", d
   print "(e12.4)", c 
   print '(/,3x,"n = ",i6, 3x, "d = ",f7.4)', n, d
   
end program formattedPrint

Quando il codice precedente viene compilato ed eseguito, produce il seguente risultato:

45
045
300789 45  2
300789 45  2
Tutorials Point
123.457
0.1279E-08

n = 300789 d = *******

La dichiarazione di formato

L'istruzione format consente di combinare e abbinare caratteri, numeri interi e output reali in un'unica istruzione. Il seguente esempio lo dimostra:

program productDetails 
implicit none 

   character (len = 15) :: name
   integer :: id 
   real :: weight
   name = 'Ardupilot'
   id = 1
   weight = 0.08
   
   print *,' The product details are' 
   
   print 100
   100 format (7x,'Name:', 7x, 'Id:', 1x, 'Weight:')
   
   print 200, name, id, weight 
   200 format(1x, a, 2x, i3, 2x, f5.2) 
   
end program productDetails

Quando il codice precedente viene compilato ed eseguito, produce il seguente risultato:

The product details are
Name:       Id:    Weight:
Ardupilot   1       0.08

Fortran ti consente di leggere dati da e scrivere dati in file.

Nell'ultimo capitolo hai visto come leggere e scrivere dati sul terminale. In questo capitolo si studieranno le funzionalità di input e output di file fornite da Fortran.

Puoi leggere e scrivere su uno o più file. Le istruzioni OPEN, WRITE, READ e CLOSE consentono di ottenere questo risultato.

Apertura e chiusura di file

Prima di utilizzare un file è necessario aprire il file. Ilopencomando viene utilizzato per aprire i file per la lettura o la scrittura. La forma più semplice del comando è:

open (unit = number, file = "name").

Tuttavia, la dichiarazione aperta può avere una forma generale:

open (list-of-specifiers)

La tabella seguente descrive gli specificatori più comunemente usati:

Suor n Specifier e descrizione
1

[UNIT=] u

Il numero di unità u potrebbe essere qualsiasi numero compreso tra 9 e 99 e indica il file, puoi scegliere qualsiasi numero ma ogni file aperto nel programma deve avere un numero univoco

2

IOSTAT= ios

È l'identificatore di stato dell'I / O e dovrebbe essere una variabile intera. Se l'istruzione open ha esito positivo, il valore ios restituito è zero altrimenti un valore diverso da zero.

3

ERR = err

È un'etichetta alla quale il controllo salta in caso di errore.

4

FILE = fname

Nome del file, una stringa di caratteri.

5

STATUS = sta

Mostra lo stato precedente del file. Una stringa di caratteri e può avere uno dei tre valori NEW, OLD o SCRATCH. Un file di lavoro viene creato ed eliminato quando viene chiuso o il programma termina.

6

ACCESS = acc

È la modalità di accesso ai file. Può avere uno dei due valori, SEQUENZIALE o DIRETTO. L'impostazione predefinita è SEQUENZIALE.

7

FORM = frm

Fornisce lo stato di formattazione del file. Può avere uno dei due valori FORMATTED o UNFORMATTED. L'impostazione predefinita è UNFORMATTED

8

RECL = rl

Specifica la lunghezza di ogni record in un file ad accesso diretto.

Dopo che il file è stato aperto, vi si accede tramite istruzioni di lettura e scrittura. Una volta fatto, dovrebbe essere chiuso utilizzando il fileclose dichiarazione.

L'istruzione close ha la seguente sintassi:

close ([UNIT = ]u[,IOSTAT = ios,ERR = err,STATUS = sta])

Si noti che i parametri tra parentesi sono facoltativi.

Example

Questo esempio mostra l'apertura di un nuovo file per scrivere alcuni dati nel file.

program outputdata   
implicit none

   real, dimension(100) :: x, y  
   real, dimension(100) :: p, q
   integer :: i  
   
   ! data  
   do i=1,100  
      x(i) = i * 0.1 
      y(i) = sin(x(i)) * (1-cos(x(i)/3.0))  
   end do  
   
   ! output data into a file 
   open(1, file = 'data1.dat', status = 'new')  
   do i=1,100  
      write(1,*) x(i), y(i)   
   end do  
   
   close(1) 
   
end program outputdata

Quando il codice precedente viene compilato ed eseguito, crea il file data1.dat e vi scrive i valori degli array xey. E poi chiude il file.

Lettura da e scrittura nel file

Le istruzioni di lettura e scrittura vengono usate rispettivamente per leggere e scrivere in un file.

Hanno la seguente sintassi:

read ([UNIT = ]u, [FMT = ]fmt, IOSTAT = ios, ERR = err, END = s)
write([UNIT = ]u, [FMT = ]fmt, IOSTAT = ios, ERR = err, END = s)

La maggior parte degli specificatori è già stata discussa nella tabella precedente.

Lo specificatore END = s è un'etichetta di istruzione in cui il programma salta, quando raggiunge la fine del file.

Example

Questo esempio dimostra la lettura e la scrittura in un file.

In questo programma leggiamo dal file, che abbiamo creato nell'ultimo esempio, data1.dat, e lo visualizziamo sullo schermo.

program outputdata   
implicit none   

   real, dimension(100) :: x, y  
   real, dimension(100) :: p, q
   integer :: i  
   
   ! data  
   do i = 1,100  
      x(i) = i * 0.1 
      y(i) = sin(x(i)) * (1-cos(x(i)/3.0))  
   end do  
   
   ! output data into a file 
   open(1, file = 'data1.dat', status='new')  
   do i = 1,100  
      write(1,*) x(i), y(i)   
   end do  
   close(1) 

   ! opening the file for reading
   open (2, file = 'data1.dat', status = 'old')

   do i = 1,100  
      read(2,*) p(i), q(i)
   end do 
   
   close(2)
   
   do i = 1,100  
      write(*,*) p(i), q(i)
   end do 
   
end program outputdata

Quando il codice precedente viene compilato ed eseguito, produce il seguente risultato:

0.100000001  5.54589933E-05
0.200000003  4.41325130E-04
0.300000012  1.47636665E-03
0.400000006  3.45637114E-03
0.500000000  6.64328877E-03
0.600000024  1.12552457E-02
0.699999988  1.74576249E-02
0.800000012  2.53552198E-02
0.900000036  3.49861123E-02
1.00000000   4.63171229E-02
1.10000002   5.92407547E-02
1.20000005   7.35742599E-02
1.30000007   8.90605897E-02
1.39999998   0.105371222    
1.50000000   0.122110792    
1.60000002   0.138823599    
1.70000005   0.155002072    
1.80000007   0.170096487    
1.89999998   0.183526158    
2.00000000   0.194692180    
2.10000014   0.202990443    
2.20000005   0.207826138    
2.29999995   0.208628103    
2.40000010   0.204863414    
2.50000000   0.196052119    
2.60000014   0.181780845    
2.70000005   0.161716297    
2.79999995   0.135617107    
2.90000010   0.103344671    
3.00000000   6.48725405E-02
3.10000014   2.02930309E-02
3.20000005  -3.01767997E-02
3.29999995  -8.61928314E-02
3.40000010  -0.147283033    
3.50000000  -0.212848678    
3.60000014  -0.282169819    
3.70000005  -0.354410470    
3.79999995  -0.428629100    
3.90000010  -0.503789663    
4.00000000  -0.578774154    
4.09999990  -0.652400017    
4.20000029  -0.723436713    
4.30000019  -0.790623367    
4.40000010  -0.852691114    
4.50000000  -0.908382416    
4.59999990  -0.956472993    
4.70000029  -0.995793998    
4.80000019  -1.02525222    
4.90000010  -1.04385209    
5.00000000  -1.05071592    
5.09999990  -1.04510069    
5.20000029  -1.02641726    
5.30000019  -0.994243503    
5.40000010  -0.948338211    
5.50000000  -0.888650239    
5.59999990  -0.815326691    
5.70000029  -0.728716135    
5.80000019  -0.629372001    
5.90000010  -0.518047631    
6.00000000  -0.395693362    
6.09999990  -0.263447165    
6.20000029  -0.122622721    
6.30000019   2.53026206E-02
6.40000010   0.178709000    
6.50000000   0.335851669    
6.59999990   0.494883657    
6.70000029   0.653881252    
6.80000019   0.810866773    
6.90000010   0.963840425    
7.00000000   1.11080539    
7.09999990   1.24979746    
7.20000029   1.37891412    
7.30000019   1.49633956    
7.40000010   1.60037732    
7.50000000   1.68947268    
7.59999990   1.76223695    
7.70000029   1.81747139    
7.80000019   1.85418403    
7.90000010   1.87160957    
8.00000000   1.86922085    
8.10000038   1.84674001    
8.19999981   1.80414569    
8.30000019   1.74167395    
8.40000057   1.65982044    
8.50000000   1.55933595    
8.60000038   1.44121361    
8.69999981   1.30668485    
8.80000019   1.15719533    
8.90000057   0.994394958    
9.00000000   0.820112705    
9.10000038   0.636327863    
9.19999981   0.445154816    
9.30000019   0.248800844    
9.40000057   4.95488606E-02
9.50000000  -0.150278628    
9.60000038  -0.348357052    
9.69999981  -0.542378068    
9.80000019  -0.730095863    
9.90000057  -0.909344316    
10.0000000  -1.07807255

UN procedureè un gruppo di istruzioni che eseguono un'attività ben definita e possono essere richiamate dal programma. Le informazioni (o dati) vengono passate al programma chiamante, alla procedura come argomenti.

Esistono due tipi di procedure:

  • Functions
  • Subroutines

Funzione

Una funzione è una procedura che restituisce una singola quantità. Una funzione non dovrebbe modificare i suoi argomenti.

La quantità restituita è nota come function value, ed è indicato dal nome della funzione.

Syntax

La sintassi di una funzione è la seguente:

function name(arg1, arg2, ....)  
   [declarations, including those for the arguments]   
   [executable statements] 
end function [name]

L'esempio seguente mostra una funzione denominata area_of_circle. Calcola l'area di un cerchio con raggio r.

program calling_func

   real :: a
   a = area_of_circle(2.0) 
   
   Print *, "The area of a circle with radius 2.0 is"
   Print *, a
   
end program calling_func


! this function computes the area of a circle with radius r  
function area_of_circle (r)  

! function result     
implicit none      

   ! dummy arguments        
   real :: area_of_circle   
   
   ! local variables 
   real :: r     
   real :: pi
   
   pi = 4 * atan (1.0)     
   area_of_circle = pi * r**2  
   
end function area_of_circle

Quando compili ed esegui il programma sopra, produce il seguente risultato:

The area of a circle with radius 2.0 is
   12.5663710

Si prega di notare che -

  • Devi specificare implicit none sia nel programma principale che nella procedura.

  • Viene chiamato l'argomento r nella funzione chiamata dummy argument.

L'opzione risultato

Se si desidera che il valore restituito venga memorizzato con un nome diverso dal nome della funzione, è possibile utilizzare l'estensione result opzione.

È possibile specificare il nome della variabile di ritorno come -

function name(arg1, arg2, ....) result (return_var_name)  
   [declarations, including those for the arguments]   
   [executable statements] 
end function [name]

Sottoprogramma

Una subroutine non restituisce un valore, tuttavia può modificare i suoi argomenti.

Syntax

subroutine name(arg1, arg2, ....)    
   [declarations, including those for the arguments]    
   [executable statements]  
end subroutine [name]

Richiamo di una subroutine

È necessario richiamare una subroutine utilizzando il call dichiarazione.

L'esempio seguente mostra la definizione e l'uso di uno scambio di subroutine, che modifica i valori dei suoi argomenti.

program calling_func
implicit none

   real :: a, b
   a = 2.0
   b = 3.0
   
   Print *, "Before calling swap"
   Print *, "a = ", a
   Print *, "b = ", b
   
   call swap(a, b)
   
   Print *, "After calling swap"
   Print *, "a = ", a
   Print *, "b = ", b
   
end program calling_func


subroutine swap(x, y) 
implicit none

   real :: x, y, temp   
   
   temp = x  
   x = y 
   y = temp  
   
end subroutine swap

Quando compili ed esegui il programma sopra, produce il seguente risultato:

Before calling swap
a = 2.00000000    
b = 3.00000000    
After calling swap
a = 3.00000000    
b = 2.00000000

Specificare l'intento degli argomenti

L'attributo intent consente di specificare l'intenzione con cui vengono utilizzati gli argomenti nella procedura. La tabella seguente fornisce i valori dell'attributo intent:

Valore Usato come Spiegazione
in intento (in) Utilizzato come valori di input, non modificato nella funzione
su intento (fuori) Utilizzati come valore di output, vengono sovrascritti
dentro fuori intent (inout) Gli argomenti vengono utilizzati e sovrascritti

Il seguente esempio dimostra il concetto:

program calling_func
implicit none

   real :: x, y, z, disc
   
   x = 1.0
   y = 5.0
   z = 2.0
   
   call intent_example(x, y, z, disc)
   
   Print *, "The value of the discriminant is"
   Print *, disc
   
end program calling_func


subroutine intent_example (a, b, c, d)     
implicit none     

   ! dummy arguments      
   real, intent (in) :: a     
   real, intent (in) :: b      
   real, intent (in) :: c    
   real, intent (out) :: d   
   
   d = b * b - 4.0 * a * c 
   
end subroutine intent_example

Quando compili ed esegui il programma sopra, produce il seguente risultato:

The value of the discriminant is
   17.0000000

Procedure ricorsive

La ricorsione si verifica quando un linguaggio di programmazione consente di chiamare una funzione all'interno della stessa funzione. Si chiama chiamata ricorsiva della funzione.

Quando una procedura chiama se stessa, direttamente o indirettamente, viene chiamata procedura ricorsiva. È necessario dichiarare questo tipo di procedure precedendo la parolarecursive prima della sua dichiarazione.

Quando una funzione viene utilizzata in modo ricorsivo, il result deve essere utilizzata l'opzione.

Di seguito è riportato un esempio, che calcola fattoriale per un dato numero utilizzando una procedura ricorsiva -

program calling_func
implicit none

   integer :: i, f
   i = 15
   
   Print *, "The value of factorial 15 is"
   f = myfactorial(15)
   Print *, f
   
end program calling_func

! computes the factorial of n (n!)      
recursive function myfactorial (n) result (fac)  
! function result     
implicit none     

   ! dummy arguments     
   integer :: fac     
   integer, intent (in) :: n     
   
   select case (n)         
      case (0:1)         
         fac = 1         
      case default    
         fac = n * myfactorial (n-1)  
   end select 
   
end function myfactorial

Procedure interne

Quando una procedura è contenuta all'interno di un programma, viene chiamata procedura interna del programma. La sintassi per contenere una procedura interna è la seguente:

program program_name     
   implicit none         
   ! type declaration statements         
   ! executable statements    
   . . .     
   contains         
   ! internal procedures      
   . . .  
end program program_name

Il seguente esempio dimostra il concetto:

program mainprog  
implicit none 

   real :: a, b 
   a = 2.0
   b = 3.0
   
   Print *, "Before calling swap"
   Print *, "a = ", a
   Print *, "b = ", b
   
   call swap(a, b)
   
   Print *, "After calling swap"
   Print *, "a = ", a
   Print *, "b = ", b
 
contains   
   subroutine swap(x, y)     
      real :: x, y, temp      
      temp = x 
      x = y  
      y = temp   
   end subroutine swap 
   
end program mainprog

Quando compili ed esegui il programma sopra, produce il seguente risultato:

Before calling swap
a = 2.00000000    
b = 3.00000000    
After calling swap
a = 3.00000000    
b = 2.00000000

Un modulo è come un pacchetto in cui puoi conservare le tue funzioni e subroutine, nel caso tu stia scrivendo un programma molto grande, o le tue funzioni o subroutine possono essere usate in più di un programma.

I moduli forniscono un modo per suddividere i programmi tra più file.

I moduli sono utilizzati per:

  • Packaging sottoprogrammi, dati e blocchi di interfaccia.

  • Definizione di dati globali che possono essere utilizzati da più di una routine.

  • Dichiarazione di variabili che possono essere rese disponibili all'interno di qualsiasi routine scelta.

  • Importare un modulo interamente, per l'uso, in un altro programma o subroutine.

Sintassi di un modulo

Un modulo è composto da due parti:

  • una parte specifica per la dichiarazione delle istruzioni
  • a contiene una parte per le definizioni di subroutine e funzioni

La forma generale di un modulo è:

module name     
   [statement declarations]  
   [contains [subroutine and function definitions] ] 
end module [name]

Utilizzo di un modulo nel programma

È possibile incorporare un modulo in un programma o in una subroutine mediante l'istruzione use -

use name

Si prega di notare che

  • Puoi aggiungere tutti i moduli necessari, ognuno sarà in file separati e compilato separatamente.

  • Un modulo può essere utilizzato in vari programmi differenti.

  • Un modulo può essere utilizzato più volte nello stesso programma.

  • Le variabili dichiarate in una parte di specifica del modulo sono globali per il modulo.

  • Le variabili dichiarate in un modulo diventano variabili globali in qualsiasi programma o routine in cui viene utilizzato il modulo.

  • L'istruzione use può apparire nel programma principale o in qualsiasi altra subroutine o modulo che utilizza le routine o le variabili dichiarate in un particolare modulo.

Esempio

Il seguente esempio dimostra il concetto:

module constants  
implicit none 

   real, parameter :: pi = 3.1415926536  
   real, parameter :: e = 2.7182818285 
   
contains      
   subroutine show_consts()          
      print*, "Pi = ", pi          
      print*,  "e = ", e     
   end subroutine show_consts 
   
end module constants 


program module_example     
use constants      
implicit none     

   real :: x, ePowerx, area, radius 
   x = 2.0
   radius = 7.0
   ePowerx = e ** x
   area = pi * radius**2     
   
   call show_consts() 
   
   print*, "e raised to the power of 2.0 = ", ePowerx
   print*, "Area of a circle with radius 7.0 = ", area  
   
end program module_example

Quando compili ed esegui il programma sopra, produce il seguente risultato:

Pi = 3.14159274    
e =  2.71828175    
e raised to the power of 2.0 = 7.38905573    
Area of a circle with radius 7.0 = 153.938049

Accessibilità di variabili e subroutine in un modulo

Per impostazione predefinita, tutte le variabili e le subroutine in un modulo sono rese disponibili al programma che sta utilizzando il codice del modulo, dal use dichiarazione.

Tuttavia, è possibile controllare l'accessibilità del codice del modulo utilizzando il private e publicattributi. Quando dichiari una variabile o una subroutine come privata, non è disponibile al di fuori del modulo.

Esempio

L'esempio seguente illustra il concetto:

Nell'esempio precedente, avevamo due variabili di modulo, e e pi. Rendiamoli privati ​​e osserviamo l'output -

module constants  
implicit none 

   real, parameter,private :: pi = 3.1415926536  
   real, parameter, private :: e = 2.7182818285 
   
contains      
   subroutine show_consts()          
      print*, "Pi = ", pi          
      print*, "e = ", e     
   end subroutine show_consts 
   
end module constants 


program module_example     
use constants      
implicit none     

   real :: x, ePowerx, area, radius 
   x = 2.0
   radius = 7.0
   ePowerx = e ** x
   area = pi * radius**2     
   
   call show_consts() 
   
   print*, "e raised to the power of 2.0 = ", ePowerx
   print*, "Area of a circle with radius 7.0 = ", area  
   
end program module_example

Quando compili ed esegui il programma sopra, viene visualizzato il seguente messaggio di errore:

ePowerx = e ** x
   1
Error: Symbol 'e' at (1) has no IMPLICIT type
main.f95:19.13:

   area = pi * radius**2     
   1
Error: Symbol 'pi' at (1) has no IMPLICIT type

Da e e pi, entrambi sono dichiarati privati, il programma module_example non può più accedere a queste variabili.

Tuttavia, altre subroutine del modulo possono accedervi -

module constants  
implicit none 

   real, parameter,private :: pi = 3.1415926536  
   real, parameter, private :: e = 2.7182818285 
   
contains      
   subroutine show_consts()          
      print*, "Pi = ", pi          
      print*, "e = ", e     
   end subroutine show_consts 
   
   function ePowerx(x)result(ePx) 
   implicit none
      real::x
      real::ePx
      ePx = e ** x
   end function ePowerx
    
   function areaCircle(r)result(a)  
   implicit none
      real::r
      real::a
      a = pi * r**2  
   end function areaCircle
    
end module constants 


program module_example     
use constants      
implicit none     

   call show_consts() 
   
   Print*, "e raised to the power of 2.0 = ", ePowerx(2.0)
   print*, "Area of a circle with radius 7.0 = ", areaCircle(7.0)  
   
end program module_example

Quando compili ed esegui il programma sopra, produce il seguente risultato:

Pi = 3.14159274    
e = 2.71828175    
e raised to the power of 2.0 = 7.38905573    
Area of a circle with radius 7.0 = 153.938049

Le funzioni intrinseche sono alcune funzioni comuni e importanti fornite come parte del linguaggio Fortran. Abbiamo già discusso alcune di queste funzioni nei capitoli Array, Characters e String.

Le funzioni intrinseche possono essere classificate come:

  • Funzioni numeriche
  • Funzioni matematiche
  • Funzioni di ricerca numerica
  • Funzioni di manipolazione in virgola mobile
  • Funzioni di manipolazione dei bit
  • Funzioni dei caratteri
  • Funzioni gentili
  • Funzioni logiche
  • Funzioni array.

Abbiamo discusso le funzioni degli array nel capitolo Arrays. Nella sezione seguente forniamo brevi descrizioni di tutte queste funzioni da altre categorie.

Nella colonna del nome della funzione,

  • A rappresenta qualsiasi tipo di variabile numerica
  • R rappresenta una variabile reale o intera
  • X e Y rappresentano variabili reali
  • Z rappresenta la variabile complessa
  • W rappresenta una variabile reale o complessa

Funzioni numeriche

Suor n Descrizione della funzione
1

ABS (A)

Restituisce il valore assoluto di A

2

AIMAG (Z)

Restituisce la parte immaginaria di un numero complesso Z

3

AINT (A [, KIND])

Tronca la parte frazionaria di A verso zero, restituendo un numero intero reale.

4

ANINT (A [, KIND])

Restituisce un valore reale, il numero intero o intero più vicino.

5

CEILING (A [, KIND])

Restituisce il numero intero minimo maggiore o uguale al numero A.

6

CMPLX (X [, Y, KIND])

Converte le variabili reali X e Y in un numero complesso X + iY; se Y è assente, viene utilizzato 0.

7

CONJG (Z)

Restituisce il complesso coniugato di qualsiasi numero complesso Z.

8

DBLE (A)

Converte A in un numero reale a doppia precisione.

9

DIM (X, Y)

Restituisce la differenza positiva di X e Y.

10

DPROD (X, Y)

Restituisce il prodotto reale a doppia precisione di X e Y.

11

FLOOR (A [, KIND])

Fornisce il numero intero più grande minore o uguale al numero A.

12

INT (A [, KIND])

Converte un numero (reale o intero) in intero, troncando la parte reale verso lo zero.

13

MAX (A1, A2 [, A3,...])

Restituisce il valore massimo dagli argomenti, essendo tutti dello stesso tipo.

14

MIN (A1, A2 [, A3,...])

Restituisce il valore minimo dagli argomenti, essendo tutti dello stesso tipo.

15

MOD (A, P)

Restituisce il resto di A sulla divisione per P, essendo entrambi gli argomenti dello stesso tipo (A-INT (A / P) * P)

16

MODULO (A, P)

Restituisce A modulo P: (A-FLOOR (A / P) * P)

17

NINT (A [, KIND])

Restituisce il numero intero più vicino al numero A

18

REAL (A [, KIND])

Converte in caratteri reali

19

SIGN (A, B)

Restituisce il valore assoluto di A moltiplicato per il segno di P. Fondamentalmente trasferisce il segno di B in A.

Esempio

program numericFunctions
implicit none  

   ! define constants  
   ! define variables
   real :: a, b 
   complex :: z
   
   ! values for a, b 
   a = 15.2345
   b = -20.7689
    
   write(*,*) 'abs(a): ',abs(a),' abs(b): ',abs(b)   
   write(*,*) 'aint(a): ',aint(a),' aint(b): ',aint(b) 
   write(*,*) 'ceiling(a): ',ceiling(a),' ceiling(b): ',ceiling(b)   
   write(*,*) 'floor(a): ',floor(a),' floor(b): ',floor(b)  
    
   z = cmplx(a, b)
   write(*,*) 'z: ',z   
   
end program numericFunctions

Quando compili ed esegui il programma sopra, produce il seguente risultato:

abs(a): 15.2344999   abs(b): 20.7688999    
aint(a): 15.0000000  aint(b): -20.0000000    
ceiling(a): 16  ceiling(b): -20
floor(a): 15  floor(b): -21
z: (15.2344999, -20.7688999)

Funzioni matematiche

Suor n Descrizione della funzione
1

ACOS (X)

Restituisce il coseno inverso nell'intervallo (0, π), in radianti.

2

ASIN (X)

Restituisce il seno inverso nell'intervallo (-π / 2, π / 2), in radianti.

3

ATAN (X)

Restituisce la tangente inversa nell'intervallo (-π / 2, π / 2), in radianti.

4

ATAN2 (Y, X)

Restituisce la tangente inversa nell'intervallo (-π, π), in radianti.

5

COS (X)

Restituisce il coseno dell'argomento in radianti.

6

COSH (X)

Restituisce il coseno iperbolico dell'argomento in radianti.

7

EXP (X)

Restituisce il valore esponenziale di X.

8

LOG (X)

Restituisce il valore logaritmico naturale di X.

9

LOG10 (X)

Restituisce il valore logaritmico comune (base 10) di X.

10

SIN (X)

Restituisce il seno dell'argomento in radianti.

11

SINH (X)

Restituisce il seno iperbolico dell'argomento in radianti.

12

SQRT (X)

Restituisce la radice quadrata di X.

13

TAN (X)

Restituisce la tangente dell'argomento in radianti.

14

TANH (X)

Restituisce la tangente iperbolica dell'argomento in radianti.

Esempio

Il seguente programma calcola la posizione orizzontale e verticale xey rispettivamente di un proiettile dopo un tempo, t -

Dove, x = ut cos a e y = ut sin a - g t2 / 2

program projectileMotion  
implicit none  

   ! define constants  
   real, parameter :: g = 9.8  
   real, parameter :: pi = 3.1415927  
   
   !define variables
   real :: a, t, u, x, y   
   
   !values for a, t, and u 
   a = 45.0
   t = 20.0
   u = 10.0
   
   ! convert angle to radians  
   a = a * pi / 180.0  
   x = u * cos(a) * t   
   y = u * sin(a) * t - 0.5 * g * t * t  
   
   write(*,*) 'x: ',x,'  y: ',y   
   
end program projectileMotion

Quando compili ed esegui il programma sopra, produce il seguente risultato:

x: 141.421356  y: -1818.57861

Funzioni di ricerca numerica

Queste funzioni funzionano con un certo modello di aritmetica di numeri interi e virgola mobile. Le funzioni restituiscono proprietà di numeri dello stesso tipo della variabile X, che può essere reale e in alcuni casi intero.

Suor n Descrizione della funzione
1

DIGITS (X)

Restituisce il numero di cifre significative del modello.

2

EPSILON (X)

Restituisce il numero che è quasi trascurabile rispetto a uno. In altre parole, restituisce il valore più piccolo tale che REAL (1.0, KIND (X)) + EPSILON (X) non è uguale a REAL (1.0, KIND (X)).

3

HUGE (X)

Restituisce il numero più alto del modello

4

MAXEXPONENT (X)

Restituisce l'esponente massimo del modello

5

MINEXPONENT (X)

Restituisce l'esponente minimo del modello

6

PRECISION (X)

Restituisce la precisione decimale

7

RADIX (X)

Restituisce la base del modello

8

RANGE (X)

Restituisce l'intervallo esponente decimale

9

TINY (X)

Restituisce il numero positivo più piccolo del modello

Funzioni di manipolazione in virgola mobile

Suor n Descrizione della funzione
1

EXPONENT (X)

Restituisce la parte esponente di un numero di modello

2

FRACTION (X)

Restituisce la parte frazionaria di un numero

3

NEAREST (X, S)

Restituisce il numero di processore diverso più vicino nella direzione data

4

RRSPACING (X)

Restituisce il reciproco della spaziatura relativa dei numeri di modello vicino al numero dato

5

SCALE (X, I)

Moltiplica un reale per la sua base in una potenza intera

6

SET_EXPONENT (X, I)

restituisce la parte esponente di un numero

7

SPACING (X)

Restituisce la spaziatura assoluta dei numeri di modello vicino al numero dato

Funzioni di manipolazione dei bit

Suor n Descrizione della funzione
1

BIT_SIZE (I)

Restituisce il numero di bit del modello

2

BTEST (I, POS)

Test di bit

3

IAND (I, J)

AND logico

4

IBCLR (I, POS)

Un po 'chiaro

5

IBITS (I, POS, LEN)

Estrazione bit

6

IBSET (I, POS)

Imposta bit

7

IEOR (I, J)

Esclusivo o

8

IOR (I, J)

Inclusivo OR

9

ISHFT (I, SHIFT)

Spostamento logico

10

ISHFTC (I, SHIFT [, SIZE])

Spostamento circolare

11

NOT (I)

Complemento logico

Funzioni dei caratteri

Suor n Descrizione della funzione
1

ACHAR (I)

Restituisce il carattere Ith nella sequenza di confronto ASCII.

2

ADJUSTL (STRING)

Regola la stringa sinistra rimuovendo eventuali spazi vuoti iniziali e inserendo spazi vuoti finali

3

ADJUSTR (STRING)

Regola la stringa a destra rimuovendo gli spazi vuoti finali e inserendo quelli iniziali.

4

CHAR (I [, KIND])

Restituisce il I ° carattere nella sequenza di fascicolazione speci fi ca della macchina

5

IACHAR (C)

Restituisce la posizione del carattere nella sequenza di confronto ASCII.

6

ICHAR (C)

Restituisce la posizione del carattere nella sequenza di fascicolazione speci fi ca della macchina (processore).

7

INDEX (STRING, SUBSTRING [, BACK])

Restituisce la posizione iniziale più a sinistra (più a destra se BACK è .TRUE.) Di SUBSTRING all'interno di STRING.

8

LEN (STRING)

Restituisce la lunghezza di una stringa.

9

LEN_TRIM (STRING)

Restituisce la lunghezza di una stringa senza lasciare caratteri vuoti.

10

LGE (STRING_A, STRING_B)

Lexically maggiore o uguale

11

LGT (STRING_A, STRING_B)

Lexically maggiore di

12

LLE (STRING_A, STRING_B)

Lessicamente inferiore o uguale

13

LLT (STRING_A, STRING_B)

Lessicamente inferiore a

14

REPEAT (STRING, NCOPIES)

Concatenazione ripetuta

15

SCAN (STRING, SET [, BACK])

Restituisce l'indice del carattere più a sinistra (più a destra se BACK è .TRUE.) Di STRING che appartiene a SET, o 0 se nessuno appartiene.

16

TRIM (STRING)

Rimuove i caratteri vuoti finali

17

VERIFY (STRING, SET [, BACK])

Verifica il set di caratteri in una stringa

Funzioni gentili

Suor n Descrizione della funzione
1

KIND (X)

Restituisce il valore del parametro di tipo kind.

2

SELECTED_INT_KIND (R)

Restituisce il tipo di parametro di tipo per l'intervallo di esponenti specificato.

3

SELECTED_REAL_KIND ([P, R])

Valore del parametro di tipo reale, precisione e intervallo dati

Funzione logica

Suor n Descrizione della funzione
1

LOGICAL (L [, KIND])

Conversione tra oggetti di tipo logico con parametri di tipo diverso

Abbiamo già discusso che, nelle versioni precedenti di Fortran, ce n'erano due real tipi: il tipo reale predefinito e double precision genere.

Tuttavia, Fortran 90/95 fornisce un maggiore controllo sulla precisione dei tipi di dati reali e interi tramite kind specifie.

L'attributo gentile

Diversi tipi di numeri vengono memorizzati in modo diverso all'interno del computer. Ilkindl'attributo consente di specificare come un numero viene memorizzato internamente. Per esempio,

real, kind = 2 :: a, b, c
real, kind = 4 :: e, f, g
integer, kind = 2 :: i, j, k
integer, kind = 3 :: l, m, n

Nella dichiarazione di cui sopra, le variabili reali e, f e g hanno più precisione delle variabili reali a, be c. Le variabili intere l, m e n, possono memorizzare valori più grandi e avere più cifre per la memorizzazione rispetto alle variabili intere i, j e k. Anche se questo dipende dalla macchina.

Esempio

program kindSpecifier
implicit none

   real(kind = 4) :: a, b, c
   real(kind = 8) :: e, f, g
   integer(kind = 2) :: i, j, k
   integer(kind = 4) :: l, m, n
   integer :: kind_a, kind_i, kind_e, kind_l
   
   kind_a = kind(a)
   kind_i = kind(i)
   kind_e = kind(e)
   kind_l = kind(l)
   
   print *,'default kind for real is', kind_a
   print *,'default kind for int is', kind_i
   print *,'extended kind for real is', kind_e
   print *,'default kind for int is', kind_l
   
end program kindSpecifier

Quando compili ed esegui il programma sopra, produce il seguente risultato:

default kind for real is 4
default kind for int is 2
extended kind for real is 8
default kind for int is 4

Indagine sulla dimensione delle variabili

Esistono numerose funzioni intrinseche che consentono di interrogare la dimensione dei numeri.

Ad esempio, il file bit_size(i)la funzione intrinseca specifica il numero di bit utilizzati per la memorizzazione. Per numeri reali, ilprecision(x) funzione intrinseca, restituisce il numero di cifre decimali di precisione, mentre il range(x) la funzione intrinseca restituisce l'intervallo decimale dell'esponente.

Esempio

program getSize
implicit none

   real (kind = 4) :: a
   real (kind = 8) :: b
   integer (kind = 2) :: i
   integer (kind = 4) :: j

   print *,'precision of real(4) =', precision(a)
   print *,'precision of real(8) =', precision(b)
   
   print *,'range of real(4) =', range(a)
   print *,'range of real(8) =', range(b)
   

   print *,'maximum exponent of real(4) =' , maxexponent(a)
   print *,'maximum exponent of real(8) =' , maxexponent(b)
  
   print *,'minimum exponent of real(4) =' , minexponent(a)
   print *,'minimum exponent of real(8) =' , minexponent(b)
   
   print *,'bits in integer(2) =' , bit_size(i)
   print *,'bits in integer(4) =' , bit_size(j)
   
end program getSize

Quando compili ed esegui il programma sopra, produce il seguente risultato:

precision of real(4) = 6
precision of real(8) = 15
range of real(4) = 37
range of real(8) = 307
maximum exponent of real(4) = 128
maximum exponent of real(8) = 1024
minimum exponent of real(4) = -125
minimum exponent of real(8) = -1021
bits in integer(2) = 16
bits in integer(4) = 32

Ottenere il valore gentile

Fortran fornisce altre due funzioni intrinseche per ottenere il valore del tipo per la precisione richiesta di numeri interi e reali -

  • selected_int_kind (r)
  • selected_real_kind ([p, r])

La funzione selected_real_kind restituisce un numero intero che è il valore del parametro di tipo kind necessario per una data precisione decimale pe intervallo di esponente decimale r. La precisione decimale è il numero di cifre significative e l'intervallo di esponenti decimali specifica il numero rappresentabile più piccolo e più grande. L'intervallo è quindi da 10-r a 10 + r.

Ad esempio, selected_real_kind (p = 10, r = 99) restituisce il valore del tipo necessario per una precisione di 10 cifre decimali e un intervallo da almeno 10-99 a 10 + 99.

Esempio

program getKind
implicit none

   integer:: i
   i = selected_real_kind (p = 10, r = 99) 
   print *,'selected_real_kind (p = 10, r = 99)', i
   
end program getKind

Quando compili ed esegui il programma sopra, produce il seguente risultato:

selected_real_kind (p = 10, r = 99) 8

Sono disponibili vari strumenti e librerie Fortran. Alcuni sono gratuiti e alcuni sono servizi a pagamento.

Di seguito sono riportate alcune librerie gratuite:

  • RANDLIB, numeri casuali e generatori di distribuzione statistica
  • BLAS
  • EISPACK
  • Guida GAMS – NIST al software matematico disponibile
  • Alcune routine statistiche e altre del NIST
  • LAPACK
  • LINPACK
  • MINPACK
  • MUDPACK
  • Biblioteca matematica NCAR
  • La raccolta Netlib di software matematico, documenti e database.
  • ODEPACK
  • ODERPACK, un insieme di routine per classificare e ordinare.
  • Expokit per il calcolo degli esponenziali delle matrici
  • SLATEC
  • SPECFUN
  • STARPAC
  • Libreria statistica StatLib
  • TOMS
  • Ordinamento e unione di stringhe

Le seguenti librerie non sono gratuite:

  • La libreria numerica di NAG Fortran
  • La libreria IMSL di Visual Numerics
  • Ricette numeriche

Lo stile di programmazione consiste nel seguire alcune regole durante lo sviluppo dei programmi. Queste buone pratiche conferiscono valori come leggibilità e non ambiguità al tuo programma.

Un buon programma dovrebbe avere le seguenti caratteristiche:

  • Readability
  • Struttura logica adeguata
  • Note e commenti autoesplicativi

Ad esempio, se fai un commento come il seguente, non sarà di grande aiuto -

! loop from 1 to 10 
do i = 1,10

Tuttavia, se stai calcolando il coefficiente binomiale e hai bisogno di questo ciclo per nCr, un commento come questo sarà utile -

! loop to calculate nCr 
do i = 1,10
  • Blocchi di codice rientrati per rendere chiari i vari livelli di codice.

  • Codici di autocontrollo per garantire che non ci siano errori numerici come divisione per zero, radice quadrata di un numero reale negativo o logaritmo di un numero reale negativo.

  • Compresi codici che assicurano che le variabili non assumano valori illegali o fuori intervallo, ad esempio la convalida dell'input.

  • Non mettere controlli dove sarebbe inutile e rallenta l'esecuzione. Ad esempio:

real :: x 
x = sin(y) + 1.0

if (x >= 0.0) then
   z = sqrt(x)
end if
  • Codice scritto in modo chiaro utilizzando algoritmi appropriati.
  • Dividere le espressioni lunghe utilizzando il marcatore di continuazione "&".
  • Creare nomi di variabili significativi.

Uno strumento debugger viene utilizzato per cercare gli errori nei programmi.

Un programma debugger esegue il codice e consente di esaminare i valori nelle variabili e in altri oggetti dati durante l'esecuzione del programma.

Carica il codice sorgente e dovresti eseguire il programma all'interno del debugger. I debugger eseguono il debug di un programma tramite:

  • Impostazione dei punti di interruzione,
  • Passando attraverso il codice sorgente,
  • Impostazione dei punti di controllo.

I punti di interruzione specificano dove il programma deve arrestarsi, in particolare dopo una riga di codice critica. Le esecuzioni del programma dopo che le variabili sono state verificate in un punto di interruzione.

I programmi debugger controllano anche il codice sorgente riga per riga.

I punti di controllo sono i punti in cui è necessario controllare i valori di alcune variabili, in particolare dopo un'operazione di lettura o scrittura.

Il debugger gdb

Il debugger gdb, il debugger GNU viene fornito con il sistema operativo Linux. Per il sistema X Windows, gdb è dotato di un'interfaccia grafica e il programma si chiama xxgdb.

La tabella seguente fornisce alcuni comandi in gdb:

Comando Scopo
rompere Impostazione di un punto di interruzione
correre Inizia l'esecuzione
cont Continua l'esecuzione
Il prossimo Esegue solo la riga successiva del codice sorgente, senza passare ad alcuna chiamata di funzione
passo Eseguire la riga successiva di codice sorgente entrando in una funzione in caso di chiamata di funzione.

Il debugger dbx

C'è un altro debugger, il debugger dbx, per Linux.

La tabella seguente fornisce alcuni comandi in dbx:

Comando Scopo
interrompi [var] Imposta un punto di interruzione quando il valore della variabile var cambia.
fermati in [proc] Arresta l'esecuzione quando viene inserita una procedura proc
fermati a [linea] Imposta un punto di interruzione su una riga specificata.
correre Inizia l'esecuzione.
cont Continua l'esecuzione.
Il prossimo Esegue solo la riga successiva del codice sorgente, senza entrare in alcuna chiamata di funzione.
passo Eseguire la riga successiva di codice sorgente entrando in una funzione in caso di chiamata di funzione.