25
Programaci´on estruturada en Fortran Exercicios clases interactivas Semana 2 Traballo en clase 1. Vari´ abeis, expresi´ ons aritm´ eticas e E/S b´ asica. Escribe un programa en Fortran que lea un umero real x por teclado e mostre por pantalla x 1, x 2 + x 2e(x 3)/(x 2 + x 1). Escribe o programas usando o editor Gedit e almac´ enao no arquivo programa1.f90 (os programas de Fortran deben ter a extensi´ on .f90). ´ Imolo compilar co comando f95: f95 programa1.f90 Deste modo x´ erase o programa executable a.out. Para executalo, teclea na li˜ na de comandos a.out. program programa1 print *, "Introduce x:" read *, x print *, "Os valores son:" print *, "x - 1 = ", x - 1 print *, "x^2 + x - 2 = ", x*x + x - 2 print *, "(x - 3)/(x^2 + x - 1) = ", (x - 3)/(x**2 + x - 1) stop end program programa1 2. Sentenzas de selecci´ on, ecuaci´on de 2 o grao. Escribe un programa que lea os coeficientes (reais) dunha ecuaci´ on de segundo grao ax 2 + bx + c = 0 e calcule as s´ uas soluci´ ons segundo a f´ormula: x = b ± b 2 4ac 2a (1) Sexa d = b 2 4ac o discriminante. Se d< 0, ent´ on hai d´ uas soluci´ ons complexas conxugadas x = b 2a ± i d 2a , onde i ´ e a unidade imaxinaria i = 1. Se d = 0, ent´ on hai d´ uas soluci´ ons reais iguais x = b 2a . Se d> 0 hai d´ uas soluci´ ons reais distintas x = b ± d 2a . Se a =0e b = 0, ent´ on temos unha ecuaci´ on de 1 o grao con soluci´ on x = c/b. Se a = b = c = 0 todo x IR ´ e soluci´ on, e se a = b =0,c = 0 non hai soluci´ on. Para comprobar que o programa funciona correctamente, proba os seguintes exemplos: a b c N o soluci´ ons Soluci´ons 1 1 1 2 complexas x = 1 2 ± i 3 2 1 -2 1 2 reais iguais x =1 1 0 -1 2 reais distintas x = ±1 0 1 -1 ec. 1 o grao x =1 0 0 0 x = IR 0 0 0 0 x = Cuadro 1: Valores dos coeficientes a, b, c e das soluci´ ons que debe obter o programa. 1

exercicios_interactivas

  • Upload
    m1f2p3

  • View
    15

  • Download
    0

Embed Size (px)

Citation preview

Page 1: exercicios_interactivas

Programacion estruturada en Fortran

Exercicios clases interactivas

Semana 2

Traballo en clase

1. Variabeis, expresions aritmeticas e E/S basica. Escribe un programa en Fortran que lea unnumero real x por teclado e mostre por pantalla x− 1, x2 + x− 2 e (x− 3)/(x2 + x− 1). Escribe oprogramas usando o editor Gedit e almacenao no arquivo programa1.f90 (os programas de Fortrandeben ter a extension .f90). Imolo compilar co comando f95:

f95 programa1.f90

Deste modo xerase o programa executable a.out. Para executalo, teclea na lina de comandos a.out.

program programa1

print *, "Introduce x:"

read *, x

print *, "Os valores son:"

print *, "x - 1 = ", x - 1

print *, "x^2 + x - 2 = ", x*x + x - 2

print *, "(x - 3)/(x^2 + x - 1) = ", (x - 3)/(x**2 + x - 1)

stop

end program programa1

2. Sentenzas de seleccion, ecuacion de 2o grao. Escribe un programa que lea os coeficientes(reais) dunha ecuacion de segundo grao ax2 + bx + c = 0 e calcule as suas solucions segundo aformula:

x =−b±

√b2 − 4ac

2a(1)

Sexa d = b2 − 4ac o discriminante. Se d < 0, enton hai duas solucions complexas conxugadas

x =−b

2a± i

√−d

2a, onde i e a unidade imaxinaria i =

√−1. Se d = 0, enton hai duas solucions reais

iguais x =−b

2a. Se d > 0 hai duas solucions reais distintas x =

−b±√d

2a. Se a = 0 e b 6= 0, enton

temos unha ecuacion de 1o grao con solucion x = −c/b. Se a = b = c = 0 todo x ∈ IR e solucion,e se a = b = 0, c 6= 0 non hai solucion. Para comprobar que o programa funciona correctamente,proba os seguintes exemplos:

a b c No solucions Solucions

1 1 1 2 complexas x = −1

2± i

√3

21 -2 1 2 reais iguais x = 11 0 -1 2 reais distintas x = ±10 1 -1 ec. 1o grao x = 10 0 0 ∞ x = IR0 0 0 0 x = ∅

Cuadro 1: Valores dos coeficientes a, b, c e das solucions que debe obter o programa.

1

Page 2: exercicios_interactivas

program ec2grao

real :: im

print *, "introduce a,b,c"

read *, a,b,c

if(0 == a) then

if(0 == b) then

if(0 == c) then

print *, "infinitas solucions reais"

else

print *, "non existen solucions"

endif

else

print *, "solucion= ", -c/b

endif

else

d= b*b - 4*a*c; a2 = 2*a

if(d > 0) then

sqrtd = sqrt(d)

print *, "2 solucions reais: ", (-b + sqrtd)/a2, (-b - sqrtd)/a2

else if(0 == d) then

print *, "2 solucions reais iguais: ", -b/a2

else

re = -b/a2; im= sqrt(-d)/abs(a2)

print *, "2 solucions complexas conxugadas:", re, "+/- I*", im

endif

endif

stop

end program ec2grao

3. Sentenza de iteracion, acumulador, polinomio de Tchevyshev. Os polinomios de Tcheby-shev Tn(x) podense escribir como un producto de termos. Escribe un programa en Fortran quecalcule o n-esimo polinomio para un valor de x, definido por:

Tn(x) = 2n−1n∏

k=1

[

x− cos

(

(2k − 1)π

2n

)]

