Tècniques Computacionals, Curs 2007-2008. Pedro Salvador
4
1.- Programació en FORTRAN
1.1- Ordinadors, llenguatges d'alt nivell, compiladors
Els ordinadors digitals
Les aplicacions principals d’un ordinador podríem dir que són dues:
• Càlcul numèric
• Emmagatzematge, processament i anàlisi de dades.
En l’actualitat existeixen infinitat d’aplicacions (software) que permeten realitzar
tasques específiques com processament de textos, edició d’imatges, bases de dades, o
fins i tot programes de càlcul simbòlic matemàtic com el Mathematica o Maple.
Nosaltres ens dedicarem més aviat a les aplicacions de càlcul numèric i, en concret, a la
programació en el llenguatge FORTRAN. Els avantatges que comporta tenir uns
coneixements de programació en son vàries:
• Permet resoldre problemes específics que potser no serien resolubles amb el
software standard de què es disposi.
• S’elimina la dependència del software comercial i potencialment costós, a més
d’haver d’adaptar-se a les successives revisions i versions.
• Amb la programació es fomenta el desenvolupament intel·lectual, el pensament
lògic i estructurat. De fet, difícilment es pot programar un mètode o algorisme que
no s’entengui prèviament. Per tant, si fer un programa per realitzar una tasca podem
estar segurs que haurem entès com es fan les coses.
El FORTRAN (FORmula TRANslator) és un dels llenguatges de programació d’alt
nivell més utilitzats en l’actualitat en l’àmbit científic i tècnic, juntament amb el C.
L’avantatge del FORTRAN respecte al C, és que és relativament més senzill
d’aprendre. Pels objectius d’aquest curs, el FORTRAN es més que suficient.
Tècniques Computacionals, Curs 2007-2008. Pedro Salvador
5
Una de les característiques dels ordinadors actuals és la representació binària de la
informació. Internament, l’ordinador està composat de commutadors que poden tenir
posició oberta o tancada, i serveixen per representar els nombres 0 i 1. Per tant, dos és
la base natural de representació dels nombres en l’entorn informàtic. És a dir, mentre
que en base deu representem el nombre 113 com
113 = 1(102) + 1(101)+ 3(100)
en base dos tindríem
113 = 1(26)+ 1(25)+ 1(24)+ 0(23)+ 0(22)+ 0(21)+ 1(20) = 64 + 32 + 16 +1 = (1110001)2
Val a dir que també es poden representar de la mateixa manera altres tipus de dades,
com per exemple lletres (caràcters alfanumèrics) , simplement assignant-ne un valor a
cada lletra de l’abecedari.
Cada unitat d’informació binària rep el nom de bit. Normalment els bits s’agrupen en
blocs de 8 unitats formant un byte. Les dades que s’emmagatzemen i amb les que
treballarem a l’ordinador poden ser de 1 fins a 16 bytes, segons el tipus.
Per exemple, en FORTRAN el nombres sencers (integer) es representen per defecte
amb 4 bytes (o 32 bits). Això vol dir que amb aquest tipus de dades poden representar
nombres en el rang +231 -231 (cal un bit per especificar el signe).
Pels caràcters alfanumèrics només ens caldrà un byte, amb el que podem codificar 28 =
256 caràcters diferents.
La memòria principal d’un ordinador està formada per milions de circuits integrats
capaços emmagatzemar zeros o uns. Hi ha dos valors associats a cada element de la
memòria: la dada que conté i la direcció de la mateixa que ens permet accedir a la
mateixa.
El temps d’accés a la dada es un paràmetre molt important en la informàtica actual. De
fet, un suma es fa en menys temps que es triga en trobar els sumands a la memòria. En
les memòries RAM, el temps d’accés es independent de la posició que ocupa l’element
(random access memory).
Els PC’s actuals tenen també l’anomenada memòria cache, situada físicament a prop del
Tècniques Computacionals, Curs 2007-2008. Pedro Salvador
6
processador on es realitzen les operacions, que té un temps d’accés molt mes curt que la
memòria RAM i on s’emmagatzemen les dades més recentment accedides a la memòria
principal. Aquesta memòria ultraràpida és molt petita (típicament 256-1024 Kb). Una
bona estratègia de programació avançada és aconseguir que les dades estiguin el major
temps possible a la memòria cache.
A més de la memòria principal, hi ha altres llocs on s’emmagatzema la informació de
manera permanent però a canvi d’un temps d’accés superior. Són els dispositius de
memòria massiva o secundaria (discs durs, CD-ROM, DVD, diskettes, pen drives,
etc...). Per tant, un altra estratègia de programació eficient és la d’accedir el mínim
numero de vegades possible al disc dur (treballant sempre en memòria RAM o bé
llegint les dades necessàries en grans blocs).
En la comunicació amb l’ordinador cal tenir presents el dispositius d’entrada i sortida
(Input/output devices). Com a dispositius d’entrada tenim el teclat i les memòries
massives (disk dur, etc...), i són les vies per les quals li entrem les dades a l’ordinador.
Pel que fa a la sortida, tenim la pantalla, la impressora i les mateixes memòries
massives.
A l’hora d’escollir un dispositiu o un altre cal tenir en compte l’ús que en fem de la
informació. Per exemple, moltes vegades els nostres programes tindran unes opcions
típiques que ens pot interessar no introduir mitjançant el teclat cada vegada que
l’executem sinó que poden ser llegides d’un fitxer creat prèviament.
De la mateix manera, ens pot interessar guardar de manera permanent la sortida del
programa (output), per exemple per fer-la servir com a entrada (input) d’un altre
programa. En aquest cas convé, doncs, fer servir el disc dur com a dispositiu de sortida.
Per últim comentarem com li comuniquem a l’ordinador què volem fer. De fet, el
llenguatge primari de l’ordinador consta d’instruccions del tipus:
• Porta el numero X de la direcció de memòria Y
• Emmagatzemar-lo a la CPU
• Suma dos nombres
Tècniques Computacionals, Curs 2007-2008. Pedro Salvador
7
Aquest llenguatge màquina (ensamblador, assembler), però, no resulta gaire útil per
l’usuari. Els anomenats llenguatges d’alt nivell el que permeten es codificar de manera
més “humana” les instruccions, de manera que siguin, a més, independent de la màquina
on es treballi. El conjunt d’instruccions escrites en aquest llenguatge rep el nom de codi
font.
El programa que realitza la traducció a llenguatge màquina és el compilador, i el
resultat de la traducció es codi objecte. Per últim, el procés de creació del fitxer
executable final rep el nom de link i el duu a terme, generalment, el propi compilador
després de la compilació (exitosa).
Tant el codi objecte com el programa executable final depenen de l’arquitectura de
l’ordinador de treball (i per tant només podrà executar-se en aquell tipus de màquina i
sistema operatiu) mentre que només el codi font és universal.
FORTRAN
En l’actualitat existeixen vàries revisions del llenguatge FORTRAN original:
FORTRAN 77, FORTRAN 90 i FORTRAN 95. Les versions 90 i 95 es poden
considerar, de fet, com ampliacions del FORTRAN 77, pel què la pràctica totalitat de
les instruccions de FORTRAN 77 estan incloses en les versions posteriors.
Per tant, tot i que farem servir el compilador de FORTRAN 95, ens limitarem a fer
servir instruccions de FORTRAN 77. De fet, l’actualització dels programes científics
existents a versions posteriors és pràcticament inexistent avui en dia. A més, existeixen
compiladors de FORTRAN77 gratuïts pel sistema operatiu Linux (GNU g77).
Bibliografia
Programación en FORTRAN77, G. J. Borse, Ed. Anaya 1989.
Tècniques Computacionals, Curs 2007-2008. Pedro Salvador
8
1.2- Fonaments del FORTRAN 77
A l’hora d’elaborar el codi font en FORTRAN77 hi ha una sèrie de pautes que cal
seguir:
• Les instruccions o expressions (sentencies) s’escriuen en línies independents,
de tal manera que les instruccions s’executen seqüencialment (una darrera de
l’altra).
• El compilador ignora les línies en blanc
• Cada línia té una amplada màxima de 80 caràcters.
• Les instruccions han de situar-se entre les columnes 7 i 72 de cada línia.
• Les columnes 1 a 5 estan reservades per etiquetar les sentencies amb
números (opcional).
• La columna 6 és de continuació. Si una sentencia és massa llarga es pot
continuar a la següent línia (a partir de la columna 7) escrivint un caràcter
diferent del 0 en la columna 6 (típicament es fa servir “+” o “1”, “2”, etc...)
• Qualsevol línia que contingui a la columna 1 el caràcter “C” o bé “*” es
considera comentari i el compilador l’ignora. És molt important incloure
comentaris en el codi font per tal de millorar la seva comprensió
posterior!
Tot programa escrit en FORTRAN comença per la sentència PROGRAM i termina amb
la sentència END (o END PROGRAM).
La comanda PROGRAM pot venir acompanyada d’una paraula, que dóna nom al
programa. És important recalcar que aquest nom no te res a veure amb el nom del fitxer
que conté el codi font o el nom del fitxer executable final.
Tècniques Computacionals, Curs 2007-2008. Pedro Salvador
9
Tipus de dades
El FORTRAN ofereix una certa varietat en la referència i emmagatzematge de dades.
En concret n’hi ha de cinc tipus: INTEGER, REAL, COMPLEX, CHARACTER i
LOGICAL que serveixen per codificar nombres enter, decimals (o de coma flotant) i
complexes, caràcters alfanumèrics i expressions booleanes (vertader o fals).
Per defecte les variables de tipus INTEGER, REAL i COMPLEX ocupen 4 bytes,
mentre que les LOGICAL i CHARACTER n’ocupen 1 byte.
Molt sovint es treballa amb dades de tipus DOUBLE PRECISION, que de fet son
variables de tipus REAL però de 8 bytes. De fet, REAL*8 és un sinònim de DOUBLE
PRECISION. Això és així perquè amb dades de tipus REAL de 4 bytes podem
emmagatzemar números decimals dins el rang 10-38 – 1038 amb 8 dígits de precisió. En
canvi, amb les DOUBLE PRECISION s’arriba fins a un rang de 10-308.- 10308. amb 16
xifres significatives.
Les dades que s’utilitzen en el programa poden ser constants o variables i han de tenir
un nom. Les constants designen un valor específic que cal introduir i que no canvia al
llarg del mateix. Pera altra banda, el concepte de variable coincideix amb l’habitual, és a
dir, un nom simbòlic que fa referència a una dada que pot prendre diferents valors. Hi
ha algunes restriccions al respecte de quins noms es poden assignar a les variables o
constants:
• Han de començar per un caràcter alfanumèric (una lletra).
• No poden contenir caràcters especials (accents, signes, asterisc, etc..).
• És convenient, tot i que no obligatori, denominar les variables o constants amb
noms que recordin al concepte que representen.
Quan s’escriu un programa en FORTRAN77 s’utilitzen sentencies d’especificació o
declaració on s’explicita quin tipus de dades es faran servir al programa. Aquestes
sentencies s’inclouen en el codi font just després de la sentència PROGRAM.
Les constants es declaren i especifiquen a la vegada mitjançant la sentència parameter
de tal manera que amb l’expressió
parameter (MAXDIM=100, PI = 3.1415926)
estem dient al programa que hem definit dues dades constants amb els noms MAXDIM i
Tècniques Computacionals, Curs 2007-2008. Pedro Salvador
10
PI , el valor de les quals queda fixat i no es pot modificar posteriorment.
En el cas de les variables cal tenir en compte el següent:
• Per defecte, totes les variables el nom de les quals comenci per les lletres
i, j, k, l, m, n seran considerades com INTEGER. La resta seran de tipus
REAL.
• Els casos per defecte es poden modificar amb la sentència implicit. Per
exemple, la sentència següent (desprès de la sentència program):
implicit double precision (a-h,o-z)
fa que es conservi que les variables que comencin per les lletres i fins n siguin
considerades INTEGER però aquelles que comencin per les lletres a fins h i o
fins z seran reals de doble precisió (8 bytes)
• Es pot assignar de forma explícita un o més variables. Per exemple, amb les
sentències
real x,y,z
integer dia,mes, any
character linia*80, nom*20
declarem que les variables x, y ,z seran considerades dins el programa de
tipus REAL; les variables dia, mes, any seran de tipus INTEGER; les
variables línia i nom seran de tipus CHARACTER amb longitud 80 i 20
caràcters, respectivament.
• Les sentències anteriors s’inclouen en el programa després de la
sentencia program.
• La declaració explicita del tipus de les variables no és obligatori. Si no
s‘especifica res, el compilador considera el cas per defecte comentat
anteriorment. Això, de fet, implica que les variables de tipus CHARACTER
o LOGICAL s’hagin de declarar sempre
• Amb les sentències de declaració no s’assigna cap valor a les variables,
només es dona un nom determinat a una posició física de la memòria on
s’emmagatzemarà el valor de la variable.
En els exemples següents assumirem que les variables són del tipus determinat per
l’opció per defecte.
Tècniques Computacionals, Curs 2007-2008. Pedro Salvador
11
Input/output standard
Les comandes input/output standard en FORTRAN són
• read(*,*) llista de variables entre comes
• write(*,*) llista de variables o cadenes de caràcters entre comes
(Una cadena de caràcters és un conjunt de caràcters entre cometes o apòstrofs. )
Per exemple:
Sentència Resultat
read(*,*) x llegeix del teclat un nombres real
read(*,*) i, j llegeix del teclat dos nombres sencers
write(*,*) x, i escriu per pantalla un nombre real seguit
d’un nombre sencer
write(*,*) ‘El producte x*y = ‘,x*y
escriu per pantalla literalment
El producte x*y = , seguit del resultat del
producte
Quan el programa arriba a una sentència d’input/output es transfereix el control als
dispositius d’input/output. Per exemple, quan s’arriba a un sentència com
read(*,*) x
el programa espera que l’usuari introdueixi mitjançant el teclat (dispositiu d’input
standard) una dada (real, en aquest cas). Les dades s’introdueixen simplement escrivint
el número seguit de INTRO. Quan la sentència read inclou més d’una variable entre
comes, els valors es poden introduir durant l’execució del programa bé entre comes o
bé un a un prement INTRO cada cop.
Per altra banda, quan s’ arriba a una sentència com
write(*,*) x
el programa escriu per pantalla (dispositiu d’output standard) el valor que tingui
assignat en aquell precís moment la variable x
Més endavant veurem com es pot controlar el format de input/output dels nombres i
caràcters alfanumèrics mitjançant les sentències de format (format). També veurem
com definir altres dispositius d’input/output diferents als standard, i en concret, com
escriure i llegir de fitxers als discs locals.
Tècniques Computacionals, Curs 2007-2008. Pedro Salvador
12
Assignació
De fet, el procés d’assignació en FORTRAN ja ho hem anat veient. Bàsicament, hi ha
dues maneres d’assignar un valor a una variable
• Externament, mitjançant la comanda read : Per exemple, amb la sentència
read(*,*) x
aconseguim assignar-li a la variable x un valor mitjançant el teclat
• Per assignació directa. Per exemple, amb la sentència
y = 3.0d0*x +4.0d0
li assignem a la variable y el resultat de multiplicar el valor de la variable x
per tres i sumar-li quatre.
En aquest cas d’assignació directa cal tenir en compte alguns punts:
• Si fem servir una variable a la que no se li ha assignat cap valor, el resultat
por ser qualsevol. Per exemple, si fem
y = 3.0d0*x +4.0d0
sense haver donat cap valor a x, el resultat que es guardarà a y pot ser
qualsevol (tot i això molts compiladors assignen per defecte el valor 0 a totes
les variables).
• Expressions del tipus
y = 3.0d0
y = 3.0d0*y +4.0d0
son perfectament vàlides. De fet estem dient que y inicialment conté el valor
3 i, posteriorment, s’hi emmagatzema el resultat de multiplicar el valor
anterior de y per 3.0 i sumar-li 4.0. Recordeu que son sentencies
d’assignació! No implica igualtat.
Exemple: Escriu un programa que intercanviï el valor de dues variables. És a dir,
que si inicialment i=3 i j =2, al final tinguem i=2 i j = 3.
• El valor que quedi emmagatzemat a la variable depèn del tipus de variable.
Per exemple si fem
i = 4.0d0/3.2d0
Tècniques Computacionals, Curs 2007-2008. Pedro Salvador
13
a la variable INTEGER i s’hi emmagatzemarà el valor 1
x= 1/2
a la variable REAL x i s’hi emmagatzemarà el valor 0.0
Operacions aritmètiques
Els operadors aritmètics típics són els següents
+ suma
- resta
* multiplicació
/ divisió
** potència
Els operands poden ser números, constants o variables, sempre i quan siguin del tipus
escaient. Cal tenir en compte que:
• El resultat de les operacions on intervenen nombres sencers (INTEGER) és un
nombre sencer. Així, per exemple, 10/3 = 3, mentre que 10.0d0/3 = 3.33333...
• La barreja de variables o nombres de diferents tipus en una mateixa operació es
potencialment perillosa. Per exemple1
Expressió Resultat
a = 10/3 a = 3.000000
b = 10.0d0/3 b = 3.3333332
c = 10.0d0/3.0d0 c = 3.33333333
i = 10/3 i = 3
j = 10.0d0/3.0d0 j = 3
Comparant els valors a b i c es pot veure com es pot perdre precisió. Si escrivim 10.0d0
estem indicant que el número és de doble precisió (a diferència de 10.0 o 10.0e0).
Podem veure també que si la variable on s’assigna el resultat es de tipus INTEGER el
valor que emmagatzema serà sempre de tipus enter.
1 D’ara endavant suposarem que s’han definit variables reals de doble precisió.
Tècniques Computacionals, Curs 2007-2008. Pedro Salvador
14
A les variables de tipus CHARACTER també se’ls pot assignar valors. Per exemple, si
fem
character nom*10, cognom*10, tot*30
nom = ‘Armando’
cognom = ‘Bronca’
assignem a les variables nom i cognom valors alfanumèrics.
L’operació que es pot fer amb aquest tipus de dades es la concatenació. amb l’operador
“//”
tot =nom//cognom//”Segura”
Així, a la variable tot tindrem assignat
Armando___Bronca____Segura____
• Si l’expressió és més llarga que la variable, aquesta es trunca a la mida
necessària
• Si l’expressió és mes curta que la variable s’afegeixen espais en blanc fins
arribar a la mida declarada de la variable
Tècniques Computacionals, Curs 2007-2008. Pedro Salvador
15
1.3 Instruccions de execució condicional
L’ordinador, a més de realitzar operacions aritmètiques és capaç de fer comparacions i
executar determinades instruccions en funció del resultat. Per realitzar les comparacions
s’utilitzen expressions o sentències lògiques acompanyades dels corresponents
operadors lògics. Veiem primer aquests últims:
Operador lògic Significat
.EQ. igual a
.NE. diferent de
.LT. més petit que
.LE. més petit o igual que
.GT. més gran que
.GE. més gran o igual que
.AND. i lògic
.OR. o lògic
.NOT. negació lògica
És important tenir en compte que els punts formen part de l’operador lògic.
La sentència if , una de les estructures de control clau, es la que permet realitzar les
comparacions. Veiem com funciona:
El cas més senzill seria la sentència
if (expressió_lògica) sentència1
En aquest cas, s’avalua l’expressio_logica i si es vertadera s’executa la sentència1.
Per exemple, amb la sentència
if(x.LT.0.0) x = -x
si el valor de la variable x és negatiu li canviem el signe (obtenim el valor absolut). De
fet, ja hem vist que la funció intrinseca abs( ) faria també aquesta feina.
Tècniques Computacionals, Curs 2007-2008. Pedro Salvador
16
Si volem incloure més d’una instrucció dins el bloc if llavors hem de fer
if (expressió_lògica) then
sentència1
sentència2
...
end if
Per altra banda, també podem dirigir l’execució del programa en funció del resultat de
l’expressió lògica (i no només realitzar una sèrie d’instruccions només en cas que sigui
vertadera, com fins ara). Veiem-ho:
if (expressió_lògica) then
sentència1
...
else
sentència2
...
end if
En aquest cas, si l’expressió lògica es vertadera s’executa la sentència1 i de més
sentències escrites abans de la paraula else. En cas que hagués estat falsa, l’execució
del programa salta a la sentència immediatament posterior a else i posteriors fins end if.
Per exemple:
if (x.GT.-3.0.AND.x.LE.10.0) then
write(*,*) ‘El nombre esta dins l’interval (–3 , 10]
else
write(*,*) ‘El nombre esta fora de l’interval (–3 , 10]
end if
Tècniques Computacionals, Curs 2007-2008. Pedro Salvador
17
Per últim, es poden incloure dins la sentència if més d’una opció, mitjançant altres
expressions lògiques:
if (expressió_lògica1) then
sentència/es 1
else if (expressió_lògica2) then
sentència/es 2
...
else if (expressió_lògica n) then
sentència/es n
else
sentència/es que s’executen cas que totes les expr. lògiques
anteriors siguin falses
...
end if
De tal manera que, per exemple, el bloc de sentències 2 només s’executarà si
l’expressió lògica 1 es FALSA i l’expressió lògica 2 és VERTADERA. Desprès
d’això el programa continuarà amb la sentència immediatament posterior a end if.
Fixeu-vos també que, tot i que no és cap obligació, les sentències que queden entre les
sentències pròpies de control (if..else...end if), s’indenten per millorar la comprensió
del programa.
Exemple: Fes un programa que trobi les solucions d’una equació de segon grau del tipus ax2 +
bx + c = 0. El programa hauria de distingir entre els possibles casos que es poden donar (no hi
ha solució real, una solució doble, dues solucions) i escriure’n el resultat en funció del cas.
Tècniques Computacionals, Curs 2007-2008. Pedro Salvador
18
1.4- Instruccions de execució repetitiva (bucles)
Els bucles son una de les tècniques de programació més utilitzades. Bàsicament
consisteixen en repetir un numero determinat (finit) o indeterminat (infinit) de vegades
les sentències que s’executen dins el propi bucle.
En FORTRAN existeixen dos tipus de instruccions per fer bucles, segons el numero de
vegades que es repeteixen sigui determinat o indeterminat (depenent d’una condició).
Res millor que un exemple. Veiem com funciona
do while(expressió_lògica) (1)
sentència 1
....
end do (2)
En aquest cas tenim un bucle on el nombre de vegades que es repeteix és indeterminat i
dependent de la condició lògica. Quan el programa entra en el bucle (1) avalua
l’expressió lògica. Si es vertadera, entra dins el bucle i executa les sentències fins
arribar al punt final del bucle (2). Si fos falsa no entraria en el bucle i el control del
programa tornaria a la sentència immediatament posterior al punt final del bucle (2).
Cas d’haver estat vertadera, el programa tornaria al començament del bucle (1) i
tornaria a avaluar l’expressió lògica. Si fos vertadera, entraria al bucle, etc...
Per exemple, el següent és un programa que suma els N primers nombres.
read(*,*) N
i=1
isuma=0
do while (i.LE.N)
isuma=isuma + i
i= i+1
end do
write(*,*) ‘La suma dels ‘,N, ‘ primers nombres enters es: ‘,isuma
Analitzem-ho. Primer es llegeix el nombre final N, de tipus INTEGER. Tot seguit
Tècniques Computacionals, Curs 2007-2008. Pedro Salvador
19
inicialitzen dues variables INTEGER (i, isuma). La variable i ens servirà de
comptador, mentre que a isuma n’acumularem el resultat final. Quan el control del
programa arriba a l’entrada del bucle, comprova si i és menor o igual que N. En cas
afirmatiu entra al bucle. A dins, el que fem es sumar el valor de i al total (isuma) i,
posteriorment, incrementar en una unitat el valor del comptador i. Quan s’arriba al final
del bucle (end do) el programa torna al principi a comprovar que i encara es menor o
igual que N.
És important incrementar la variable i dins el bucle perquè sinó tindríem un bucle
infinit i bàsicament podríem “penjar” l’ordinador.
Si, per exemple, haguéssim donat a N un valor de 7, el programa entraria fins a 7
vegades el bucle i aniria sumant a isuma els valors 1, 2,3 ..., fins a 7.
Valor de i Valor de isuma
1 1
2 3
3 6
4 10
5 15
6 21
7 28
Però, de fet, també podríem haver fet el programa utilitzant una estructura de bucle
determinat, ja que si N és 7 cal que el bucle es repeteixi exactament 7 vegades.
En aquest cas seria
read(*,*) N
do i=1,N
isuma=isuma+i
end do
write(*,*) ‘La suma dels ‘,N, ‘ primers nombres enteres es: ‘,isuma
Ara la sentència inicial del bucle té l’estructura
do comptador_INTEGER = valor_inicial, valor_final, (valor_pas)
No hi ha, doncs, expressió lògica. Quan el programa entra per primer cop al bucle li
Tècniques Computacionals, Curs 2007-2008. Pedro Salvador
20
assigna a la variable comptador_INTEGER el valor_incial (per tant, no hi ha necessitat
de inicialitzar-la com abans). Tot seguit s’entra dins el bucle i s’executen les sentències.
Quan s’arriba al final del bucle (end do) es torna a la sentència inicial i s’incrementa en
valor_pas2 el valor de la variable comptador _INTEGER. Aquest procés es repeteix fins
que la variable comptador _INTEGER prengui el valor_final o, en tot cas, no el superi.
És important no modificar el valor de la variable comptador_INTEGER dins
l’estructura del bucle. De fet, molts compiladors no ho permeten i donen error.
Els bucles també es poden aniuar. Per exemple, si volem generar els 99 primers
nombres inclòs el 0, podem fer
do i = 0,99
write(*,*) i
end do
o bé
do i=0,9
do j=0,9
write(*,*) 10*i + j
end do
end do
En aquest segon cas, inicialment la variables i prenen els valor 0 i entra en el bucle.
Llavors ens troben un altre bucle, on el valor inicial de j és 0 i va variant fins a 9, per a
cada valor possible de i. Per tant, la instrucció
write(*,*) 10*i + j
s’executarà un total de 9x9 = 81 vegades.
Fixeu-vos també que, de la mateixa manera que amb les sentències de control (if...end
if), les sentencies dintre de cada bucle es solen indentar per millorar la comprensió del
programa.
2 De fet, valor_pas és optatiu. Si no s’especifica assumeix que la variable incrementa en una unitat.
Tècniques Computacionals, Curs 2007-2008. Pedro Salvador
21
Finalment, també es poden simular els bucles mitjançant sentencies de decisió i de salt,
tipus go to. Veiem un exemple
read(*,*) N
isuma=0
i=1
1 if(i.LE.N) then
isuma=isuma+i
i=i+1
go to 1
end if
write(*,*) ‘La suma dels ‘,N, ‘ primers nombres enteres es: ‘,isuma
Aquest programa també realitza la suma dels N primers nombres enters. La repetició de
les sentències s’aconsegueix amb la sentència go to 1. El que fa és transferir el control
de l’execució a la línia etiquetada amb el numero 1.
De tota manera, és molt recomanable no utilitzar mai les sentencies de salt tipus go to.
La raó principal és que dificulten la comprensió del codi font.
Exemple: Un mètode per resoldre equacions no lineals és el de les substitucions successives. Si
tenim una equació del tipus f(x)=x , es dóna un valor inicial a x i es calcula la seva imatge f(x).
Si f(x)=x, vol dir que x és la solució. Cas contrari, s’utilitza el valor de f(x) com a nova
aproximació a la solució i s’itera fins que la diferència entre el valor de x i la seva imatge f(x)
sigui menor que un nombre suficientment petit (precisió). Fes un petit programa que trobi la
solució a l’equació ln(x)=x.
Tècniques Computacionals, Curs 2007-2008. Pedro Salvador
22
1.5- Altres dispositius Input/Output
Ens podem comunicar amb l’ordinador a traves d’altres dispositius a banda del teclat i
la pantalla. En concret, és molt freqüent fer servir fitxers per emmagatzemar les dades ,
tant d’entrada (input) com de sortida (output).
Això pot ser útil per introduir ràpidament gran quantitat d’informació al programa (una
matriu, per exemple) o per emmagatzemar els resultats directament per posteriors
aplicacions.
En FORTRAN l comanda open ens serveix per obrir un fitxer. La sintaxi bàsica és la
següent
open(nombre_INTEGER, file=cadena_CHARACTER)
on cadena_CHARACTER és el nom del fixer i nombre_INTEGER el número que se li
assignarà internament. Per exemple amb
open(1, file=”dades.dat”)
obrim un fitxer al directori de treball que es diu dades.dat, i internament li assignem el
nombre 1.
El nom del fitxer es pot introduïr també mitjançant una variable de tipus
CHARACTER. Per exemple aquest petit tros de codi
CHARACTER*20 nomfitxer
write(*,*) ‘Escriu el nom del fitxer que vols obrir/crear “
read(*,*) nomfitxer
open(1,file=nomfitxer)
ens demana (per pantalla) el nom del fitxer que volem obrir, el guarda en una variable
de tipus CHARACTER anomenada nomfitxer i finalment obre el fitxer amb el nom que
hem entrat (per teclat) , tot assignant-li la unitat 1.
Podem tenir accés a tants fitxers com vulguem, escrivint cada cop una sentència de tipus
open per cadascun.
Tècniques Computacionals, Curs 2007-2008. Pedro Salvador
23
Un cop tenim un fitxer obert (accessible) podem llegir dades que haguéssim
introduït anteriorment o bé escriure dades noves.
Per llegir dades existents al fitxer, fem servir al comanda read. Així,
read(1,*) N,x0
llegeix un nombre enter i un nombre real del fitxer que li hem assignat el nombre 1, és a
dir, en aquest cas dades.dat. És clar que al fitxer hauríem d’haver escrit prèviament els
valors de les variables per què els llegeixi el programa de la mateixa manera que ho
hauríem fet mitjançant el teclat.
Per tant, el fitxer dades.dat haurà de contenir, per exemple
10, 0.57d0
o bé
10
0.57d0
Si, per contra, el fitxer no existia prèviament (o el volem sobreescriure) i hi volem
escriure dades, faríem, per exemple
write(1,*)’Aquesta línia sortirà al començament del fitxer’
write(1,*)’Tot seguit escric un nombre sencer i un de real’, N,x0
Si obrim el fitxer dades.dat amb un editor simple com el Bloc de Notes del Windows hi
trobaríem el següent
Aquesta línia sortirà al començament del fitxer
Tot seguit escric un nombre sencer i un de real 10 0.57d0
És molt important tenir en compte que l’accés als fitxers és seqüencial.
És a dir, que per accedir a la línia n-sima d’un fitxer haurem d’haver llegit les n-1 línies
anteriors. Quan obrim un fitxer amb la comanda open, el programa esta preparat per
llegir/escriure de/a la primera línia del fitxer. Conforme anem llegint o escrivint anem
avançant línia a línia.
Un comanda que pot ser útil en algunes circumstàncies és rewind(nombre_fitxer), de
manera que si fem
Tècniques Computacionals, Curs 2007-2008. Pedro Salvador
24
rewind(1)
tornem al programa a la posició inicial del fitxer (primera línia).
Tot i que no és necessari pel correcte funcionament del programa, és recomanable
tancar el fitxer un cop hàgim escrit/llegit tota la informació amb la comanda
close(nombre_fitxer)
close(1)
Finalment, val a dir que les unitats 5 i 6 estan reservades per defecte i corresponen a
“teclat” i “pantalla”. Es a dir que
write(*,*) és equivalent a write(6,*) i
read(*,*) és equivalent a read(5,*)
Per exemple, per fer que el programa escrigui un llistat dels N primers nombres sencers
amb els corresponents quadrats en un fitxer podríem fer el següent
open(2,file=”llista.out”)
read(*,*) N
do i=1,N
write(2,*) i, i*i
end do
end
Es molt recomanable donar extensió típica diferent als fitxers que han de ser
essencialment d’input i d’ouput. Per exemple, els fitxers d’input es solen anomenar
*.in o *.dat , mentre que pels d’output es solen fer servir extensions del tipus *.out
o *.log.
Tècniques Computacionals, Curs 2007-2008. Pedro Salvador
25
1.6- Vectors i Matrius
En programació, un array o vector no és més que una manera ordenada
d’emmagatzemar un conjunt d’elements del mateix tipus sota un mateix nom. Aquests
elements, en FORTRAN 77 poden qualsevol dels tipus de variables que hem vist.
Per indicar en un programa que volem fer servir un array, primer de tot l’hem de
declarar amb una sentència DIMENSION. Com totes les sentencies de declaració, les
haurem de introduir sempre abans de les sentències d’execució. Veiem un exemple
DIMENSION a(10)
DIMENSION b(10,10), imat(10,15)
Amb la primera de les sentències anteriors hem declarat una variable array
monodimensional (vector) de dimensió 10 al què hem assignat el nom a. A la segona
hem declarat dos arrays bidimensionals (matrius) b i imat de dimensions 10x10 i 10x15,
respectivament.
A més, els elements del vector a i la matriu b seran variables de tipus REAL mentre que
la de la matriu imat seran de tipus INTEGER (perquè el nom comença per i, i sempre i
quan no hàgim sobreescrit les opcions per defecte).
És important entendre que, de nou, el fet de declarar no implica assignar cap valor als
elements dels vectors o matrius. Només n’informem al ordinador de la seva existència i,
en aquest cas, en fixem el nombre màxim d’elements per dimensió que en poden
emmagatzemar.
Per assignar valors als elements del vectors o matrius ho podem fem de la següent
manera amb sentències d’assignació:
a(1) = 2.0d0
read(*,*) b(2,3)
imat(1,15) = 2
En el primer cas emmagatzemem el valor 2.0d0 al primer element del vector a, al què es
fa referència com a a(1). En el segon accedim a l’element que es troba en la segona fila,
tercera columna i li assignem el valor que l’usuari entra externament mitjnaçat el teclat,
etc...
Tècniques Computacionals, Curs 2007-2008. Pedro Salvador
26
En FORTRAN 77, per assignar un valor a cada element d’un vector o una matriu s’ha
de fer element per element. Afortunadament, per això tenim els bucles. Per exemple, si
volem inicialitzar els elements del vector a a zero faríem simplement
do i=1,10
a(i) = 0.0d0
end do
Per entrar els elements de la matriu b externament mitjançat el teclat podríem fer
do i=1,10
do j=1,10
read(*,*) a(i,j)
end do
end do
Fixa’t que en aquest cas els elements de la matriu s’introdueixen un per un i per
columnes. Existeix una manera alternativa que permet llegir (i escriure) matrius de
manera semblant a com ho fem sobre el paper, introduint els valors filera per filera. Per
fer això cal escriure el següent.
do i=1,10
read(*,*) (a(i),i =1,10)
end do
i
do i=1,10
read(*,*) (a(i,j),j =1,10)
end do
En el primer cas entraríem els elements del vector un a un i entre comes. En el segon,
entraríem els elements d’una mateixa filera un a un i entre comes, i això per les 10
fileres de la matriu (començant per la primera).
i vectors.
A l’hora d’escriure la matriu per pantalla podem fer, de la mateixa manera
do i=1,10
write(*,*) (a(i,j),j =1,10)
end do
Tècniques Computacionals, Curs 2007-2008. Pedro Salvador
27
En FORTRAN podem definir hipermatrius de fins a 7 dimensions, tot i que rarament en
necessitarem més de dues i excepcionalment 3 o 4.
És també molt important veure que, de la mateixa manera que els elements de les
matrius s’introdueixen un a un, no es poden fer operacions directament amb les
matrius/vectors. És a dir, si volem sumar dues matrius A i B (que es puguin sumar) no
ho podem fer com
C = A +B
sinó que haurem de calcular els elements de la matriu resultant un per un. De nou, els
bucles faciliten molt la feina. Primer de tot, escrivim l’expressió corresponent a un
element qualsevol de la matriu suma
c(i,j) = a(i,j) + b(i,j)
Ara, assumint que les matrius anteriors A i B han estat declarades de dimensió 10x10, el
codi que ens permetria calcular la suma de les matrius seria simplement
do i=1,10
do j=1,10
c(i,j) = a(i,j) + b(i,j)
end do
end do
És a dir, escrivim l’expressió general i mitjançant els bucles que calguin ho estenem per
tots els valors possibles.
Val a dir, finalment, que la dimensió amb què és declarat un array representa només la
dimensió màxima de l’array. De fet, és pràctica habitual declarar un array de dimensió
suficientment gran per als nostres propòsits, generalment amb una constant
PARAMETER(MAXDIM=100)
DIMENSION A(MAXDIM,MAXDIM), B(MAXDIM,MAXDIM)
i després fer servir en realitat una dimensió més petita pels nostres càlculs
...
READ(*,*) N,M
do i=1,N
read(*,*) (A(i,j),j =1,M)
end do
....
Tècniques Computacionals, Curs 2007-2008. Pedro Salvador
28
El codi següent
DIMENSION A(N,M), B(N,M)
...
READ(*,*) N,M
do i=1,N
read(*,*) (A(i,j),j =1,M)
end do
....
no es possible en FORTRAN77 i donarà error. La raó és que, en el moment de
declarar les matrius A i B , les variables N i M no tenen assignat cap valor (i de cap
manera es pot escriure la sentència READ abans de les sentencies de declaració!).
Tècniques Computacionals, Curs 2007-2008. Pedro Salvador
29
1.7 Subprogrames: Funcions i Subrutines
El llenguatge FORTRAN té dos tipus de subprogrames: la subrutina i la funció externa.
L’objectiu és el de definir subprogrames o blocs que realitzin tasques específiques.
Aquests blocs realitzaran part del programa i poden ser utilitzat per a la construcció
d’un programa major o futur. Per tal que es pugui segmentar el programa cal
comunicació entre els diferents subprogrames. Aquesta comunicació es fa mitjançant els
paràmetres dels subprogrames. Les regles per passar la informació del programa
principal als subprogrames són les mateixes tant per les funcions com per les subrutines.
La principal diferencia entre una funció i una subrutina és que la primera torna al
programa principal, un valor emmagatzemat en el seu propi nom, mentre que la
subrutina ho fa a traves dels paràmetres.
Funcions
Una utilitat obvia de les funcions en FORTRAN és precisament la de definir funcions
matemàtiques complexes. De fet, el FORTRAN té una sèrie de funcions matemàtiques
bàsiques per defecte. Son les funcions intrínseques. Algunes d’aquestes son
Funció Resultat
sin(nombre_real); cos(nombre_real); tan(nombre_real)
sinus, cosinus o tangent d’un nombre real en radians
asin(nombre_real); acos(nombre_real); atan(nombre_real)
arcsinus, arcosinus o arctangent en radians
exp(nombre_real) Valor de e elevat a la potència indicada sqrt(nombre_real) Arrel quadrada d’un nombre real log(nombre_real) Logaritme neperià d’un nombre real
log10(nombre_real) Logaritme en base 10 d’un nombre real
abs(nombre_real_o_integer) Valor absolut d‘un nombre real o sencer
mod(sencer1,sencer2) Resta entera de la divisió entre sencer1 i sencer2
real(nombre_sencer) Equivalent real d’un nombre sencer
Quan l’argument de la funció sigui un nombre real de doble precisió (REAL*8,
DOUBLE PRECISION) s’afegeix una “d” al nom de la funció.
sin(0.56) dsin(0.56d0)
Tècniques Computacionals, Curs 2007-2008. Pedro Salvador
30
sqrt(37.8) dsqrt(4.0d0)
Tot i això alguns compiladors ajusten automàticament la precisió al tipus de dada que
s’utilitza com a argument sense necessitat d’afegir aquesta “d” extra.
Podem fer servir les funcions intrínseques en sentencies d’assignació o mostrar el
resultat directament
x = sin(3.0)
write(*,*) dsqrt(x)
Nosaltres podrem definir funcions (que poden ser matemàtiques o de qualsevol tipus) en
FORTRAN de manera que les puguem fer servir de manera anàloga a com s’utilitzen
les funcions intrinseques.
Per fer-ho hem de crear un subprograma de tipus funció. En aquest cas la nomenclatura
és la següent
function nom_funció (llista d’arguments)
declaració dels arguments
sentencies....
nom_funcio=expressió
end
És important tenir en compte que, com a subprograma, cal escriure la funció de manera
externa al programa principal. És a dir, normalment escriurem les funcions al final de
programa i sempre desprès de la sentencia end. (Fixeu-vos que al final de la
declaració de la funció també cal afegir la sentencia end).
Un cop definida la funció la podem fer servir dins el programa com una funció
intrínseca més. En aquest cas podríem fer
x = nom_funcio(llista d’arguments)
Tècniques Computacionals, Curs 2007-2008. Pedro Salvador
31
Veiem un exemple: Podríem definir la funció f(x) =2 e- 2x + sin(πx)
function y(x)
IMPLICIT DOUBLE PRECISION (a-h,o-z)
PARAMETER(PI=dacos(-1.0d0))
y = 2.0d0*exp(-2.0d0*x)-sin(PI*x)
end
(Fixa’t en la manera d’introduir el valor de π. Així s’aconsegueix el màxim de precisió)
i dintre del programa podem cridar a la funció amb sentencies del tipus
val = y(2.0)
read(*,*) x0
write(*,*) ‘El valor de la funció a x0 = ‘,x0, ‘es ‘,y(x0)
Exemple: Definirem una funció entera que comprovi si un nombre N1 es divisible per
un altre N2. Cas que si, la funció ha de prendre el valor 1 i 0 en cas contrari. En aquest
cas li hem de passar a la funció dos arguments (N1i N2) que seran dues variables de
tipus INTEGER. Ho podríem fer de la següent manera
FUNCTION idiv(N1,N2) ir = mod(N1,N2) IF(ir.EQ.0) then idiv=0 else idiv=1 end if end
Llavors el programa principal quedaria
PROGRAM check_division WRITE(*,*) ‘Entra dos nombres enters i et dire si son divisibles entre si’ READ(*,*) N1,N2 IF(idiv(N1,N2).EQ.1) then WRITE(*,*) N1,' i’ ,N2, ‘son divisibles’ else WRITE(*,*) N1,' i’ ,N2, ‘no son divisibles’ end if end
Tècniques Computacionals, Curs 2007-2008. Pedro Salvador
32
De fet, aquest programa no funcionarà en tots els casos. Es un exemple típic de
programa ben escrit però mal pensat.
Fixa’t que si N2 es més gran que N1 el programa dirà que els números son divisibles!
Per tant ens caldria afegir a la funció un filtre previ que comprovi que el divisor sigui
més petit que el dividend.
Per exemple
FUNCTION idiv(N1,N2) if(N1.gt.N2) then ir = mod(N1,N2) else ir = mod(N2,N1) end if IF(ir.EQ.0) then idiv=0 else idiv=1 end if end
En l’argot informàtic diem que ara la funció és més robusta.
De tota manera, ja que la funció en el fons ens ha de dir si o no, el més adient és definir-
la de tipus LOGICAL. La funció, amb una altra petita modificació podria quedar de la
següent manera.
LOGICAL FUNCTION idiv(N1,N2) idiv=.true. if(N1.gt.N2) then ir = mod(N1,N2) else ir = mod(N2,N1) end if IF(ir.EQ.0) idiv=.false. end
Fixeu-vos que la funció idiv és de tipus LOGICAL, de la mateixa manera que la versió
anterior era de tipus INTEGER. Per construir una funció que retorni un nombre
INTEGER només cal que el nom comenci per les lletres i-n.(sempre i quan no hàgim
sobreescrit les opcions per defecte). Si volem una funció de tipus LOGICAL ho hem de
expressar explícitament a l’hora de definir la funció (LOGICAL FUNCTION).
Tècniques Computacionals, Curs 2007-2008. Pedro Salvador
33
Cal anar en compte ara. Ja que la funció és de tipus lògic, el seu resultat s’ha d’assignar
o ha de aparèixer en un context de tipus LOGICAL també. Per tant, caldria modificar el
programa principal de la manera següent
PROGRAM check_division LOGICAL idiv WRITE(*,*) ‘Entra dos nombres enters i et dire si son divisibles entre si’ READ(*,*) N1,N2 IF(idiv(N1,N2).EQ..true.) then WRITE(*,*) N1,' i’ ,N2, ‘son divisibles’ else WRITE(*,*) N1,' i’ ,N2, ‘no son divisibles’ end if end
Per últim, es important veure que els noms de les variables que es passen com a
argument a la funció i al programa principal no tenen perquè coincidir i, de fet, no ho
solen fer. El que si ha de coincidir és el tipus de variable i l’ordre en que es passen els
arguments. Per tant, escriure la funció anterior com
LOGICAL FUNCTION idiv(K1,K2) idiv=.true. if(K1.gt.K2) then ir = mod(K1,K2) else ir = mod(K2,K1) end if IF(ir.EQ.0) idiv=.false. end
no afecta en absolut el funcionament del programa. Simplement, quan el control del
programa es passa a la funció, aquesta pren els valors emmagatzemats a les variables
N1 i N2, els guarda amb altres variables K1 i K2 per utilitzar-los posteriorment. Tot i
això, en FORTRAN, si a la funció es modifiquen els valors assignats a K1 o K2, aquests
canvis es veuran reflectits també a les variables N1 i N2 quan el control del programa
torni al programa principal.
Tècniques Computacionals, Curs 2007-2008. Pedro Salvador
34
Subrutines
Sovint, les operacions que cal fer son massa llargues o complexes per poder incloure-les
dins una funció3. Si decidim posar-les dins el programa principal podríem fer més difícil
el seguiment de l’estructura lògica del programa. Per exemple, si al mig d’un programa
haguéssim d’invertir una matriu seria més còmode dir-li al ordinador
Deixa per un moment el que estàs fent, inverteix aquesta matriu, i quan estiguis, torna
amb el que feies
Això precisament és el que fan les subrutines. És un programa independent que és cridat
dins el programa principal, i que realitza una feia concreta. Un cop terminada, es retorna
automàticament el control al programa principal. En aquest cas la sintaxi és la següent
subroutine nom_funció (llista d’arguments)
declaració dels arguments
sentencies....
end
És clar que, com a programa independent, necessita comunicar-se amb el programa
principal per a) disposar de les dades inicials necessàries (input) i b) passar-li al
programa principal les noves dades calculades (output). Aquestes variables d’input,
output i input-output4 s’especifiquen a la llista d’arguments. Noteu que aquestes
variables s’han de declarar, de la mateixa manera que es fa al programa principal. És a
dir que si la variable que passem es de tipus CHARACTER o una matriu, cal incloure
les respectives sentències CHARACTER i DIMENSION a la subrutina. De la mateixa
manera, per evitar sorpreses, si hem afegit al programa principal la sentència
implicit double precision(a-h,o-z)
el mateix hauríem de fer als subprogrames (tant de tipus funció com subrutina)
3 A més, podríem necessitar que el subprograma ens retornés més d’un únic valor (una matriu, per
exemple) i per tant la funció no ens serviria. 4 En aquest cas el valor de la variable d’input inicial es sobreescriu dins la subrutina i el seu valor
modificat es passa al programa principal
Tècniques Computacionals, Curs 2007-2008. Pedro Salvador
35
Crides a les subrutines
Per poder accedir a una subrutina dins un programa farem servir la sentència CALL. Per
exemple, si hem definit una subrutina determinada
subroutine fes_algo(llista_arguments)
la cridarem des de el programa principal fent
call fes_algo(llista_arguments)
Recordeu que a la subrutina li hem de passar el mateix tipus d’arguments (i en el
mateix ordre), però no tenen perquè tenir el mateix nom. A més, les variables que no
es passen com a arguments dins una subrutina no són visibles pel programa
principal i viceversa. Per tant, podem fer servir variables amb el mateix nom al
programa principal (tipicament i, j, k, etc per als bucles) i als subprogrames sense que
interfereixin.
Cal tenir en compte que l’ús de subrutines respon més a raons estètiques que
computacionals. Res impedeix fer un programa sense subrutines, tot i que sovint es
redueix la complexitat i longitud del codi. Per exemple, suposem que disposem d’una
subrutina que realitza el producte de dues matrius quadrades de dimensió N. La
subrutina es diu multmat i els seus arguments son la dimensió de les matrius (N), les
matrius a multiplicar (A,B) i la matriu on emmagatzemarem el resultat (C).
Les primeres linees de la declaració de la subrutina haurian de ser quelcom com
subroutine multmat(N,A,B,C)
implicit double precision(a-h,o-z)
parameter(maxdim=100)
dimension A(maxdim,maxdim),B(maxdim,maxdim),C(maxdim,maxdim)
Llavors, dins el programa prinicpal, la subrutina s’hauria de cridar de la manera següent
call multmat(N,A,B,C)
Podem veure la utilitat de definir subrutines si ens plantegem determinar la k-essima
potència d’una matriu (Ak). En aquesta cas el programa es podria escriure de la següent
manera
Tècniques Computacionals, Curs 2007-2008. Pedro Salvador
36
PROGRAM potencia PARAMETER(MAXDIM=100) DIMENSION A(MAXDIM),A2(MAXDIM), AK(MAXDIM) WRITE(*,*) ‘Entra les dimensions de la matriu quadrada :' READ(*,*) N WRITE(*,*) ‘Entra la matriu per files:' do i = 1,N READ(*,*) (A(i,j)=j=1,N) end do WRITE(*,*) Quina potència vols calcular?' READ(*,*) k do i=1,N do j=1,N a2(i,j)=a(i,j) !Copiem la matriu A a una matriu auxiliar end do end do do i=1,k-1 ! hem de realitzar k-1 productes... call multmat(N,A2,A,Ak) !fem Ak=A2xA do i=1,N do j=1,N a2(i,j)=ak(i,j) !Desprès de fer cada producte copiem end do !el resultat en la matriu auxiliar end do end do WRITE(*,*) ‘Resultat:' do i=1,N WRITE(*,*) (Ak(i,j)=j=1,N) end do end
És clar que no és el algorisme més eficient! Per altra banda, fixeu-vos que hi ha part de
codi repetida; el necessària per copiar una matriu en una altra. Per fer el codi més
llegible podríem fer una altra subrutina que fes aquesta feina.
SUBROUTINE copiamatriu(N,A,B) PARAMETER(MAXDIM=200) DIMENSION A(MAXDIM),B(MAXDIM) do i=1,N do j=1,N B(i,j)=A(i,j) !Copiem la matriu A a B end do end do end
Tècniques Computacionals, Curs 2007-2008. Pedro Salvador
37
i llavors al programa principal es podria fer
PROGRAM potencia PARAMETER(MAXDIM=200) DIMENSION A(MAXDIM),A2(MAXDIM), AK(MAXDIM) WRITE(*,*) ‘Entra les dimensions de la matriu quadrada :' READ(*,*) N WRITE(*,*) ‘Entra la matriu per files:' do i=1,N READ(*,*) (A(i,j)=j=1,N) end do WRITE(*,*) Quina potència vols calcular?' READ(*,*) k call copiamatriu(N,A,A2) do i=1,k-1 call multmat(N,A2,A,Ak) ! hem de realitzar k-1 productes... call copiamatriu(N,Ak,A2) end do WRITE(*,*) ‘Resultat:' do i=1,N WRITE(*,*) (Ak(i,j)=j=1,N) end do end
Totes dues versions fan el mateix però aquesta última queda més compacta i més fàcil
d’entendre.