Ulteriori elementi di base del linguaggio Fortran Paolo Bison
Fondamenti di Informatica Ingegneria Meccanica
Università di Padova A.A. 2008/09
Basic Fortran (cont.), Paolo Bison, FI08, 2008-09-29 – p.1
Real
sottoinsieme finito dei reali ℜ
operatori:
+ - * / **
costanti
sequenza di cifre in notazione decimale (3.5) o scientifica (-1.89E-5)
3.0 6= 3
rappresentazione finita
es.
real :: x,y=45.0,z x = y*z
Basic Fortran (cont.), Paolo Bison, FI08, 2008-09-29 – p.2
Funzioni
operandi nelle espressioni
R701 primary . ..
or function-reference. ..
R1210 function-reference
is function-name ( [ actual-arg-spec-list ] )
costituita da un identificatore seguito da una lista di espressioni tra parentesi tonde
funzioni matematiche sin(x*2)
max(y,3*z,t-u)
Basic Fortran (cont.), Paolo Bison, FI08, 2008-09-29 – p.3
Funzioni intrinseche
funzioni predefinite nel linguaggio
matematiche
abs(x) iabs(i) mod(x,y) sqrt(r)
trigonometriche
cos(r) sin(r) tan(r) acos(r) asin(r) atan(r)
esponenziale e logaritmo exp(r) log(r) log10(r)
di conversione int(r) nint(r)
test tra reali
(0.3333e20 + 1.0e-7 - 0.3333e20) == 1.0e-7 vero o falso?
x == 0.0 ⇒ abs(x)<eps x == y ⇒ abs(x-y)<eps
Basic Fortran (cont.), Paolo Bison, FI08, 2008-09-29 – p.4
Zero di una funzione con il metodo della bisezione
x2 x1
y
x y=f(x)
Basic Fortran (cont.), Paolo Bison, FI08, 2008-09-29 – p.5
zero di una funzione
! bisect.f90
! calcolo dello zero della funzione cos con il metodo
! della bisezione
!
program bisect logical :: segnomeno
real :: x0=1.0,x1=2.0,x,EPS=1.0E-3 segnomeno = cos(x0) < 0.0
if ((cos(x1) < 0.0) .eqv. segnomeno) then; stop else
do
x = (x0 + x1) / 2.0
if ((cos(x) < 0.0) .eqv. segnomeno) then x0 = x
else x1 = x end if
if (abs(x0 - x1) < EPS) then; exit; end if end do
print *,x end if
end program bisect
Basic Fortran (cont.), Paolo Bison, FI08, 2008-09-29 – p.6
Conversione di tipo integer ⇔ real
integer :: a real :: x
implicite - conversione automatica x=a
a=x (troncamento)
esplicite - funzione per la conversione x=real(a)
a=int(x) troncamento
a=nint(x) arrotondamento = int(x+0.5)
esempio
a / 2 <=?=> a / 2.0
Basic Fortran (cont.), Paolo Bison, FI08, 2008-09-29 – p.7
Character
insieme delle stringhe di lunghezza arbitraria ≥ 0 di
caratteri stampabili
operatori:
//
costanti
caratteri tra doppio apice (") "abc" "1" ""
Fortran 90: ’
char-selector (len=n)
definisce il numero massimo di caratteri
ordinamento lessicografico per operatori di relazione
Basic Fortran (cont.), Paolo Bison, FI08, 2008-09-29 – p.8
Character (cont.)
sottostringhe:
R609 substring
is parent-string ( substring-range ) R611 substring-range
is [ int-expr ] : [ int-expr ]
funzioni intrinseche
len(s) len_trim(s) trim(s) ichar(c) char(i)
esempi
character(len=1) :: s0
character(len=10) :: s1="hello",s2 s2="world"
s1 = trim(s1) // " " // s0 s2 = s2(3:5)
s0=char(ichar("3"))
Basic Fortran (cont.), Paolo Bison, FI08, 2008-09-29 – p.9
reverse di una stringa
! reverse.f90
! calcola il reverse di una stringa
!
program reverse integer :: i
character(len=10) :: st,ts read *,st
ts=st(len_trim(st):len_trim(st)) do i=len_trim(st)-1,1,-1
ts = trim(ts) // st(i:i) end do
print *,ts
end program reverse
Basic Fortran (cont.), Paolo Bison, FI08, 2008-09-29 – p.10
Complex
• sottoinsieme finito dei numeri complessi r+ii
• operazioni
operatori: + - * / **
funzioni: conjg, abs, sin, cos
• costanti
due costanti reali o intere tra parentesi tonde es. (-3,8) (5.7,8.0)
• rappresentazione finita
• es.
complex :: x,y=(-3.14,5.98),z x = y*sin(z)
Basic Fortran (cont.), Paolo Bison, FI08, 2008-09-29 – p.11
Conversione di tipo integer,real ⇔ complex
integer :: a real :: x complex :: c
implicite - conversione automatica x=c (parte reale)
a=c (parte reale troncata)
c=x (p.r. ← valore di x, p.i. ← 0)
c=a (p.r. ← valore di a, p.i. ← 0)
esplicite - operatore/funzione per la conversione x=real(c) (parte reale)
x=aimag(c) (parte immaginaria) a=int(c) (parte reale troncata) c=cmplx(a,a)
c=cmplx(x,x) Basic Fortran (cont.), Paolo Bison, FI08, 2008-09-29 – p.12
composizione di forze
! sum_forze.f90
! calcola risultante di forze
! rappresentate come numeri complessi
!
program sum_forze
complex :: risultante=(0,0),forza do
read *,forza
if (forza == (0,0)) then; exit; end if risultante = risultante + forza
end do print *
print *,risultante end program sum_forze
Basic Fortran (cont.), Paolo Bison, FI08, 2008-09-29 – p.13
Costanti
valori che non cambiano durante l’esecuzione
nome significativo per i valori
uso come le variabili, eccetto a sx. dell’istruzione di assegnazione
sintassi:
- attributo parameter della dichiarazione - inizializzazione
- per le stringhe (len=*)
es.
integer, parameter :: numero_linee=60 real, parameter :: p_greco=3.1415 character(len=*), parameter :: fine="."
Basic Fortran (cont.), Paolo Bison, FI08, 2008-09-29 – p.14
grafico funzione - 1
! graph.f90
! rappresentazione grafica della funzione
! f(x)=exp(-x)*sin(2*pi*x)
!
! sistema di riferimento
!
! h y y+1
! | | s |
! ---> y
! |
! |
! |- x
! |
! | d
! |
! |
! |- x+1
! |
! |
! V x
!
Basic Fortran (cont.), Paolo Bison, FI08, 2008-09-29 – p.15
grafico funzione - 2
program graph
real, parameter :: d = 0.0625 ! 1/16, 16 linee nell’intervallo
! [x,x+1]
real, parameter :: c = 6.28318 ! 2*pi
integer, parameter :: s = 32 ! 32 caratteri di ampiezza per
!l’intervallo [y,y+1]
integer, parameter :: h = 34 ! posizione dell’asse x integer, parameter :: lim = 32 ! numero di campionamenti
real :: x, y integer :: i, n, k
character (len=2*h) :: linea
Basic Fortran (cont.), Paolo Bison, FI08, 2008-09-29 – p.16
grafico funzione - 3
do i=0,lim
x = d*i ! calcolo ascissa
y = exp(-x)*sin(c*x) ! calcolo funzione
n = nint(s*y) + h ! calcolo posizione su asse y
! costruzione linea di stampa linea = "" ! stringa vuota do k=0,n-1
if (k==h) then; linea=linea(1:k+1) // "|"
else; linea=linea(1:k+1) // " "
end if end do
linea=linea(1:k+1) // "*" ! k = n
! si continua fino ad h se n<h
! per inserire simbolo asse x do k=n+1,h
if (k==h) then; linea=linea(1:k+1) // "|"
else; linea=linea(1:k+1) // " "
end if end do
print *,linea end do
end program graph
Basic Fortran (cont.), Paolo Bison, FI08, 2008-09-29 – p.17
grafico funzione - 4
*
| *
| *
| *
| *
| *
| *
| *
*
* |
* |
* |
* |
* |
* |
* |
*
| *
| *
| *
| *
| *
| *
Basic Fortran (cont.), Paolo Bison, FI08, 2008-09-29 – p.18
Selezione multipla
E
S1 S2 SN
L1 L2 LN
E espressione che ritorna un valore LE
dato E si esegue la sequenza Si associata all’etichetta
Li = LE
if LE 6∈ {L1,L2, . . . ,LN} errore o ramo default
Basic Fortran (cont.), Paolo Bison, FI08, 2008-09-29 – p.19
select
• selezione multipla
• sintassi
R808 case-construct is select-case-stmt
[ case-stmt block ] ...
[ CASE DEFAULT block ] end-select-stmt R809 select-case-stmt
is SELECT CASE ( case-expr ) R810 case-stmt
is CASE case-selector R811 end-select-stmt
is END SELECT
Basic Fortran (cont.), Paolo Bison, FI08, 2008-09-29 – p.20
select
R812 case-expr is int-expr or char-expr R813 case-selector
is ( case-value-range-list ) R814 case-value-range
is case-value or case-value : or : case-value
or case-value : case-value R815 case-value
is int-initialization-expr or char-initialization-expr
Constraint:For a given case-construct, each case-value shall be of the same type as case-expr. For character type, length differences are allowed.
Constraint: For a given case-construct, the case-value-ranges shall not overlap; that is, there shall be no possible value of the case-expr that matches more than one case-value-range.
Basic Fortran (cont.), Paolo Bison, FI08, 2008-09-29 – p.21
esempi di select
select case (i) case (1,3,15:20)
k = k*i case default
k=0 end case
select case (k+z*3) case (:-1)
i=0 case (0)
i=-1 end case
Basic Fortran (cont.), Paolo Bison, FI08, 2008-09-29 – p.22
conteggio vocali - 1
! conta_voc.f90
! conta il numero di vocali presenti
! in una stringa
!
program conta_voc
integer :: i,n_a=0,n_e=0,n_o=0,n_i=0,n_u=0 character(len=256) :: st
character(len=1) :: ch read *,st
do i=1,len_trim(st)
ch=st(i:i) ! estrae i-esimo carattere if ((ch >= "a") .and.(ch <= "z")) then
ch=char(ichar(ch) - ichar("a")+ ichar("A")) end if
Basic Fortran (cont.), Paolo Bison, FI08, 2008-09-29 – p.23
conteggio vocali - 2
select case (ch) case("A")
n_a=n_a+1 case("E")
n_e=n_e+1 case("I")
n_i=n_i+1 case("O")
n_o=n_o+1 case("U")
n_u=n_u+1 end select end do
print *,"A",n_a,"E",n_e,"I",n_i,"O",n_o,"U",n_u end program conta_voc
Basic Fortran (cont.), Paolo Bison, FI08, 2008-09-29 – p.24
calculator -1
! calc.f90
!
! programma che calcola espressioni algebriche
! espresse dalla grammatica:
!
! V={0,1,2,3,4,5,6,7,8,9,+,-,=}
! N={<exp>,<num>}
! p={ <exp> ::= <num>= | <num><oper><exp>,
! <num> ::= <cifra> |<cifra><num>,
! <cifra> ::= 0|1|2|3|4|5|6|7|8|9|0
! <oper> ::= +|- }
!
program calc integer :: i
integer :: num1, num2
character (len=100) :: expr character (len=1):: oper,ch
Basic Fortran (cont.), Paolo Bison, FI08, 2008-09-29 – p.25
calculator - 2
read *,expr
print *,"---"
print *,trim(expr) num1=0
oper="+"
i=0 do
i=i+1
if (i>len_trim(expr)) then
print *,"espressione non corretta"; stop end if
ch = expr(i:i)
Basic Fortran (cont.), Paolo Bison, FI08, 2008-09-29 – p.26
calculator - 3
! lettura numero num2 = 0
if (ch >="0" .and. ch<="9") then do
if (ch >="0" .and. ch<="9") then
num2 = num2*10 +ichar(ch)-ichar("0") i = i+1; ch = expr(i:i)
else exit end if end do else
print *,"espressione non corretta"; stop end if
Basic Fortran (cont.), Paolo Bison, FI08, 2008-09-29 – p.27
calculator - 4
! esegue operazione con numero precedente select case (oper)
case ("+")
num1 = num1 + num2 case ("-")
num1 = num1 - num2 case default
print *,oper," non e’ nel lessico"; stop end select
! in ch c’e’ un operatore o = if (ch=="=") then
print *,num1; stop else
oper=ch end if end do
end program calc
Basic Fortran (cont.), Paolo Bison, FI08, 2008-09-29 – p.28
Esempi di esecuzione di calc
[paolo@pcbison F]$ ./calc 34+66-87-8=
>
34+66-87-8=
5
[paolo@pcbison F]$ ./calc 7-5%6=
>
7-5%6=
% non e’ nel lessico [paolo@pcbison F]$ ./calc 7
>
7
espressione non corretta [paolo@pcbison F]$ ./calc 56-=
>
56-=
espressione non corretta [paolo@pcbison F]$
Basic Fortran (cont.), Paolo Bison, FI08, 2008-09-29 – p.29
Precisione dei dati
parametro kind in dichiarazione
sintassi
(kind=n)
dove n è un numero naturale che indica la precisione
es.
integer (kind=3) :: i real (kind=8) :: x
i valori permessi di n e le precisioni associate dipendono dal compilatore
Basic Fortran (cont.), Paolo Bison, FI08, 2008-09-29 – p.30
Determinazione parametro di kind
funzioni intrinseche
determinano, se esiste, il numero di kind necessario per rappresentare un dato compreso tra −10r e 10r con p cifre decimali
selected_int_kind(r)
selected_real_kind(p,r)
costante real doppia precisione + funzione intriseca kind
lettera D per esponente: 1.0D0
kind(expr)
ritorna numero di kind relativo alla precisione di expr
Basic Fortran (cont.), Paolo Bison, FI08, 2008-09-29 – p.31
programma stampa_kind.f90
! stampa_kind.f90
! stampa numeri di kind
!
program stampa_kind integer :: p,r
print *,"single precision: ",kind(1.0E0) print *,"double precision: ",kind(1.0D0) do
print *,"p r"
read *,p,r if (p==0) then
if (r==0) then; stop; end if print *,selected_int_kind(r) else
print *,selected_real_kind(p,r) end if
end do
end program stampa_kind
Basic Fortran (cont.), Paolo Bison, FI08, 2008-09-29 – p.32
Uso delle costanti
uso di identificatori di costanti per il valore di n nell’opzione kind
integer,parameter :: byte=1 integer,parameter :: word=2 integer,parameter :: long=4 integer (kind=byte) :: b integer (kind=long) :: k
Basic Fortran (cont.), Paolo Bison, FI08, 2008-09-29 – p.33
Conversione di precisione
conversione implicita tutti gli operandi alla massima precisione associata con uno di essi
print *,1.0/3.0 + 1.0D0/3.0 => 0.666666676600774
print *,1.0D0/3.0 + 1.0D0/3.0 => 0.666666666666667
Basic Fortran (cont.), Paolo Bison, FI08, 2008-09-29 – p.34
singola vs. doppia precisione
singola doppia occ. memoria bassa alta tempo calcolo minore maggiore
quando doppia?
dati con valori assoluti minori di 10−39 o maggiori di 1039
dati di dimensione molto diverse
dati con differenze molto piccole
Basic Fortran (cont.), Paolo Bison, FI08, 2008-09-29 – p.35