(2)

O programa debe ler por teclado n e x.

program tchevishev

real, parameter :: PI = 3.141592

print *, "Introduce n, x:"

read *, n, x

tnx = 2**(n - 1); n2 = 2*n

do k = 1, n

tnx = tnx*(x - cos(((2*k - 1)*PI)/n2))

end do

print *, "t_n(x)= ", tnx

stop

end program

2

Page 3: exercicios_interactivas

Traballo a desenvolver pol@ alumn@

1. Escribe un programa que calcule a distancia entre un punto v = (x0, y0, z0) e un plano π dadopola ecuacion ax + by + cz + d = 0 . Esta ecuacion tamen se pode escribir como wTx + d = 0,onde w = (a, b, c) e o vector director do plano, wT e o trasposto de w, perpendicular ao plano π, ex = (x, y, z) e un punto pertencente ao plano. A distancia entre v e π podese calcular como:

D(v, π) =|ax0 + by0 + cz0 + d|

‖w‖ (3)

O valor absoluto e coa funcion abs(...); ademais, ‖w‖ =√a2 + b2 + c2. O programa debe ler por

teclado os valores a, b, c, d, x0, y0, z0.

2. Escribe un programa que calcule a posicion x(t), velocidade v(t) e aceleracion a(t) dun movil enmovemento armonico, dado por:

x(t) = asen(ωt+ θ) (4)

v(t) = aωcos(ωt+ θ) (5)

a(t) = −aω2sen(ωt+ θ) (6)

sendo ω = π radians/s, θ = π/2 radians, a = 2,5m/s2 para tempos 0 ≤ t ≤ 100 segs. separados 1seg. entre si.

3. Escribe un programa que lea n numeros x1, . . . , xn por teclado e calcule a sua media e o seu produto(non uses arrais):

Media =1

n

n∑

i=1

xi (7)

Produto =

n∏

i=1

xi (8)

Semana 4

Traballo en clase

1. Sumatorio dobre. Escribe un programa que lea por teclado un numero enteiro n e logo dousvectores n-dimensionais v e w, reservados dinamicamente. O programa debe calcular, usando arrais:

n∑

i=1

i∑

j=1

viwj (9)

program sumatorio_dobre

real, dimension(:), allocatable:: v, w

print*, "Introduce numero de elementos:"

read *, n

allocate(v(n), w(n))

3

Page 4: exercicios_interactivas

print*, "Introduce numeros por teclado:"

suma=0

do i=1,n

read*, v(i), w(i)

do j=1,i

suma=suma+v(i)*w(j)

end do

end do

! alternativa simple vectorizada

!suma=0

!do i=1,n

! suma = suma + v(i)*sum(w(1:i))

!end do

print*, "O resultado e: ", suma

deallocate(v, w)

stop

end program sumatorio_dobre

2. Analise dunha matriz. Escribe un programa que lea por teclado un numero enteiro n e unhamatriz A de orde n, e calcule:

A sua traza (suma dos elementos da diagonal principal), definida pola ecuacion:

tr(A) =n∑

i=1

aii (10)

A suma do seu triangulo superior.

Determine se a matriz e simetrica: Aij = Aji, i, j = 1, . . . , n.

program matriz_simetrica

real, dimension(:, :), allocatable:: a

logical :: simetrica

print*, "Introduce a orde da matriz:"

read *, n

allocate(a(n,n))

print*, "Introduce numeros por teclado:"

do i=1,n

read *, (a(i,j),j=1,n)

end do

!Calculo da traza menos eficiente

! traza=0

! do i=1,n

! do j=1, n

! if(i==j) traza = traza + a(i,j)

! end do

! end do

! calculo mais eficiente

traza=0

4

Page 5: exercicios_interactivas

do i=1,n

traza = traza + a(i,i)

end do

print *, "traza= ", traza

!suma do triangulo superior menos eficiente

!sts = 0

!do i = 1, n

! do j = 1, n

! if(j > i) sts = sts + a(i, j)

! end do

!end do

!print *, "sts= ", sts

!suma do triangulo superior mais eficiente

sts = 0

do i = 1, n

do j = i + 1, n

sts = sts + a(i, j)

end do

end do

print *, "sts= ", sts

! E a matriz simetrica

simetrica=.true.

filas: do i=1,n

columnas: do j=i+1, n

if(a(i,j)/= a(j,i)) then

simetrica=.false.

exit filas

end if

end do columnas

end do filas

if(simetrica) then

print*, "simetrica"

else

print*, "non simetrica"

end if

deallocate(a)

stop

end program matriz_simetrica

Traballo a desenvolver pol@ alumn@

1. Escribe un programa que lea un numero enteiro n e dous vectores v e w n-dimensionais con valoresreais (usa vectores reservados dinamicamente). O programa debe calcula-lo produto escalar (ouinterior) de ambos:

vw =

n∑

i=1

viwi (11)

2. Escribe un programa que lea un vector estatico v = (v1, . . . , v5) con 5 valores reais. O programadebe calcula-la norma (modulo) de v:

5

Page 6: exercicios_interactivas

‖v‖ =

n∑

i=1

v2i (12)

NOTA: a raız cadrada dun valor x calculase en Fortran coa funcion sqrt(x).

3. Escribe un programa que lea dous vectores x e y de dimension n por teclado (usa vectores dinamicos)e calculen a sua distancia ‖x− y‖ definida como:

‖x− y‖ =

n∑

i=1

(xi − yi)2 (13)

4. Escribe un programa que lea por teclado un numero enteiro n e un vector v de dimension n (usarvectores reservados dinamicamente), e calcule o vector transformado w, tamen de dimension n,definido por:

wi =

i∑

j=1

vj , i = 1, . . . , n (14)

Semana 6

Traballo en clase

1. Produto vector-matriz-vector. Escribe un programa que lea por teclado un numero enteiro n,dous vectores v e w e unha matriz A de orde n, e calcule o produto

vAwT = [v1 . . . vn]

a11 . . . a1n. . . . . . . . .an1 . . . ann

w1

. . .wn

