|
INDICE
- INTRODUZIONE
- IL PRIMO PROGRAMMA
- IL LESSICO DEL
FORTRAN
- Programma
- Istruzioni
- Commenti
- Variabili
- Vettori e Matrici
- Operazioni
aritmetiche e funzioni intrinseche.
- Istruzioni
Logiche e di Controllo
- Strutture di
controllo.
- Iterazione,
DO-loops
- Strutture
IF
- Istruzioni
di iterazione (di salto) GOTO.
- Istruzioni
di INPUT-OUTPUT
- UNA LISTA DI PROGRAMMI
MOLTO SEMPLICI
- Una farfalla
da aggiungere alla collezione
- Un bel tappeto
caotico
- Algoritmo di
Euclide.
- Ancora algoritmo
di Euclide
- Rappresentazione
di un numero reale in base binaria
A cura di G. POLLAROLO
.
1 - INTRODUZIONE.
Iniziamo queste nostre lezioni di FISICA
NUMERICA con una breve introduzione al
linguaggio FORTRAN (formula translator).
Abbiamo scelto questo linguaggio per la sua duttilità
nella implementazione degli algoritmi che si incontrano
nella risoluzioni dei problemi numerici che sono comuni
a moltissime discipline scientifiche.
Lo scopo di questa introduzione è di mostrarvi gli
elementi essenziali del linguaggio di programmazione
senza avere la pretesa di essere completi o anche
esatti (ovviamente i diversi esempi che faremo spero
lo siano). Quello che si vuole è famigliarizzarvi
al più presto con il linguaggio stesso in modo che
possiate scrivere subito programmi utili. Per fare
questo ci dobbiamo concentrare sugli aspetti fondamentali
del FORTRAN : variabili, costanti,
operazioni aritmeticche, controllo di flusso, function,
subroutine e i rudimenti dell'input e dell'output.
La parte più raffinata del linguaggio, utile per
la stesura di programmi complessi, viene lasciata
da parte, si cercherà di descriverla man mano che
diventa necessaria nel prosiego del nostro corso.
Ovviamente questa scelta comporterà delle inevitabili
ripetizioni che spero non siano di tedio ma servano
di approfondimento. Spero anche che questa introduzione
vi porti ad una comprensione del FORTRAN
tale da poter consultare con profitto i manuali dove
sono descritte in grande dettaglio tutte le varie
possibilità del liguaggio.
2 - IL PRIMO PROGRAMMA.
C'è un unico modo per imparare un nuovo linguaggio
di programmazione è, scrivendo programmi. Il primo
programma che si scrive è sempre lo stesso in tutti
i linguaggi: cioè richiedere al calcolatore di scrivere
le parole
hello, benvenuti a FISICA NUMERICA
La stesura di questo
programma, seppur semplicissimo, comporta la conoscenza
di tutti quei passaggi fondamentali che dovete imparare
a maneggiare subito.
Per poter richiedere al vostro calcolatore di eseguire
questo semplice ordine dovete essere in grado di scrivere
da qualche parte il testo del programma (questo comporta
l'avere accesso ad un terminale e saper usare un EDITOR
, dovete saperlo compilare
correttamente (cioè ordinare al calcolatore di controllare
l'ortografia del testo del programma), saper fare
il LINK (cioè controllarne la struttura
con il sistema operativo della macchina stessa) e
per ultimo saperlo eseguire e scoprire così dove la
scritta compare (cioè dove va a finire l'OUTPUT).
Trovato un amico (il cosiddetto local expert) che
vi spieghi questi dettagli, proprii della struttura
di calcolo che dovete usare, la scrittura del programma
è estremamente semplice. Usando appunto il liguaggio
FORTRAN il programma per scrivere
hello, benvenuti a FISICA NUMERICA
è semplicemente:
print *,' hello, benvenuti a FISICA NUMERICA'
stop
end
Il come eseguirete questo programma dipenderà dal
sistema su cui state lavorando, per essere specifici
supporremo di lavorare su una macchina VAX
con il sistema operativo VMS. Su questo
sistema invocando l' EDITOR, per esempio
con il comando:
$ edit/edt !($ è il prompt del VMS)
create una file che contenga il sorgente (source) del
programma e che abbia un nome con la estensione .for,
per esempio benvenuto.for. Fatto questo
con il comando
$ for benvenuto
eseguitene la compilazione, se il compilatore non protesta,
cioè se non vi inonda lo schermo con messaggi di errore,
potete proseguire alla creazione dell'elemento eseguibile
con il comando
$ link benvenuto
Se anche il link non protesta troverete nella vostra
directory un nuovo file benvenuto.exe
che può essere eseguito con il comando
$ run benvenuto
Se tutti gli steps descritti sono eseguiti correttamente
sul, vostro schermo (sulla sinistra in basso) troverete
le parole:
hello, benvenuti FISICA NUMERICA
[FORTRAN STOP]
Come esercizio provate a riscrivere il summenzionato
programma commettendo deliberamente degli errori durante
la fase di editing e leggete attentamente i messaggi
di errore che compariranno sul vostro schermo durante
la fase di compilazione, questo servirà a famigliarizzarvi
con il linguaggio del calcolatore stesso.
Prima di finire, alcune considerazione sul programma
stesso. Un programma FORTRAN, indipendentemente
dalla sua dimensione, è costituito da un insieme di
più functions e/o subroutines che
specificano le diverse operazione che devone essere
fatte. Il nome di queste routines è lasciato
libero al programmatore eccetto che per il main
che viene definito come quella routine che
contiene le istruzioni stop ed end
(le altre routines terminano con l'istruzione
return). Tutti i programmi FORTRAN
iniziano la loro esecuzione dal main. è il
main che distribuisce poi i vari compiti
alle subroutine. La chiamata ad una routine,
sia questa intrinseca o scritta dal programmatore,
avviene normalmente nominandola nel programma e facendola
seguire da una serie di argomenti che ne costituiscono
l' input e ne determinano il risultato output
(anche questo può, in generale, essere contenuto negli
argomenti).
Ritornamdo al nostro esempio vediamo che questo programma
è costituito da una sola routine il main
che contiene una chiamata alla routine intrinseca
del FORTRAN print . Questa
routine ha come argomenti una stella (
*) e la stringa di caratteri che deve scrivere,
notate che questa è stata delimitata da apici (
'. La stellina ( *) definisce il formato
con cui gli argomenti che seguono devono essere stampati
(in questo caso in free format), ne approfondiremo
il significato più avanti. Le ultime due istruzioni
del programma sono già state commentate.
3 - IL LESSICO DEL FORTRAN.
Riassumiamo brevemente cosa abbiamo imparato dall'esempio
precedente. Il FORTRAN, permettendo
la stesura di procedure (programmi) per impartire
istruzioni alla CPU del calcolatore, costituisce
una importante interfaccia utente macchina. Al contrario
del forse più noto BASIC, non è direttamente eseguibile
ma necessita di una prima fase di compilazione
per il controllo della ortografia e di una successiva
fase di mapping che ne controlla la sua struttura
con il sistema operativo della macchina stessa. Dopo
questi due passaggi si ottiene un modulo che è direttamente
eseguibile.
Il FORTRAN permette una programmazione
STRUTTURATA e per la sua struttura algebrica
è particolarmente adatto alle applicazioni scientifiche.
Il riconoscimento di questo è molto importante in
quanto a noi interessa non tanto sapere quello che
un programma fa ma vogliamo sapere come lo fa in quanto
vogliamo essere in grado di rileggerlo ed eventualmente
modificarlo in tempi successivi per renderlo adatto
alle nostre nuove esigenze.
Quando scriviamo un programma dobbiamo sempre tener
presente che questo dovrà poter essere letto da altri
(o da noi stessi in tempi successivi) per cui dovranno
essere facilmente riconoscibili le sue diverse parti
ed il modo con cui gli algoritmi usati sono stati
implementati. Questo per capire se un dato programma
di cui siamo venuti in possesso soddisfa le nostre
esigenze e se gli algoritmi sono stati implementati
correttamente ed in modoefficiente
La struttura di un programma non si manifesta solo
nella sua suddivisione in SUBROUTINE e FUNCTION
ma nella presenza di una certa gerarchia nelle
diverse parti che lo compongono. Al livello più basso
troviamo l'insieme dei caratteri ASCII, poi
le costanti, gli operatori e semplici istruzioni quali
per esempio:
root(j)=.5*(-b+sqrt(delta))/a
Al livello successivo si trovano gruppi di istruzioni
cha hanno un certo significato quando sono considerate
in blocco, per esmpio:
aux=a(i)
a(i)=b((i)
b(i)=aux
vengono interpretate da ogni programmatore come lo scambio
di due variabili mentre il gruppo di istruzioni
sum=0
ifial=1
answer=0.
n=1
significa probabilmente la inizializzazione di variabili
per alcuni procedimenti iterativi. Il buon programmatore
avrà cura di mettere commenti che descrivono il significato
di questi blocchi di istruzioni, così scriverà cambio
di variabili nel primo caso ed inizializzazione
nel secondo,
c
c inizilizzazione per l'intergrazione....
sum=0
ifial=1
answer=0.
n=1
Al livello successivo abbiamo poi le strutture che
sono governate da comandi di controllo come il DO
o l' IF che modificano l'esecuzione
sequenziale di un programma e che verranno spiegate
dovutamente in seguito.
Da ultimo abbiamo le strutture fornite dalle subroutine
e dalle function . Il loro significato
e la loro importanza nella corretta costruzione di
un5 programma sarà trasparente solo quando si implementeranno
i vari algoritmi che studieremo nella risoluzione
pratica dei problemi fisici. Per preparci a capire
questo cominciamo con il vedere un po' di lessico
del FORTRAN.
3.1 Programma
La traduzione di un metodo di calcolo (algoritmo)
con una seguenza di istruzioni che il calcolatore
può interpretare e che termina con la parola end
definisce una struttura di calcolo cioè
un programma. Il programma principale (main),
le subroutine e le function costituiscono
le unità di programma.
3.2 Istruzioni
Queste si possono suddividere in due categorie:
- eseguibili, cioè che descrivono una azione che
il programma può eseguire
- non eseguibili, cioè che definiscono delle variabili
o delle stutture di dati o delle dichiarazioni,....
Le istruzioni, cioè i diversi passi in cui un programma
è suddiviso, devono essere solitamente contenute in
una linea di 72 caratteri, partendo sempre
dalla colonna 7. Le prime sei colonne sono
usate per definire la label di una data istruzione,
per dire se questa linea di programma deve essere
considerata di commento o per dire se essa deve esssere
vista come una continuazione di quella precedente.
Se l'istruzione che si vuole scrivere richiede più
dei caratteri permessi si può continuare nella linea
successiva avendo cura di mettere un carattere (non
sono permessi lo zero (0) e lo spazio (blank)) in
colonna 6.
3.3 Commenti
Sono linee che si inseriscono durante la stesura
di un programma per documentazione. Queste non alterano
la sequenza di calcolo e possono essere inserite in
qualsiasi punto del programma identificandole con
un carattere speciale in colonna 1 (uno). Cono permessi
i seguenti caratteri di commento:
- la lettera c in colonna 1
- l'asterisco * in colonna 1
- il punto esclamativo& ! si ignora tutto ciò che sta alla destra
Per facilitare la lettura di un programma si raccomanda
l'uso delle linee di commento che devono illustrare
le procedure adottate. Si raccomanda altresi l'uso della
* in colonna uno (1) per definire le linee di commento,
questo perche sulle macchine vettoriali la lettera c
in prima colonna viene interpretata diversamente dal
FORTRAN implementato su questo tipo
di macchine.
3.4 Variabili.
Nel FORTRAN una variabile è definita
quando appare sul lato sinistro di una istruzione.
Per esempio:
x=3.
definisce la variabile x , questa può in seguito
essere usata in successive istruzioni che possono definire
nuove variabili come per esempio:
y=1.+x+3.*x**2
si noti che il segno di uguale ( =) non va
interpretato con il suo significato matematico ma piuttosto
rappresenta l'operazione di rimpiazzamento, così l'espressione:
x=x+1.
non ha senso in matematica mentre in programmazione
significa rimpiazzare la x con il valore di
x+1
Il nome di una variabile è una sequenza al più di
31 caratteri che possono essere lettere (maiuscole
e minuscole) numeri e caratteri speciali quali il
$ e _ (underscore). Le variabili non possono iniziare
con un numero. Su alcune vecchie macchine le variabili
non possono eccedere la lunghezza di sei (6) caratteri.
Il FORTRAN permette variabili di
diverso tipo, le più importanti sono:
- variabili intere (per default il compilatore considera
intere le variabili che iniziano con le lettere
i,j,k,l,m,n che possono assume valori da
-32768 a +32767 ( integer *2)
- variabili reali (per default tutte le variabili
che iniziano con gli altri caratteripermessi) che
assumono valori nell'intervallo -0.29*10-38 ed 1.7*1038
con una precisione sulle prime sette (7) cifre (
real *4)
- variabili complesse (come due variabili reali)
- variabili logiche
- caratteri alfanumerici (dette anche stringhe)
- byte (cioè otto (8) bit)
3.5 Vettori e Matrici.
L'istruzione:
dimension avec(12),amat(5,7)
oppure
real*4 avec(12),amat(5,7)
definisce che la varaibile avec deve essere
considerata come un insieme di 12 variabili reali identificabili
con l'indice i=(1-12), in modo analogo amat
definisce un insieme di 5*7 variabili reali. Ovviamente
l'introduzione di vettori e matrici non costituisce
semplicemente una economia di nomi di variabili ma permette
l'implementazione di raffinati algoritmi matematici.
I nomi ivec e imat indicheranno vettori (matrici) di
numeri interi.
3.6 Operazioni aritmetiche e funzioni intrinseche.
Le operazioni aritmetiche elementari che si possono
fare sono:
- x+y somma
- x-y differenza
- x*y prodotto
- x/y divisione
- x**m potenza m-esima di x (m
intero)
- x**y esponenzazione
dove con x e y abbiamo indicato il
nome di variabili o di espressioni. Oltre alle operazioni
fondamentali viste sopra si possono richiamare un certo
numero di funzioni intrinseche (build-in functions,).
Le più comuni che troverete sono:
- sin,cos,tan le funzioni trigonometriche
del seno, coseno e tangente
- asin,acos le funzioni trigonometriche
inverse
- log logaritmo naturale
- exp esponenziale
- sqrt radice quadrata
- abs valore assoluto
Queste funzioni intrinseche possono intervenire nella
definizione di espressioni del tipo 3.+2.*sqrt(5.)
oppure del tipo 2.*acos(0) (quest'ultima per
definire il numero $\pi$). Si noti che l'argomento va
racchiuso tra parentesi e segue il nome della funzione
chiamata. Per ottenere la lista completa delle funzioni
intrinsiche consultate il manuale del FORTRAN che state
usando.
3.7 Istruzioni Logiche e di Controllo.
Sono relazioni che intercorrono fra variabili logiche.
Siano x and y due variabili logiche,
allora:
- .not.x falsa se x è vera e vera
se x è falsa,
- x.and.y vera se x ed y
sono vere contemporaneamente, falsa altrimenti,
- x.or.y vera se la x o la y
sono vere, falsa altrimenti.
Se x ad y sono due espressioni o due
variabili (intere o reali) le seguenti istruzioni permettono
di confrontarle fra loro:
- x.eq.y vera se x è uguale a
y, falsa altrimenti
- x.ne.y vera se x e y
sono diversi, falsa altrimenti
- x.gt.y vera se x è più grande
di y, falsa altrimenti
- x.lt.y vera se x è più piccola
di y, falsa altrimenti
- x.ge.y vera se x è più grande
od uguale a y, falsa altrimenti
- x.le.y vera se x è più piccola
od uguale a y, falsa altrimenti.
Si notino i punti (.) che intervengono sempre nella
definizione degli operandi logici.
3.8 Strutture di controllo.
Un programma viene eseguito sequenzialmente una istruzione
dopo l'altra nell'ordine in cui queste sono state
scritte (il compilatore può a volte alterare questo
ordine se lo ritiene necessario per ottimizzare lo
svolgimento del programma). Le istruzioni che modificano
l'ordine con cui le istruzioni vengono eseguite si
chiamano istruzioni di controllo. Queste non
hanno un particolare significato in sè, il significato
che assumono deriva dal blocco di istruzioni che governano.
La corretta implemetazione di queste istruzioni è
essenziale per una buona programmazione strutturata.
3.8.1 Iterazione, DO-loops.
Nel FORTRAN la semplice iterazione
viene effettuata con il do-loop per esempio
se si vuole calcolare la funzione f(x)=sin(x)exp(-x/a)
per i valori di x compresi fra x=0
ad x=2. in step di dx=0.1 si procede
come segue:
dimension a(200)
................
flam=0.65
xmin=0.
xmax=2.
dx=0.1
x=xmin
npoint=(xmax-xmin)/dx+1.0001 !(nota il fattore 1.0001)
do n=1,npoint
a(n)=sin(x)*exp(-x/flam)
x=x+dx
enddo
................
Notare che nella scrittura delle istruzioni governate
dal do-loop si è avuto cura di indentarle.
Questo modo di scrivere il source di un programma non
interessa il compilatore ma aiuta molto i vostri occhi
quando devono rileggere il programma. Purtroppo non
tutti i calcolatori accettano come ortografia del do-loop
quella appena vista, ma preferiscono la seguente:
dimension a(200)
................
flam=0.65
xmin=0.
xmax=2.
dx=0.1
x=xmin
npoint=(xmax-xmin)/dx+1.0001 !(nota il fattore 1.0001)
do 10 n=1
a(n)=sin(x)*exp(-x/flam)\endline
x=x+dx
10 continue
................
come si vede in questo secondo caso si è dovuto ricorrere
all'uso di numeri labels che identificano una
data istruzione in questo caso il continue.
Questa è una istruzione muta che passa l'esecuzione
alla istruzione successiva.
Oltre al semplice do-loop visto sopra si
possono avere i cosiddetti NESTED do-loop
come:
dimension a(30,25)
.................
do n=1,25\endline
...............
do m=1,30
................
a(m,n)=.........
................
enddo
enddo
..................
si noti ancora l'importanza della indentazione per identificare
il gruppo di istruzioni che sono interssate alla iterazione.
In generale il do-loop si scrive:
.................
do n=n1,n2,nstep
...............
a(n)=..........
...............
enddo
..................
dove i valori di n1 ed n2 specificano
l'intervallo entro cui l'indice n del do-loopd
deve essere iterato ed nstep indica con che
passo questa iterazione debba avvenire. Se nstep
viene omesso, come negli esempi precedenti, il compilatore
assume nstep=1. È importante sapere che l'indice
del do-loop viene ad assumere il valore (
n2+nstep) al termine della iterazione e che il
controllo di fine loop avviene prima della esecuzione
del blocco di istruzioni interno. Questa considerazione
pu\'o risultare importante in molte applicazioni che
vedremo in seguito.
3.8.2 Strutture IF.
Gli esempi che seguono illustrano l'uso della struttua
if, è importante capirla bene in quanto è
essenziale nella implementazione degli algorimtmi
che vedremo in seguito. In tutti gli esempi che seguono
con e,e1,e2,... si intenderanno delle espressioni
logiche.
Esempio 1.
if(e)then
..................
..................
endif
è chiaro che il blocco di istruzioni (indicato con )
è eseguito solo se la condizione e è vera.
Esempio 2.
if(e1)then
..................
..................
else
..................
..................
endif
Il blocco 1 di istruzione è eseguito se la condizione
e1 è vera, in caso contrario viene eseguito
il blocco 2 di istruzioni.
Esempio 3.
if(e1)then
..................
..................
else if(e2)then
..................
..................
endif
Se la condizione e1 è verificata viene eseguito
il blocco 1 mentre se è verificata la condizione e2
viene eseguito il blocco 2. Se le condizioni logiche
e1 ed e2 non sono verificate allora
nessuno dei blocchi viene eseguito.
Esempio 4.
if(e1)then
..................
..................
else if(e2)then
..................
..................
else
..................
..................
endif
Le istruzioni indicate genericamente con vengono
eseguite solo se le condizioni e1 ed e2
non sono verificate.
Le strutture if degli esempi 3 e 4 possono
essere iterate anche per più condizioni logiche. L'importanza
di queste strutture è di per se ovvia e la si apprezzerà
appieno in seguito durante le applicazioni pratiche.
Ancora una volta vi ricordo l'importanza della corretta
indentazione del blocco di istruzioni interessato
dalla istruzione IF.
3.8.3 Istruzioni di iterazione (di salto)
GOTO.
Il molte applicazioni si ha la necessità di interrompere
alcune sequenze di iterazione quando si verificano
certe condizioni su alcuni parametri che governano
l'iterazione stessa. Per illustrare come queste istruzioni
si usano vediamo come si può riscrivere il primo esempio
dell'applicazione del do-loop appunto usando
il goto.
dimension a(200)
................
flam=0.65
xmin=0.
xmax=2.
dx=0.1
x=xmin
npoint=(xmax-xmin)/dx+1.0001 !(nota il fattore 1.0001)
n=1
10 continue
a(n)=sin(x)*exp(-x/flam)
x=x+dx
n=n+1
if(n.gt.npoint) goto 20
goto 10
20 continue
................
Si deve notare che la istruzione goto deve
sempre fare riferimento ad una istruzione del programma
con una label.
L'adozione di questa istruzione di salto al di fuori
di un suo uso corretto deve essere in ogni caso molto
parsimonioso impone infatti al programma di avere
diversi labels (si ricordi che in un programma
i labels devono essere unici) che pregiudicano
la lettura del programma stesso in quanto ne alterano
la seguenzialità. Un uso esasperato dei goto
porta inevitabilmente a commettere molti errori nella
stesura del programma, fortunatamente questi sono
quasi sempre rilevati dal compilatore derivando per
lo più da un cattivo uso delle labels. Ovviamente
non è qui il caso di fare una lista di tutti i possibili
errori che si possono commettere è meglio discuterli
man mano che si presentano raccomandando però di leggere
attentamente il commento che il compilatore scrive
a fianco dell'errore rilevato.
3.9 Istruzioni di INPUT-OUTPUT .
Le istruzione di input-output, di cui abbiamo
visto un esempio, nella nostra introduzione, sono
molto importanti in quanto costituiscono lo strumento
con cui il programma comunica con il mondo esterno.
Questa comunicazione avviene sia quando il programma
richiede ( input) dati per l'elaborazione
sia per comunicare i risultati della sua elaborazione
( output).
Per le operazioni di input si possono invocare
i comandi:
read
accept (preferibile non usare)
mentre per quelle di output i comandi:
write
print
type (preferibile non usare)
Questi comandi devono essere specificatiattraverso
due campi di opzioni; il primo contiene le opzioni
di controllo mentre l'altro conterrà la lista per
l'i/o. La lista di i/o contiene chiaramente la lista
delle variabili che il programma deve eleaborare o
che ha elaborato ed il cui valore deve essere comunicato
all'utilizzatore esterno. La lista di controllo da
uno o più parametriche specificano:
- unità logica su cui devono agire
- file interno su cui devono operare
- se i dati da leggere o da scrivere devono essere
formattati (cioè se su questi si devono fare delle
operazioni di editing)
- il numero di una istruzione a cui devono fare
riferimento nel caso in cui un errore od un end
of data intervenga durante la fase di i/o.
Una struttura tipica che interviene nei programmi
che devono richiedere dei dati in input è
per esempio:
print *, ' Enter zmin,zmax,dz (*)'
read *, z1,z2,dz
Con queste istruzioni il calcolatore richiede i dati
scrivendo sullo schermo ( STANDAR_DINPUT):
Enter zmin,zmax,dz (*)
e quindi posizionando il cursore sul primo carattere
della linea successiva apetta che voi scriviate i valori
dei parametri richiesti. In questo particolare esempio
l'asterisco ( *) ricorda che questi dati devono
essere entrati in free format cioè i tre numeri
devono essere separati o da una virgola (,) o da una
spazio (blank). In queste due istruzioni la lista di
controllo è costituita semplicemente dall' asterisco
( *) intendendo con questo che si vogliono
usare i default del FORTRAN stesso,
cioè che l'input/output avvenga attraverso l'unit'a
logica 5/6 ( STANDARD_INPUT/OUTPUT e che i
dati devono essere dati in free-format.
Senza ricorrere ai valori di default le istruzioni
precedenti posso riscriversi:
write(6,98)
read(5,99)z1,z2,dz
98 format(' Enter zmin,zmax,dz[3f10.4]')
99 format(3f10.4)
oppure
write(6,'(a)') 'Enter zmin,zmax,dz'
read(5,'(3f10.4)')z1,z2,dz
Si osservi che in questo caso i dati devono essere
inseriti rispettando le regole di editing come specificato
dalle istruzioni format. In questo caso per
i dati (sono in foating-point, cioè numeri reali)
si sono riservati 3 campi di dieci (10) caratteri
di cui gli ultimi quattro (4) per le cifre significative
dopo la virgola.
Come altro esempio supponiamo di dover leggere una
serie di dati (sia per esempio la tabulazione di una
funzione) che sono contenuti in un file di nome mydata.dat.
Le seguenti istruzioni servono allo scopo:
dimension x(50),y(50)
character*50 filename
100 continue
print *,' Enter name of the file with da data'
read(*,'(a)',err=100) filename
c
open(unit=20,file=filename,status='old',err=100)
c
do n=1,1000
read (20,*,end=110,err=100) x(n),y(n)
enddo
110 continue
close 20
npoint=n-1
.....................
stop
end
si noti che la lista di controllo nella istruzione read
contiene due campi aggiuntivi che permettono l'uno di
gestire l'errore passando il controllo alla istruzione
con label 100, l'altro di gestire l' end_
of_ file passando il controllo alla istruzione
con label 110 e quindi interrompe la sequenza
del do-loop. Si noti che con questo metodo
siamo in grado dideterminare il numero di punti in cui
la funzione è definita.
Qui di seguito vediamo tre modi equivalenti per ottenere
lo stesso scopo in fase di scrittura, cioè l'
output dei valori della due variabili a
e b.
Esempio 1.
.......................
write(6,97) ' dr =',a,'R =',b
97 format(a,1f5.2,2x,a,1f8.2)
........................
Esempio 2.
........................
write(6,'(a,1f5.2,2x,a,1f8.2)')' dr =',a,'R =',b
........................
Esempio 3.
........................
print '(a,1f5.2,2x,a,1f8.2)',' dr =',a,'R =',b
........................
se a=0.25 e b=10.18 si ottiene il seguente risultato:
dr = 0.25 R = 10.18
Mi pare ovvio rimandare una più approfondita esposizione
dei vari metodi di input/output durante la
stesura dei programmi veri e proprii e di consigliarvi
la lettura delle approppriate pagine dei manuali.
4. UNA LISTA DI PROGRAMMI MOLTO SEMPLICI.
Quì di seguito una lista di semplicissimi programmi
iniziali che sono commentati durante le lezioni che
servono per famigliarizzarvi con il linguaggio. Nella
loro stesusa si è anche cercato di completare alcune
informazioni sul FORTRAN stesso
4.1 Una farfalla da aggiungere alla collezione
implicit real*8(a-h,o-z)
print *, ' enter number of point, number of turn'
read *, npoint, nturn
pi=2.d0*acos(0.d0)
dth=2.d0*pi*dfloat(nturn)/dfloat(npoint)
call ginit
th0=0.d0
call window(-4.d0,-3.d0,4.d0,4.d0)
do i=0,npoint-1
th=th0+dth*dfloat(i)
r=exp(cos(th))-2.d0*cos(4.d0*th)+sin(th/12.d0)**5
x1=r*cos(th+pi/2.d0)
y1=r*sin(th+pi/2.d0)
c
th=th0+dth*float(i+1)
r=exp(cos(th))-2.d0*cos(4.d0*th)+sin(th/12.d0)**5
x2=r*cos(th+pi/2.d0)
y2=r*sin(th+pi/2.d0)
c
call line(x1,y1,x2,y2)
enddo
c
c si puo' fare di meglio provateci
c
call gend
c
stop
end
4.2 Un bel tappeto caotico
include 'fgraph.fi'
include 'fgraph.fd'
record /videoconfig/ vc
record /xycoord/ xy
integer*2 dummy,xt(4),yt(4),x0,y0,xmedio,ymedio
data xt/ 320,590, 50,320/
data yt/ 5,450,450, 5/
c
print *, ' enter number off calls'
read *,ncalls
call getvideoconfig (vc)
if(vc.adapter.eq.$vga) idummy=setvideomode($vres2color)
c
c inizializza lo schermo grafico
call getvideoconfig (vc)
c
c disegna il triangolo
call moveto(xt(1),yt(1),xy)
do i=2,4
dummy=lineto(xt(i),yt(i))
enddo
c
x0= 0 ! starting point
y0= 0 ! starting point
do n=1,ncalls
call random(ran)
ip=3.*ran+1
xmedio=(x0+xt(ip))/2.
ymedio=(y0+yt(ip))/2.
call moveto(xmedio,ymedio,xy)
dummy=lineto(xmedio,ymedio)
x0=xmedio
y0=ymedio
enddo
if (ncalls.gt.49999) then
call settextposition(2,2,xy)
call outtext(' The CAOS game')
call settextposition(3,2,xy)
call outtext(' Sierpinski gasket')
else
call settextposition(2,2,xy)
call outtext(' End Iteration')
endif
read (*,*)
c
idummy=setvideomode($defaultmode)
c
stop
end
4.3 Algoritmo di Euclide.
c program euclid.for
c
c this program implements the Euclid algorithm to calculate the MCD
c between two integer number (m,n).
c
integer*4 n,m,r ! (1)
c
print *,' scrivi n,m (*)'
read *,n,m
if(m.eq.n) stop 'm=n'
do i=1,100
r=n-(n/m)*m ! (2)
if(r.eq.0)then
print '(a,1i5)',' Massimo Comun Divisore (MCD) ', m
goto 101
else
n=m
m=r
endif
enddo
print *,' passi: troppo pochi' ! (3)
101 continue
stop
end
c
c (1) questa istruzione serve per dichiarare al compilatore che
c tutte le variabili in questa lista devono essere considerate
c come variabili integer*4 (cioe' 32 bit).
c
c (2) E' piu' conveniente richiamare la funzione del Fortran
c MOD(m,n)
c Questa funzione calcola i modulo di m in base n
c cioe' ritorna come valore il resto del divisione di m per n,
c in formula mod(n,m)=n-(n/m)*m.
c
c (4) questa scritta comparira' qualora il programma faccia piu' di
c 100 iterazioni senza arrivare al risultato. Chiaramente quando
c questa evenienza si verifica il programmatore deve essere avvisato
c affinche modifichi il do-loop.
4.4 Ancora algoritmo di Euclide
c program euclid1.for
c
c this program implements the Euclid algorithm to calculate the MCD
c between two integer number (m,n).
c
integer*4 n,m,r
c
print *,' scrivi n,m (*)'
read *,n,m
r=421616
do while(r.ne.0)
r=mod(m,n)
print *,r
m=n
n=r
enddo
print '(a,1i5)',' Massimo Comun Divisore (MCD) ', m
c
stop
end
4.5 Rappresentazione di un numero reale
in base binaria
c program chbf
c this program transforms the real number fnum in base 10
c in its rapresentation in base 2.
c
implicit real*8(a-h,o-z) ! (1)
dimension ires(100),kres(100)
c
c input the number and set to zero's ires
nba=2
100 continue
print *,' Enter number (*), ctrl_z to exit'
read (*,*,end=101) fnum
n1=int(fnum)
dec=fnum-float(n1)
c
c zeros ires (integer part) kres (decimal part)
do n=1,100
ires(n)=0
kres(n)=0
enddo
c
c change of base starts for the integer part
do n=1,100
n2=n1/nba
ires(n)=n1-n2*nba
n1=n2
if(n1.eq.0) goto 90
enddo
90 continue
ndint=n
c
c printing of the result for the real part only
iaux=ndint/8
if((8*iaux).lt.n)then
nmax=8*(ndint/8+1)
else
nmax=iaux*8
endif
print *,' Integer part'
print '(1x,4(8i1,1x))',(ires(n),n=nmax,1,-1) ! (2)
if(dec.eq.0.) goto 100
c
c change of base starts for the decimal part
nbit=48
x=dec
do n=1,nbit
aux=0.5**n
dif=x-aux
if(dif.ge.0.) then
kres(n)=1
x=dif
else
kres(n)=0
endif
enddo
c
c Printing the resuls for the dec part
print *,' Decimal part'
print '(1x,6(8i1,1x))',(kres(n),n=1,nbit) ! (2)
goto 100
c
101 continue
c
end
c
c----------------------------------------------------------------------
c
c Note al programma CHBF.FOR
c
c (1) Con questa istruzione implicir real*8 si dichiarano in doppia
c precisione (cioe' di 64 bit) tutte le variabili che iniziano
c per una qualsiasi lette dalla a alla h e dall o all z.
c Le variabili che iniziano per i,j,k,l,m ed n non sono modificate
c dalla dichiarazione per cui per esse valgolo i valori di defaults
c del FORTRAN cioe' sono variabili intere.
c
c (2) Si noti cove viene richiesta la stampa di tutte le componeti del
c vettore ires(i) (oppure kres(i))
|