program prod_vector_matriz_vector

real, dimension(:,:), allocatable :: a

real, dimension(:), allocatable :: v, w, p

print*, "Dimension do vector e matriz: "

read *, n

allocate(a(n,n), v(n), w(n), p(n))

print*,"Introduce vectores: "

do i=1,n

read*, v(i), w(i)

end do

print *, "Introduce matriz: "

do i=1,n

read *, (a(i,j),j=1,n)

end do

!p=vA

do i=1,n

p(i)=0

do j=1,n

6

Page 7: exercicios_interactivas

p(i)=p(i)+v(i)*a(j,i)

end do

end do

!r=pw

r=0

do i=1,n

r=r+p(i)*w(i)

end do

print*, "O resultado e: ", r

deallocate(a, v, w, p)

stop

end program prod_vector_matriz_vector

Version optimizada:

program prod_vector_matriz_vector

real, dimension(:,:), allocatable :: a

real, dimension(:), allocatable :: v, w

print*, "Dimension do vector e matriz: "

read *, n

allocate(a(n,n), v(n), w(n))

print*,"Introduce v: "

read *, v

print*,"Introduce w: "

read *, w

print *, "Introduce matriz: "

do i=1,n

read*, (a(i,j),j=1,n)

end do

r = 0

do i=1,n

s = 0

do j=1,n

s = s + v(i)*a(j,i)

end do

r = r + s*w(i)

end do

print*, "O resultado e: ", r

deallocate(a, v, w)

stop

end program prod_vector_matriz_vector

2. Mınimo comun multiplo de dous numeros enteiros. Subrutinas. Funcions externas. Es-cribe un programa que presente na pantalla o mınimo comun multiplo (mcm) de dous numerosenteiros positivos. O mcm calculase como o produto dos factores primos de ambos numeros, proce-dendo da seguinte maneira: se un factor primo esta presente nunha das factorizacions e non naoutra, incluese no calculo do mcm. Se un factor primo esta presente nas duas factorizacions, tomaseaquel que ten un exponente maior. Empregar subprogramas.

7

Page 8: exercicios_interactivas

c Proba con x = 120 e y = 36

c factores de 120 : 2 ^ 3 3 ^ 1 5 ^ 1

c factores de 36 : 2 ^ 2 3 ^ 2

c Factores comuns: 2 ^ 3 3 ^ 2 5 ^ 1

c O mcm e 360

program minimo_comun_multiplo

integer, dimension(100) :: bx, ex, by, ey

integer :: x, y

print *, ’Introduzca dos numeros enteros positivos’

read *, x, y

call factores_primos(x, bx, ex, nfx)

call factores_primos(y, by, ey, nfy)

mcm_xy = mcm(bx, ex, nfx, by, ey, nfy)

print *, "O mcm e", mcm_xy

stop

end program

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

subroutine factores_primos(n, b, e, nf)

integer, intent(in) :: n

integer, dimension(100), intent(out) :: b, e

integer, intent(out) :: nf

m = n; nf = 1; k = 2

do

if(mod(m, k) == 0) then

b(nf) = k; e(nf) = 1; m = m/k

do

if(mod(m, k) /= 0) exit

e(nf) = e(nf) + 1; m = m/k

end do

nf = nf + 1

end if

k = k + 1

if(m == 1) exit

end do

nf = nf - 1

print *, "factores de", n, ":", (b(i), "^", e(i), " ", i = 1, nf)

return

end subroutine factores_primos

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

function mcm(bx, ex, nfx, by, ey, nfy)

integer, dimension(100), intent(in) :: bx, ex, by, ey

integer, intent(in) :: nfx, nfy

integer, dimension(100) :: b, e

logical :: comun

8

Page 9: exercicios_interactivas

do i = 1, nfx

b(i) = bx(i); e(i) = ex(i)

end do

nf = nfx

do i = 1, nfy

comun = .false.

do j = 1, nf

if(by(i) == b(j)) then

comun = .true.

if(ey(i) > e(j)) e(j) = ey(i)

exit

end if

end do

if(.not.comun) then

nf = nf + 1

b(nf) = by(i); e(nf) = ey(i)

end if

end do

print *, "Factores comuns:", (b(i), "^", e(i), " ", i = 1, nf)

mcm = 1

do i = 1, nf

do j = 1, e(i)

mcm = mcm*b(i)

end do

end do

return

end function mcm

Traballo a desenvolver pol@ alumn@

1. Escribe un programa que lea por teclado catro numeros enteiros na, ma, nb e mb e duas matricesA e B de orde na × ma e nb × mb respectivamente, e calcule o produto matricial de ambas. Oprograma debe comprobar que son multiplicabeis.

2. Escribe un programa que lea por teclado un numero enteiro n e logo dous vectores n-dimensionaisv e w. O programa debe invocar a unha subrutina chamada calcula produto exterior(...),que calcule e proporcione como saıda a matriz A resultante de multiplicar o vector columna v polovector fila w: aij = viwj ; i, j = 1, . . . , n. O programa debe mostra-la matriz A por pantalla dendeo programa principal.

v′w =

v1. . .vn

[w1 . . . wn] =

v1w1 . . . v1wn

. . . . . . . . .vnw1 . . . vnwn

3. Escribe un programa que lea por teclado un numero enteiro n, un vector v e unha matriz A, ambosde orde n. O programa principal debe chamar a un subprograma prod vector matrix(...) (debesdecidir o seu tipo e argumentos) que calcule o resultado do produto matricial vA (sendo v un vectorfila).

4. Escribe un programa que lea por teclado un numero enteiro n, un vector v e unha matriz A, ambosde orde n. O programa debe calcula-lo resultado do produto matricial Av (sendo v un vectorcolumna).

9

Page 10: exercicios_interactivas

Semana 8

Traballo en clase

1. Calculo de lımites. Iteracion indefinida. Representacion grafica. Escribe un programa enFortran que calcule o lımite:

lımx→2

x2 + x− 6

x2 − 4(15)

program limite

!------------------------

! version con variabel real: da warning

! do x = 1, 3, 0.05

! print *, x, (x*x+x-6)/(x*x-4)

! end do

!------------------------

! version con bucle indefinido

x=1

do

print *, x, (x*x+x-6)/(x*x-4)

x=x+0.05

if (x>3) exit

end do

stop

end program limite

2. Representacion grafica empregando programas externos. Para isto, redirixe a saıda doprograma anterior a un arquivo co comando de Linux:

$ a.out >saida.dat

E logo representa graficamente esta saıda co octave: executa o comando octave -q e, unha vezdentro do octave, executa:

load saida.dat

plot(saida(:,1), saida(:,2))

exit

Ou co gnuplot: executa o comando gnuplot e, unha vez dentro do gnuplot, executa:

plot "saida.dat" using 1:2 with linespoints

exit

3. Representacion grafica en Fortran usando a librarıa GnuFor2. A mesma representaciongrafica podese facer dende Fortran, pero necesitas modificar algo o programa. Descarga dende http://www.math.yorku.ca/~akuznets/gnufor2 os arquivos gnufor2.f90, test.f90 e Makefile. Paracompilar a librarıa, teclea make. Isto crea os arquivos gnufor2.mod (arquivo de modulo) e gnufor2.o(codigo obxecto). Para representar graficamente unha curva con esta librarıa, hai que poner ascoordenadas X e Y dos puntos en dous vectores x e y. Para isto, vas usar dous vectores (con 100

elementos cada un), e meter os valores de x ∈ [1, 3] e y = f(x) =x2 + x− 6

x2 − 4nestes vectores. Tendo

en conta que i = 1, . . . , 100 e que 1 ≤ x ≤ 3, tes que poner x como funcion de i. Para isto, usa unhafuncion linear x(i) = pi + q, considerando i = 1 . . . , n (neste caso n = 100) e que x ∈ [a, b] (neste

10

Page 11: exercicios_interactivas

caso, a = 1, b = 3). Calcula p, q usando que para i = 1 debe ser x = a e para i = n debe ser x = b.Obtes o sistema linear de duas ecuacions {a = p + q; b = np + q}. Restando a segunda menos aprimeira obtemos:

b− q = (n− 1)p ⇒ p =b− a

n− 1, q = a− p =

na− b

n− 1⇒ x =

(b− a)i+ (na− b)

n− 1(16)

No noso caso, n = 100, a = 1, b = 3 e temos x =2i+ 97

99, e podes verificar que x(1) = 1, x(100) = 3.

Escribe o seguinte programa limite gnufor2.f90:

! compilacion: f95 gnufor2.o limite_gnufor2.f90

program limite_gnufor2

use gnufor2 ! indica que se use o modulo gnufor2 (arquivo gnufor2.mod)

integer, parameter :: n = 100

real, parameter :: a = 1, b = 3

real(8), dimension(n) :: x, y ! hai que usar reais de dobre precision

do i = 1, n

t = ((b - a)*i + (n*a - b))/(n - 1); x(i) = t; y(i) = (t*t + t - 6)/(t*t - 4)

end do

call plot(x, y) ! subrutina da libraria gnufor2

stop

end program limite_gnufor2

Compila o programa co comando (necesitas ter os arquivos gnufor2.o e gnufor2.mod no mesmodirectorio que limite gnufor2.f90):

f95 gnufor2.o limite gnufor2.f90

Executa o programa co comando a.out: crea a venta da figura 1, na que podes comprobar que o

lımx→2

x2 + x− 6

x2 − 4= 1.25.

Figura 1: Representacion grafica dunha funcion dunha variabel usando gnufor2.

4. Representacion grafica de funcion de duas variabeis en IR2. Escribe un programa en Fortranque represente a funcion f(x, y) = sen(5(x2 + y2))e−(x2+y2)/4, con x, y ∈ [−2, 2].

! compilacion: f95 gnufor2.o grafica3D.f90

11

Page 12: exercicios_interactivas

program grafica3D

use gnufor2

integer, parameter :: n = 100

real, parameter :: a = -2, b = 2

real(8), dimension(n) :: x, y

real(8), dimension(n,n) :: z

do i=1,n

t = ((b - a)*i + (n*a - b))/(n - 1); x(i) = t; y(i) = t

end do

do i=1,n

do j=1,n

u = x(i)**2 + y(j)**2; z(i,j)=sin(5*u)*exp(-u/4)

end do

end do

call surf(x,y,z)

stop

end program grafica3D

Podes compilar este programa co comando f95 gnufor2.o grafica3D.f90, obtendo a venta dafigura 2.

Figura 2: Representacion grafica da funcion f(x, y) = sin(10(x2 + y2))e−(x2+y2)/4 usando gnufor2.

5. Calculo de derivadas. Calcula e representa graficamente a derivada da funcion f(x) = e−xsen2xno intervalo [0, 10].

program derivada

real, parameter :: a = 0, b = 10

open(1, file="derivada.dat", status="new")

h = 0.01; x = a; fxh = f(x)

do

fx = fxh; fxh = f(x + h); df = (fxh - fx)/h

print *, x, fx, df

write (1, *) x, fx, df

x = x + h

if(x > b) exit

end do

close(1)

12

Page 13: exercicios_interactivas

stop

end program derivada

!cccccccccccccccccccccccccccc

function f(x)

real, intent(in) :: x

f = exp(-x)*sin(2*x)

return

end function f

Para representar a funcion e a derivada co octave:

a.out

octave -q

x=load("derivada.dat");

subplot(2,1,1)

plot(x(:,1),x(:,2),’f(x)’)

subplot(2,1,2)

plot(x(:,1),x(:,3),’df(x)’)

quit

6. Calculo de integrais indefinidas. Escribe un programa que calcule a integral indefinida dunhafuncion f(x).

Sabemos que se g(x) =

∫ x

a

f(t)dt, enton g′(x) = f(x). Pola definicion de derivada temos que:

f(x) = g′(x) = lımh→0

g(x+ h)− g(x)

h(17)

Se tomamos h ≃ 0+ podemos aproximar:

f(x) ≃ g(x+ h)− g(x)

h(18)

e despexar na ec. anterior g(x+h) ≃ g(x)+hf(x). Como conecemos f(x) e queremos a sua integralindefinida (e dicir, g(x) tal que g′(x) = f(x)), fixando un valor inicial g(x0) podemos calcularg(x), ∀x > x0. Este valor inicial g(x0) prefixado e equivalente a constante C que se lle pode sumar

a funcion primitiva g(x). No programa, calculamos g(x) =

∫ x

a

f(t)dt no intervalo [a, b] usando

a = 0, b = 1, f(t) = t, x0 = 0, g(x0) = g(0) = 0. Repite o calculo para a = 0, b = π, f(t) =sin(t), x0 = 0, g(x0) = g0 = 0.

program integral_indef

!print *, "introduce a e b: "

!read *, a, b

open(1, file="integral_indef.dat", status="new")

a = 0; b = 1

x = a; h = 0.01; gx = 0

do

fx = f(x)

print *, x, fx, gx

write (1, *) x, fx, gx

gx = gx + h*fx; x = x + h

if(x > b) exit

13

Page 14: exercicios_interactivas

end do

close(1)

stop

end program integral_indef

!!!!!!!!!!!!!!!!!!!!

function f(x)

real, intent(in) :: x

f = x

return

end function f

7. Calculo de integrais definidas. Calcula a integral definida:

∫ 1

−1

arcos(x)

1 + x2dx (19)

program integral_indef

real :: integral

!print *, "introduce a e b: "

!read *, a, b

a = -1; b = 1; h = 0.001

x = a; integral = 0

do

integral = integral + f(x)

x = x + h

if(x > b) exit

end do

print *, "integral = ", h*integral

stop

end program integral_indef

!!!!!!!!!!!!!!!!!!!!!!!!!!!

function f(x)

real, intent(in) :: x

!f = x

f = acos(x)/(1 + x*x)

return

end function f

Traballo a desenvolver pol@ alumn@

1. Escribe un programa en Fortran que calcule os valores da seguinte funcion definida por intervalos:

f(x) =

1 + x x ≤ 0x 0 < x < 12− x 1 ≤ x ≤ 23x− x2 x > 2

14

Page 15: exercicios_interactivas

2. Escribe un programa que calcule lımite lımx→0

e|x|/x.

3. Escribe un programa que calcule a derivada de f(x) =x

x2 + 2x+ 9

4. Xeraliza o programa visto en clase para calcular integrais definidas de modo que, usando funcionsexternal, poida calcular a integral de calquer funcion (definida como funcion externa no programa).

Semana 9

Traballo en clase

1. Determinante dunha matriz cadrada de orde n: Subprogramas recursivos. Arquivos.Escribe un programa que lea dende un arquivo a orde n dunha matriz cadrada e a propria matriz(ambas operacions deben facerse dende subprogramas). Logo, o programa principal debe chamara un subprograma recursivo det(...) que calcule o determinante da matriz lida usando o desen-volvemento por adxuntos da primeira fila da matriz.

program determinante

real, dimension(:, :), allocatable :: a

open(1, file = "matriz.dat", status="old", err=1)

read (1, *) n

allocate(a(n, n))

do i = 1, n

read (1, *) (a(i, j), j = 1, n)

print *, (a(i, j), j = 1, n)

end do

close(1)

d = det(a, n)

print *, "det = ", d

deallocate(a)

stop

1 print *, "erro en open abrindo matriz.dat"

stop

end program determinante

!------------------------------------

recursive function det(a, n) result(y)

real, dimension(n, n), intent(in) :: a

integer, intent(in) :: n

real, dimension(:,:), allocatable :: b

if(2 == n) then

y = a(1,1)*a(2,2) - a(1,2)*a(2,1)

else

y = 0

allocate(b(n - 1, n - 1))

do i = 1, n

call adxunto(a, n, i, b)

y = y + (-1)**(1+i)*a(1,i)*det(b, n - 1)

end do

deallocate(b)

end if

return

end function det

15

Page 16: exercicios_interactivas

!-------------------------------------

subroutine adxunto(a, n, i, b)

real, dimension(n,n), intent(in)::a

integer, intent(in):: n, i

real, dimension(n-1,n-1), intent(out)::b

integer :: f, c !ollo non inicializar aqui

f=1;c=1

do j=2,n

do k=1,n

if(k/=i) then

b(f,c)=a(j,k); c=c+1

end if

end do

f=f+1; c=1

end do

do k=1, n-1

print *, (b(k,l), l=1, n-1)

end do

print *, "-----------------"

return

end subroutine adxunto

2. Resolucion dun sistema de n ecuacions lineares usando a librarıa FGSL. Escribe unprograma que empregue a interfaz Fortran-GSL (FGSL) a GNU Scientific Library (GSL) pararesolver un sistema de ecuacions lineares. Antes de nada vai ao directorio fogar co comando:

cd

Logo, descarga a FGSL version 0.9.4 co comando:

wget http://www.lrz.de/services/software/mathematik/gsl/fortran/fgsl-0.9.4.tar.gz

Descomprime o arquivo fgsl-0.9.4.tar.gz co comando:

tar zxvf fgsl-0.9.4.tar.gz

Isto crea o directorio fgsl-0.9.4. Vai a este directorio co comando:

cd fgsl-0.9.4

Edita o arquivo configure, comentando as linas:

if [ "$(basename $gh)" != "gsl-histogram" ] ; then

echo "GSL installation not found. Aborting"

exit 1

fi

cun # no comezo de cada lina. Executa:

./configure --bits 64

make

Descarga dende o curso virtual os arquivos sistema orde4.dat e sistema orde5.dat, cos coefi-cientes e termos independentes de dous sistemas de orde 4 e 5, e o seguinte programa:

16

Page 17: exercicios_interactivas

!sistema_orde4.dat: x=1 y=0 z=-1 t=2; sistema={x+y+z+t=2, x-y-z+t=4, -x+z=-2, y+z+t=1}

! 1 1 1 1 2

! 1 -1 -1 1 4

! -1 0 1 0 -2

! 0 1 1 1 1

!----------------------------------------------

!sistema_orde5.dat: x=1 y=2 z=0 t=-1 u=0; sistema={x+y-z+t+u=2;x-y+t+u=1;x+z-u=0;

! x-y-z+t+u=2;x-y+z-t+u=1}

! 1 1 1 1 1 2

! 2 -1 0 -1 -1 1

! -1 0 1 -1 1 0

! 1 1 0 1 -1 2

! 0 1 -1 1 0 1

program exemplo_gsl

use fgsl

integer(fgsl_size_t) :: n

integer(fgsl_int) :: status, signum

type(fgsl_matrix) :: a

type(fgsl_vector) :: b, x

real(fgsl_double), dimension(:,:), allocatable, target :: af

real(fgsl_double), dimension(:), allocatable, target :: bf, xf

type(fgsl_permutation) :: p

character(len=1),dimension(10) :: incog=(/’x’,’y’,’z’,’t’,’u’,’v’,’w’,’r’,’s’,’p’/)

a = fgsl_matrix_init(type=1.0_fgsl_double)

b = fgsl_vector_init(type=1.0_fgsl_double)

x = fgsl_vector_init(type=1.0_fgsl_double)

open(1, file="sistema_orde4.dat", status="old")

read (1,*) n

allocate(af(n,n),bf(n),xf(n))

p = fgsl_permutation_alloc(n)

do i = 1, n

read (1, *) (af(j, i), j = 1, n), bf(i) ! ollo: a(j,i)

end do

close(1)

print ’(a,i3,a)’, "sistema de orde", n, " ="

do i = 1, n

print ’(f7.2,a,$)’, af(i, 1), incog(1)

do j = 2, n

if(af(i,j) >= 0) then

print ’(a,f7.2,a,$)’, ’ + ’, af(i, j), incog(j)

else

print ’(a,f7.2,a,$)’, ’ - ’, -af(i, j), incog(j)

endif

end do

print ’(a,f7.2)’, ’ = ’, bf(i)

end do

status = fgsl_matrix_align(af, n, n, n, a)

status = fgsl_vector_align(bf, n, b, n, 0_fgsl_size_t, 1_fgsl_size_t)

status = fgsl_vector_align(xf, n, x, n, 0_fgsl_size_t, 1_fgsl_size_t)

status = fgsl_linalg_LU_decomp (a, p, signum)

17

Page 18: exercicios_interactivas

status = fgsl_linalg_LU_solve (a, p, b, x)

print *, "solucion:"

do i = 1, n

print ’(2a,f6.2)’, incog(i), ’ = ’, xf(i)

end do

call fgsl_matrix_free(a)

call fgsl_vector_free(b)

call fgsl_vector_free(x)

call fgsl_permutation_free(p)

deallocate(af,bf,xf)

stop

end program exemplo_gsl

Logo, debes compilalo co comando:

f95 -I/usr/include/gsl -L. sistema_fgsl.f90 -lfgsl_gfortran -lgsl -lgslcblas -lm

No mesmo directorio tes que ter os arquivos libfgsl gfortran.a (usada coa opcion -lfgsl gfortran

do comando de compilacion) e fgsl.mod (incluido na sentenza use fgsl do programa). Executa oprograma co comando a.out. Comproba a solucion co octave (p.ex. para orde 4):

$ octave -q

> a = [1 1 1 1; 1 -1 -1 1; -1 0 1 0; 0 1 1 1]; b=[2; 4; -2; 1];

> a\b

> quit

Finalmente, executa cd .. e cp -r fgsl-0.9.2 /Z/rai/nome.apelido ou cp -r fgsl-0.9.2

/media/MEMORIA dependendo de se usas a unidade Z ou un lapiz de memoria, para almacenartodo o necesario.

3. Calculo da inversa dunha matriz cadrada de orde n usando a librarıa Lapack. Descargadende o curso virtual o seguinte programa, que calcula a inversa dunha matriz cadrada usando alibrarıa Lapack (a matriz lese dende un arquivo).

! ORDE 3: matriz a=

! 2.00 1.00 -1.00

! 2.00 0.00 1.00

! 1.00 2.00 4.00

! inv(a)=

! 0.13 0.40 -0.07

! 0.47 -0.60 0.27

! -0.27 0.20 0.13

!--------------------------------

! ORDE 4: a =

! 1 2 3 4

! -1 2 0 3

! 4 1 9 5

! 4 3 2 1

! inv(a) =

! 3.08 -2.40 -1.00 -0.12

! -3.32 2.60 1.00 0.48

! -2.80 2.00 1.00 0.20

! 3.24 -2.20 -1.00 -0.36

18

Page 19: exercicios_interactivas

program inversa

real(8),dimension(:,:),allocatable :: a, b

open(1, file="matriz_orde4.dat", status="old")

read (1,*) n

allocate(a(n,n),b(n,n))

do i = 1, n

read (1, *) (a(i, j), j = 1, n)

do j = 1, n

print ’(f6.2,$)’, a(i, j)

end do

print *, ’’ ! para pasar a seguinte linha

end do

close(1)

call inv(a, n, b)

print *, "inv(a)="

do i = 1, n

do j = 1, n

print ’(f6.2,$)’, b(i, j)

end do

print *, ’’

end do

deallocate(a,b)

stop

end program inversa

!-------------------------------

! Retorna a inversa dunha matriz calculando a descomposicion LU con Lapack

subroutine inv(A, n, Ainv)

real(8), dimension(n,n), intent(in) :: A

real(8), dimension(n,n), intent(out) :: Ainv

integer, intent(in) :: n

real(8), dimension(n) :: work ! work array for LAPACK

integer, dimension(n) :: ipiv ! pivot indices

integer :: info

! procedementos external definidos en Lapack

external DGETRF

external DGETRI

! Almacena A en Ainv para evitar que lapack a sobrescriba

Ainv = A

! DGETRF calcula a factorizacion LU da matriz usando pivote parcial con intercambio de filas

call DGETRF(n, n, Ainv, n, ipiv, info)

if (info /= 0) stop "error: matriz singular"

! DGETRI calcula a matriz inversa usando a factorizacion LU calculada por DGETRF.

call DGETRI(n, Ainv, n, ipiv, work, n, info)

if (info /= 0) stop "error en la inversion"

return

end subroutine inv

19

Page 20: exercicios_interactivas

Compila co comando:

f95 inversa.f90 -llapack

Executa o programa probando cos arquivos matriz orde3.dat e matriz orde4.dat indicados nos co-mentarios do comezo do programa, que podes descargar dende o curso virtual. Comproba a solucionco octave (p.ex. para orde 3):

$ octave -q

> a = [2 1 -1; 2 0 1; 1 2 4];

> inv(a)

ans =

0.133333 0.400000 -0.066667

0.466667 -0.600000 0.266667

-0.266667 0.200000 0.133333

> quit

4. Resolucion dun sistema de n ecuacions lineares usando a librarıa Lapack. Descarga oseguinte programa dende o curso virtual ao arquivo sistema linear.f90:

!sistema_orde4.dat: x=1 y=0 z=-1 t=2; sistema={x+y+z+t=2, x-y-z+t=4, -x+z=-2, y+z+t=1}

! 1 1 1 1 2

! 1 -1 -1 1 4

! -1 0 1 0 -2

! 0 1 1 1 1

!----------------------------------------------

!sistema_orde5.dat: x=1 y=2 z=0 t=-1 u=0; sistema={x+y-z+t+u=2;x-y+t+u=1;x+z-u=0;

! x-y-z+t+u=2;x-y+z-t+u=1}

! 1 1 1 1 1 2

! 2 -1 0 -1 -1 1

! -1 0 1 -1 1 0

! 1 1 0 1 -1 2

! 0 1 -1 1 0 1

program sistema_linear

real,dimension(:,:),allocatable :: a

real,dimension(:),allocatable :: b

integer, dimension(:),allocatable :: pivote

character(len=1),dimension(10) :: incog=(/’x’,’y’,’z’,’t’,’u’,’v’,’w’,’r’,’s’,’p’/)

open(1,file="sistema_orde4.dat",status="old",err=1)

read (1,*) n

allocate(a(n,n),b(n),pivote(n))

do i = 1, n

read (1, *) (a(i, j), j = 1, n), b(i)

end do

close(1)

print ’(a,i3,a)’, "sistema de orde", n, " ="

do i = 1, n

print ’(f7.2,a,$)’, a(i,1), incog(1)

do j = 2, n

if(a(i,j) >= 0) then

print ’(a,f7.2,a,$)’, ’ + ’, a(i, j), incog(j)

else

print ’(a,f7.2,a,$)’, ’ - ’, -a(i, j), incog(j)

endif

20

Page 21: exercicios_interactivas

end do

print ’(a,f7.2)’, ’ = ’, b(i)

end do

call sgesv(n, 1, a, n, pivote, b, n, info)

print *, "solucion:"

do i = 1, n

print ’(2a,f6.2)’, incog(i), ’ = ’, b(i)

end do

deallocate(a,b,pivote)

stop

1 print *, "erro en open"

stop

end program sistema_linear

Descarga tamen dende o curso virtual os arquivos sistema orde4.dat e sistema orde5.dat, coscoeficientes e termos independentes dos sistemas lineares de ecuacions. Compila o programa cocomando:

f95 sistema linear.f90 -llapack

Executao con a.out. Comproba que a solucion e correcta calculandoa co octave (p.ex. para o sistemade orde 4):

$ octave -q

> a = [1 1 1 1; 1 -1 -1 1; -1 0 1 0; 0 1 1 1]; b=[2; 4; -2; 1];

> a\b

ans =

1

-0

-1

2

> quit

5. Xerador de numeros aleatorios. Descarga dende o curso virtual o seguinte programa, que im-prime por pantalla 10 numeros aleatorios no intervalo [a, b) empregando a subrutina random number()

de f95. O programa usa a subrutina init random seed() para inicializar o xerador de numerosaleatorios co reloxio do sistema:

program aleatorio

print ’(a,$)’, "introduce a,b: "

read *, a, b

rango = b - a

call init_random_seed()

do i=1,10

call random_number(x)

print *, i, rango*x + a

end do

stop

end program aleatorio

!----------------------------------------

subroutine init_random_seed()

integer :: i, n, clock

integer, dimension(:), allocatable :: seed

21

Page 22: exercicios_interactivas

call random_seed(size = n)

allocate(seed(n))

call system_clock(count = clock)

seed = clock + 37 * (/ (i - 1, i = 1, n) /)

call random_seed(put = seed)

deallocate(seed)

return

end subroutine

6. Medida do tempo consumido por un programa en Fortran. Descarga dende o curso virtualo seguinte programa, que executa un bucle de 1000 iteracions e mostra o tempo consumido:

program mide_tempo

real(8) :: inicio, fin, n, i

call cpu_time(inicio)

n=1e3; i = 0

print *, "medindo tempo ..."

do

i = i + 1

if(i > n) exit

end do

call cpu_time(fin)

print ’("n=",d10.1, " tempo = ",d10.4," s.")’, n, fin - inicio

end program mide_tempo

7. Funcions para produto escalar de vectores e para produto matricial. Descarga dende ocurso virtual este programa, que define un vector v e unha matriz cadrada a, ambos de orde 3, ecalcula o produto escalar vTv e o produto matricial aa.

program exemplos_funcions

real, dimension(3) :: v = (/1,2,3/)

real, dimension(3,3) :: a = reshape((/1,2,3,4,5,6,7,8,9/),shape(a)), b

print *, "v=", v

print *, "a="

do i=1,3

print *, (a(i,j),j=1,3)

end do

print *, "dot(v,v)=", dot_product(v,v)

b = matmul(a,a)

print *, "a*a="

do i=1,3

print *, (b(i,j),j=1,3)

end do

b = transpose(a)

print *, "a^T="

do i=1,3

print *, (b(i,j),j=1,3)

end do

stop

end program exemplos_funcions

8. Persistencia dun numero enteiro (descomposicion en cifras). Escribe un programa quecalcule a persistencia dun numero enteiro. Con este fin, o programa debera separar o numero nas suascifras e multiplicalas entre si. O resultado tamen se dividira nas suas cifras, e estas multiplicaranseentre si continuando o proceso ata obter un resultado dunha unica cifra. A persistencia sera onumero de veces que se repetiu o proceso. Exemplo: o numero 715 ten persistencia 3 (715

->35 ->15 ->5)

22

Page 23: exercicios_interactivas

program persistencia

print ’(a, $)’, "introduce n: "

read *, n

k = 0

do

m = 1

do

m = m*mod(n, 10); n = n/10

if(n == 0) exit

end do

print *, m

n = m; k = k + 1

if(m < 10) exit

end do

print *, "persistencia= ", k

stop

end program persistencia

Traballo a desenvolver pol@ alumn@

1. Escribe un programa que lea por teclado o grao n dun polinomio p(x) = anxn+ . . . a2x

2+a1x+a0 eos seus coeficientes a0, . . . , an e calcule as raıces enteiras do polinomio. Ter en conta que as posıbeisraıces enteiras do polinomio son divisores do termo independente a0.

2. Escribe un programa que calcule a matriz de covarianza Σ dun conxunto deN vectores d-dimensionais{xi, i = 1, . . . , N}, sendo xi = (xi1, . . . , xid). O elemento ij da matriz de covarianza Σ (cadrada deorde d) defınese como:

Σij =1

N

N∑

k=1

(xki − 〈xi〉)(xkj − 〈xj〉) (20)

Onde 〈xi〉 e o valor medio da componente i dos vectores xk:

〈xi〉 =1

N

N∑

k=1

xki (21)

O programa debe, dados N = 12 e d = 5, debe chamar a un subprograma onde abra o arquivo e leaos vectores (cada vector esta almacenado nunha lina distinta no arquivo). Logo, debe chamar a outrosubprograma que calcule as medias 〈xi〉, i = 1, . . . , d. Por ltimo, debe chamar a un subprogramaque calcule cada elemento Σij , i, j = 1, . . . , d, mediante a formula 3. Finalmente, debe chamar aoutro subprograma que imprima a matriz Σ (fila a fila).

NOTA: Empregar o arquivo vectores.dat que se proporciona (N = 12, d = 5).

1.3 0.4 1.5 0.4 1.2

1.9 0.4 1.5 0.7 1.3

1.2 0.4 0.9 0.5 1.2

1.5 0.4 2.1 0.8 1.1

1.1 0.4 2.2 0.9 1.0

1.0 0.4 2.3 0.2 0.9

0.6 0.4 2.5 0.1 0.8

1.1 1.4 1.9 0.4 0.7

0.4 0.3 1.5 0.3 0.6

0.5 1.2 1.3 0.2 0.5

0.8 1.4 1.6 0.4 0.4

1.3 0.9 1.2 0.7 0.2

23

Page 24: exercicios_interactivas

3. Analiza o seguinte programa, que resolve unha ecuacion non lineal da forma:

f(x) =n∑

i=0

aixi = 0 (22)

polo Metodo de Newton (resolvela significa atopar x). Este metodo consiste no seguinte: partindodunha aproximacion inicial x0 para x, este metodo calcula aproximacions sucesivas xi, i = 1, 2, . . .empregando a seguinte formula:

xi+1 = xi −f(xi)

f ′(xi)(23)

Esta operacion iterativa executase ata que |xi − xi−1| < 0,00001

O programa debe facer o seguinte:

Pedir o usuario a orde n do polinomio f(x).

Pedir o usuario os coeficientes ai, i = 0, . . . , n do polinomio f(x).

Escribe unha funcion que calcule o valor f(x).

Escribe outra funcion que calcule o valor f ′(x), determinado pola expresion:

f ′(x) =

n∑

i=1

iaixi−1 (24)

Escribe o programa principal, onde se debera executar a operacion iterativa 5 ata que |xi −xi−1| < 0,00001.

EXEMPLO: dada a ecuacion x3 − x2 − x + 1 = 0 ten raıces en x = 1 (dobre) e x = −1 (simple).Neste caso, n = 3. Probar con x0 = 2 (para calcular a raiz x = 1 e con x0 = −3 (para calcular araiz x = −1).

O programa debe almacenar os valores xi, i = 1, ... no ficheiro datos.dat, co seguinte formato:

x(i - 1) | x(i)

-------------------

-2.00000 | -1.400

-1.40000 | -1.100

-1.10000 | -1.009

-1.00870 | -1.000

-1.00007 | -1.000

-1.00000 | -1.000

program newton

parameter (EPSILON = 0.00001)

real, dimension(0:10) :: a

real :: x, xp

print *, "Introduce n:"

read *, n

do i = 0, n

print *, "Introduce o coeficiente ", i

read *, a(i)

end do

print *, "Introduce x0: "

read *, x

open(1, file = "datos.dat", status="new")

write (1, 3) "x(i - 1)", " x(i)"

3 format(a, t10, "|", a)

24

Page 25: exercicios_interactivas

write (1, *) "-----------------"

do

xp = x

d = df(a, xp, n)

if(d.eq.0) then

x = xp

else

x = xp - f(a, xp, n)/d

endif

write (1, 2) xp, x

2 format(f8.5, t10, "|", f8.5)

print 2, xp, x

if(abs(x - xp) < EPSILON) exit

end do

print *, "Atopada raiz en x = ", x, ", f(x) = ", f(a, x, n)

close(1)

stop

end program newton

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

function f(a, x, n)

real, dimension(0:n), intent(in) :: a

real, intent(in) :: x

integer, intent(in) :: n

f = a(0)

do i = 1, n

f = f + a(i)*x**i

end do

return

end function f

!!!!!!!!!!!!!!!!!!!!!!!!!!!!

function df(a, x, n)

real, dimension(0:n), intent(in) :: a

real, intent(in) :: x

integer, intent(in) :: n

df = a(1)

do i = 2, n

df = df + i*a(i)*x**(i - 1)

end do

return

end function df

25