Está en la página 1de 61

Gua de Practicas:

Analisis Numerico
de
Ecuaciones Diferenciales
usando MATLAB
2
Indice general

Notaciones 5

Introduccion 6

I Elementos basicos de MATLAB 9

1. Introduccion a MATLAB. 11
1.1. Vectores en MATLAB . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
1.2. Matrices en MATLAB . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
1.3. Funciones de vectores . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
1.4. Bucles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
1.4.1. Relaciones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
1.5. La instruccion if . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
1.6. Ficheros ejecutables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
1.7. Subrutinas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
1.8. Cadenas de texto, mensajes de error, entradas . . . . . . . . . . . . . . . . 33
1.9. Comparando la eficiencia de algoritmos: cputime . . . . . . . . . . . . . . . 34
1.10. Formatos de salida . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34
1.11. Graficos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
1.11.1. Representaciones en 2D . . . . . . . . . . . . . . . . . . . . . . . . 35
1.11.2. Representaciones en 3D . . . . . . . . . . . . . . . . . . . . . . . . 37
1.12. Resumen de funciones elementales y matrices especiales . . . . . . . . . . . 39

3
4

II Introduccion a la construccion de algoritmos 41


2. Sistemas de numeracion; errores y sus fuentes 43
2.1. Sistemas de numeros y conversiones . . . . . . . . . . . . . . . . . . . . . . 43
2.1.1. Sistemas de numeracion en base q . . . . . . . . . . . . . . . . . . . 43
2.1.2. Conversion de base decimal a base q . . . . . . . . . . . . . . . . . 44
2.1.3. Estandar IEEE de representacion de numeros enteros y en coma
flotante . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47
2.2. Errores y sus causas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50
2.2.1. Definiciones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50
2.2.2. Fuentes de errores . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50
2.3. Propagacion de errores: condicion y estabilidad. . . . . . . . . . . . . . . . 54
2.4. Eficiencia de un algortmo numerico . . . . . . . . . . . . . . . . . . . . . . 56
2.4.1. Ejemplo: Evaluacion de polinomios, metodo de Horner . . . . . . . 57
2.5. EJERCICIOS PRACTICOS . . . . . . . . . . . . . . . . . . . . . . . . . . 60
5

NOTACIONES

Notaciones generales

Smbolo Significado
x = (x1 , x2 , ..., xN ) Elemento de IRN
r = |x|= (x21 + x22 + ...+ x2N )1/2 Modulo de x
u u u
u = x ,
1 x2
, ..., x N
Gradiente de u
Espacios de funciones

Smbolo Significado
C() Funciones continuas en
C0 () Funciones continuas en con soporte compacto
C k () Funciones de clase k en
C0k () Funciones de C k () con soporte compacto
C () Funciones indefinidamente diferenciables en
C0 () = D() Funciones de C () con soporte compacto
6

Introduccion
7
8
Parte I

Elementos basicos de MATLAB

9
Captulo 1

Introduccion a MATLAB.

Vamos a optar por MATLAB para programar los algoritmos que aparecen asociados
a los distintos metodos numericos que estudiaremos a lo largo del curso. La razon de ello
es que, para propositos docentes, existen ventajas en la utilizacion de este software de
calculo matematico respecto a lenguajes de programacion como C o Fortran: por un lado,
la sintaxis de programacion de MATLAB es bastante similar a la de cualquier lenguaje
de alto nivel, lo que nos permitira adaptarnos a las peculiaridades de su programacion
sin demasiados problemas; por otro lado, podremos utilizar como test de nuestros propios
algoritmos las rutinas especficas que incorpora MATLAB; por ultimo, la integracion
de una serie de paquetes graficos en el entorno de programacion de MATLAB facilita
extraordinariamente la tarea de presentacion de resultados.
Los ejemplos que se incluyen en las secciones siguientes se han obtenido con la version
6.0 (R12) de MATLAB. Al tratarse de ejercicios sencillos, no es esperable diferencias
significativas cuando se reproduzcan en versiones posteriores de MATLAB.
La aritmetica de trabajo en MATLAB es doble precision (concepto que aclararemos
posteriormente) aunque la version 7.0 ha introducido la posibilidad de trabajar con arit-
metica entera y real de precision simple.
Una vez hemos accedido a MATLAB y estando situados en la ventana de coman-
dos, comenzamos nuestro recorrido introductorio. En el texto que sigue a continuacion,
cualquier lnea que comienza con dos signos >> se utiliza para denotar una lnea de
comando MATLAB.

11
12

1.1. Vectores en MATLAB


Casi todos los comandos basicos en MATLAB implican el uso de vectores. Podemos
definir un vector tecleando cada uno de sus elementos o, alternativamente y cuando es
posible, podemos hacerlo especificando el primer elemento, un incremento y el ultimo
elemento. Por ejemplo, para crear un vector cuyos elementos son 0, 2, 4, 6 y 8, podemos
teclear:

>> 0:2:8

ans =

0 2 4 6 8

MATLAB tambien guarda el ultimo resultado. En el ejemplo previo, se ha creado


una variable ans. Para obtener el vector traspuesto, tecleamos:

>> ans

ans =

0
2
4
6
8

Para guardar los vectores creados de modo que seamos capaces de trabajar con ellos
posteriormente, debemos darles nombre. Por ejemplo, para crear el vector fila v, tecleamos:

>> v = [0:2:8]

v =

0 2 4 6 8
13

>> v

v =

0 2 4 6 8

>> v;
>> v

ans =

0
2
4
6
8

Podemos darnos cuenta a partir del ejemplo anterior que si finalizamos una lnea con
un punto y coma no se muestra el resultado. MATLAB permite tambien trabajar con
elementos especficos del vector:

>> v(1:3)

ans =

0 2 4

>> v(1:2:4)

ans =

0 4

>> v(1:2:4)

ans =
14

0
4

Una vez especificada la notacion podemos realizar diversas operaciones. Por ejemplo:

>> v(1:3)-v(2:4)

ans =

-2 -2 -2

1.2. Matrices en MATLAB


Damos a continuacion una introduccion basica a la definicion y manipulacion de
matrices. La definicion de una matriz es analoga a la definicion de un vector. Podemos
considerarla como una columna de vectores fila:

>> A = [ 1 2 3; 3 4 5; 6 7 8]

A =

1 2 3
3 4 5
6 7 8

o como una fila de vectores columna:

>> B = [ [1 2 3] [2 4 7] [3 5 8]]

B =

1 2 3
15

2 4 5
3 7 8

A estas alturas de la introduccion, si hemos estado reproduciendo los ejemplos anteri-


ores tendremos, muy probablemente, una considerable cantidad de variables definidas en
nuestro espacio de trabajo. Si queremos conocer esta informacion utilizaremos el comando
whos:

>> whos
Name Size Elements Bytes Density Complex

A 3 by 3 9 72 Full No
B 3 by 3 9 72 Full No
ans 1 by 3 3 24 Full No
v 1 by 5 5 40 Full No

Volviendo a las matrices y a la hora de realizar operaciones basicas con las mismas, la
notacion que utiliza MATLAB es la usual en algebra lineal. Obviamente, las operaciones
matriciales deben ser legales si no queremos tener problemas:

>> v = [0:2:8]

v =

0 2 4 6 8

>> A*v(1:3)
??? Error using ==> * Inner matrix dimensions must agree.

>> A*v(1:3)

ans =

16
16

28
46

Podemos trabajar con diferentes partes de una matriz, al igual que vimos que se poda
hacer con vectores. De nuevo, debemos tener cuidado en hacer operaciones permitidas:

>> A(1:2,3:4)
??? Index exceeds matrix dimensions.

>> A(1:2,2:3)

ans =

2 3
4 5

>> A(1:2,2:3)

ans =

2 4
3 5

Aparte de las operaciones elementales (suma, producto), podemos hacer otras de


interes como por ejemplo, obtener la inversa de una matriz (cuando esta operacion tenga
sentido, si no obtendremos un error). Sin embargo, debemos tener cuidado puesto que las
operaciones que se realizan pueden presentar errores de redondeo. En el ejemplo, la matriz
A no es una matriz invertible, pero MATLAB devuelve una matriz como resultado.

>> inv(A)

Warning: Matrix is close to singular or badly scaled.


Results may be inaccurate. RCOND = 4.565062e-18

ans =
17

1.0e+15 *

-2.7022 4.5036 -1.8014


5.4043 -9.0072 3.6029
-2.7022 4.5036 -1.8014

Conviene hacer notar, en este punto, que MATLAB distingue entre mayusculas y
minusculas. Esta es otra potencial fuente de problemas cuando trabajamos con algoritmos
complicados:

>> inv(a)
??? Undefined function or variable a.

Otra posible operacion es, por ejemplo, la obtencion de los valores propios aproxima-
dos de una matriz. Hay dos versiones de esta rutina: una encuentra los valores propios y
la otra encuentra los valores y vectores propios. Si no recordamos cual es cual, podemos
obtener mas informacion tecleando eig en la lnea de comandos.

>> eig(A)

ans =

14.0664
-1.0664
0.0000

>> [v,e] = eig(A)

v =

-0.2656 0.7444 -0.4082


-0.4912 0.1907 0.8165
-0.8295 -0.6399 -0.4082
18

e =

14.0664 0 0
0 -1.0664 0
0 0 0.0000

>> diag(e)

ans =

14.0664
-1.0664
0.0000

Existen tambien rutinas que permiten encontrar soluciones de ecuaciones. Por ejem-
plo, si Ax = b y queremos encontrar x, un modo lento de hacerlo es, simplemente,
invertir A y realizar una multiplicacion por la izquierda sobre ambos lados de la ecuacion.
Obviamente, hay metodos mas eficientes y mas estables para hacer esto (descomposiciones
L/U con pivotes, por ejemplo). MATLAB tiene comandos especiales para hacer esto.
MATLAB posee ademas dos tipos diferentes de operadores / y \. La accion del primer
operador es la siguiente: x = A\v A1 v; la accion del segundo operador es: x = v/B
vB 1 . Se dan ejemplos de su uso a continuacion:

>> v = [1 3 5]

v =

1
3
5

>> x = A\v

Warning: Matrix is close to singular or badly scaled.


19

Results may be inaccurate. RCOND = 4.565062e-18

x =

1.0e+15 *

1.8014
-3.6029
1.8014

>> x = B\v

x =

2
1
-1

>> B*x

ans =

1
3
5

>> x1 = v/B

x1 =

4.0000 -3.0000 1.0000

>> x1*B
20

ans =

1.0000 3.0000 5.0000

Finalmente, si queremos borrar todos los datos del sistema y comenzar de nuevo uti-
lizaremos el comando clear. Conviene utilizar este comando con cuidado porque MATLAB
no pide una segunda opinion ...

>> clear

>> whos

1.3. Funciones de vectores


Es indudable que la gran ventaja de trabajar con MATLAB es la facilidad de ma-
nipulacion de vectores y matrices. En este apartado comenzaremos con manipulaciones
simples (suma, resta, multiplicacion). A continuacion mostramos como se pueden definir
operaciones relativamente complejas con un pequeno esfuerzo.
Comenzamos con la suma y resta de vectores. Definiremos dos vectores y a conti-
nuacion los sumaremos y restaremos:

>> v = [1 2 3]

v =

1
2
3

>> b = [2 4 6]

b =

2
21

4
6

>> v+b

ans =

3
6
9

>> v-b

ans =

-1
-2
-3

La multiplicacion de vectores y matrices sigue, logicamente y como comentamos an-


teriormente, reglas estrictas, as como la suma. En el ejemplo anterior los vectores son
ambos vectores columna con tres componentes:

>> v*b
Error using ==> * Inner matrix dimensions must agree.

>> v*b

ans =

2 4 6
4 8 12
6 12 18

>> v*b

ans =
22

28

Hay ocasiones en las que queremos realizar una operacion sobre cada elemento de un
vector o matriz. MATLAB permite hacer este tipo de operaciones. Por ejemplo, supon-
gamos que queremos multiplicar cada componente de un vector v por la correspondiente
componente del vector b. En otras palabras, Supongamos que queremos hallar v(1)*b(1),
v(2)*b(2) y v(3)*b(3). Estara bien utilizar el smbolo * puesto que estamos haciendo un
tipo de multiplicacion. Sin embargo, como este smbolo ha sido definido con otra funcion,
debemos recurrir a otra cosa. Los programadores ocupados del desarrollo de MATLAB
decidieron entonces utilizar los smbolos .* para hacer esta operacion. De hecho, se puede
emplear este smbolo antes de cualquier smbolo matematico para especificar a MATLAB
que la operacion en cuestion debe tener lugar sobre cada entrada del vector.

>> v.*b

ans =

2
8
18

>> v./b

ans =

0.5000
0.5000
0.5000

Puesto que hemos comenzado a hablar de operaciones no lineales continuemos con


ellas: si pasamos un vector a una operacion matematica predefinida, obtendremos un
vector del mismo tamano con entradas obtenidas realizando la operacion especificada
sobre la correspondiente entrada del vector original:

>> sin(v)
23

ans =

0.8415
0.9093
0.1411

>> log(v)

ans =

0
0.6931
1.0986

La posibilidad de trabajar con estas funciones vectoriales es una de las ventajas de


MATLAB. De este modo, podemos definir operaciones complejas rapida y facilmente. En
el siguiente ejemplo trabajamos con un vector con muchas componentes:

>> x = [0:0.1:100]

x =

Columns 1 through 7

0 0.1000 0.2000 0.3000 0.4000 0.5000 0.6000

(stuff deleted)

Columns 995 through 1001

99.4000 99.5000 99.6000 99.7000 99.8000 99.9000 100.0000

>> y = sin(x).*x./(1+cos(x));

Ademas de esta simple manipulacion de vectores, MATLAB nos permitira tambien


representar graficamente los resultados que obtengamos. Tecleando,
24

>> plot(x,y)

tendremos una representacion grafica de la funcion antes considerada. Si tecleamos

>> plot(x,y,rx)

obtenemos la misma grafica pero las lneas son reempladas por puntos rojos en forma de
x. Para ver mas opciones del commando plot, podemos teclear

>> help plot

El comando help es, sin duda, el camino mas corto para estar seguro de la sintaxis de un
determinado comando de MATLAB.
La notacion compacta permitira realizar un gran numero de operaciones utilizando
pocos comandos. Veamos el siguiente ejemplo:

>> coef = zeros(1,1001);


>> coef(1) = y(1);
>> y = (y(2:1001)-y(1:1000))./(x(2:1001)-x(1:1000));
>> whos
Name Size Elements Bytes Density Complex

ans 3 by 1 3 24 Full No
b 3 by 1 3 24 Full No
coef 1 by 1001 1001 8008 Full No
v 3 by 1 3 24 Full No
x 1 by 1001 1001 8008 Full No
y 1 by 1000 1000 8000 Full No

Grand total is 3011 elements using 24088 bytes

>> coef(2) = y(1);


>> y(1)

ans =

0.0500
25

>> y = (y(2:1000)-y(1:999))./(x(3:1001)-x(1:999));
>> coef(3) = y(1);
>>
>>

A partir de este algoritmo podemos encontrar el polinomio de Lagrange que interpola


los puntos definidos anteriormente (vector x). Por supuesto, con tantos puntos el proceso
puede resultar algo tedioso. Afortunadamente MATLAB dispone de un modo sencillo de
hacer tareas monotonas, como veremos a continuacion.

1.4. Bucles
En esta seccion veremos como utilizar los bucles for y while. En primer lugar, dis-
cutiremos el uso del bucle for con ejemplos para operaciones fila sobre matrices. A con-
tinuacion, mostraremos el uso del bucle while.
El bucle for permite repetir ciertos comandos. Todas las estructuras de bucles en
MATLAB comienzan con una palabra clave (como for o while) y terminan con un end
(parece sencillo, no?). Veamos un ejemplo trivial:

>> for j=1:4,


j
end

j =

j =

j =
26

j =

>>

Otro ejemplo:

>> v = [1:3:10]

v =

1 4 7 10

>> for j=1:4,


v(j) = j;
end
>> v

v =

1 2 3 4

Este es un ejemplo simple y una demostracion bonita de como funcionan los bucles
for. Sin embargo, no se debe utilizar en la practica: la notacion utilizada en la primera
lnea es mucho mas rapida que el bucle. Un mejor ejemplo se presenta a continuacion,
donde realizamos operaciones sobre las filas de una matriz. Si queremos comenzar en
la segunda fila de una matriz y restar la fila previa y repetir esta operacion sobre las
siguientes filas, un bucle for puede ocuparse de esto:

>> A = [ [1 2 3] [3 2 1] [2 1 3]]

A =
27

1 3 2
2 2 1
3 1 3

>> B = A;
>> for j=2:3,
A(j,:) = A(j,:) - A(j-1,:)
end

A =

1 3 2
1 -1 -1
3 1 3

A =

1 3 2
1 -1 -1
2 2 4

Presentamos a continuacion un ejemplo mas realista (implementacion de eliminacion


Gaussiana):

>> for j=2:3,


for i=j:3,
B(i,:) = B(i,:) - B(j-1,:)*B(i,j-1)/B(j-1,j-1)
end
end

B =

1 3 2
0 -4 -3
3 1 3
28

B =

1 3 2
0 -4 -3
0 -8 -3

B =

1 3 2
0 -4 -3
0 0 3

La forma general de un bucle while es

>> while (condiciones)


(operaciones)
end

Las operaciones se repetiran mientras que las condiciones sean ciertas. Por ejemplo,
dado un numero a, el siguiente bloque permite calcular y mostrar el entero no negativo
mas pequeno tal que 2n a:

>> n=0;
>> while 2^n < a
n=n+1;
end
>> n

1.4.1. Relaciones
Los operadores de relacion en MATLAB son:
29

< menor que


> mayor que
<= menor o igual que
>= mayor o igual que
== igual que
= distinto a
Demonos cuenta que el smbolo == se utiliza en lugar de = en una relacion.
Podemos conectar varias relaciones utilizando los operadores logicos:

& y
| o
no

1.5. La instruccion if
La forma general de una instruccion if simple es:
>> if (condiciones)
(operaciones)
end
Las operaciones se realizaran unicamente si se cumplen las condiciones especificadas.
Se admiten las ramificaciones multiples como puede verse en el siguiente ejemplo:
>> if n <0
a=1;
elseif n<5
a=2;
else
a=3;
end

1.6. Ficheros ejecutables


En esta seccion introducimos los conceptos basicos para crear ficheros ejecutables. Los
ficheros ejecutables son ficheros de texto que incluyen una serie de comandos MATLAB.
30

Si una tarea MATLAB la vamos a ejecutar muchas veces, es buena idea escribir un fichero
con estos comandos para poder ejecutarlos tantas veces como queramos.
La edicion del fichero ejecutable la realizamos con un editor cualquiera. Si nos resulta
mas comodo, podemos utilizar el editor que incorpora MATLAB y al que invocaremos
desde la lnea de comandos como:
>>edit
Los ficheros ejecutables de MATLAB (llamados ficheros M) deben tener como exten-
sion .m. En el ejemplo que damos a continuacion, crearemos un programa que calcula
el factorial de 6:
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%Este es un programa no muy util,
%que calcula el factorial de 6
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
n=6; fac=1; for i=2:n
fac=fac*i;
end fac
Si guardamos esto en el fichero fac.m en el directorio de trabajo (o cualquier otro
incluido en el path) y tecleamos el comando fac, obtenemos
>> fac

fac =

720

Las lineas tras el smbolo % son lneas de comentario, que se conviene utilizar como
explicacion del programa. El comando help sirve para mostrar esas lneas:
>> help fac

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Este es un programa no muy util,
que calcula el factorial de 6
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
31

En efecto, este no es un programa muy util, en primer lugar porque el propio MAT-
LAB tiene su comando para calcular el factorial de numeros enteros:

)) factorial(6)

ans =

720

y en segundo lugar porque nuestro programa solo calcula el factorial de 6. Para poder
calcular el factorial para distintos numeros deberemos crea una subrutina o funcion MAT-
LAB.

1.7. Subrutinas
Si ahora escribimos en un fichero con nombre facf.m los siguientes comandos

%Esta es una funcion para calcular


%el factorial de n.
%El valor de entrada es n
function fac=facf(n) fac=1; for i=2:n
fac=fac*i;
end

habremos definido una funcion que podemos utilizar tal como lo hacemos con los comandos
intrnsecos de MATLAB. Por ejemplo, tecleando en la linea de comandos facf(6) tenemos:

>> facf(6)

ans =

720

Las funciones pueden tener varios parametros de entrada y/o salida. Por ejemplo,
la siguiente es una funcion que, dados dos vectores con la misma longitud, devuelve dos
valores (es decir, la subrutina implementa una funcion f : Rn Rn R2 ).
32

%Esta es una funcion que, dados


%dos vectores de la misma longitud
%calcula dos valores reales a y b
%a=sin(x*y), b=a*x*x
function [a,b]=funci(x,y) a=sin(x*y); b=a*x*x;

Guardamos este fichero como funci.m y, como prueba, ejecutamos en la lnea de


comandos:

>> x=1:1:5

x =

1 2 3 4 5

>> y=0:0.1:0.4

y =

0 0.1000 0.2000 0.3000 0.4000

>> [f1,f2]=funci(x,y);
>> f1

f1 =

-0.7568

>> f2

f2 =

-41.6241

Por supuesto, si las matrices de entrada x e y no son vectores de la misma longitud,


el programa puede fallar. En el siguiente ejemplo, la primera llamada a funci es correcta,
pero no as la segunda:
33

>> [a,b]=funci(1:1:5,0:1:4);
>> [a,b]=funci(1:1:5,0:1:5);
??? Error using ==> * Inner matrix dimensions must agree.

Error in ==> c:\matlab\temporal\funci.m On line 6 ==>


a=sin(x*y);

Importante:

Fijemonos que la sintaxis de las rutinas es:

function [output1,output2,...]=nombre(input1,input2,...)

Si queremos crear un fichero independiente que contenga a la rutina, el nombre que


asignemos al fichero debe ser el mismo que el de la rutina con extension .m.

Por supuesto, las funciones as definidas pueden ser utilizadas tantas veces como sea
necesario dentro de otras funciones y programas.
Una norma muy conveniente que conviene seguir es sera escribir todos los progra-
mas en ficheros de texto (utilizando un editor simple) y procurar que estos sean lo mas
estructurados posibles, utilizando subrutinas (funciones) para implementar tareas inde-
pendientes. Se trata de programar de la forma mas modular y estructurada posible.

1.8. Cadenas de texto, mensajes de error, entradas


Se pueden introducir cadenas de texto en MATLAB si van entre comillas simples.
Por ejemplo, la instruccion

>> s=Mi asignatura preferida es Calculo Numerico

asigna a la variable s la anterior cadena de texto.


Se pueden mostrar cadenas de texto utilizando la funcion disp. Por ejemplo:

>> disp(En particular, me encantan las practicas de la asignatura)

Los mensajes de error pueden (deben) mostrarse utilizando la funcion error


34

>> error(Fue un error no acabar las memorias a tiempo)

puesto que cuando se utiliza en un fichero .m, interrumpe la ejecucion del mismo.
Podemos, asimismo, en un fichero .m pedir que un usuario introduzca datos de
forma interactiva utilizando la funcion input. Cuando, por ejemplo, durante la ejecucion
de un programa aparece la lnea

>>ifaltas =input(Cuantas veces has faltado a practicas?)

el citado mensaje de texto aparece en pantalla y la ejecucion del programa se interrumpe


hasta que el usuario teclea el dato de entrada. Despues de presionar la tecla de return,el
dato es asignado a la variable ifaltas y se reanuda la ejecucion del programa.

1.9. Comparando la eficiencia de algoritmos: cputime


Una forma adecuada de determinar la eficiencia de un algoritmo es medir el tiempo
de CPU transcurrido en la ejecucion del mismo. Este tiempo puede obtenerse utilizando
el comando cputime.
De hecho, la secuencia

>> cpu1=cputime, (cualquier conjunto de operaciones), cpu2=cputime-cpu1

nos proporcionara el tiempo de cpu invertido en la ejecucion del mencionado conjunto de


operaciones.

1.10. Formatos de salida


Mientras que todos los calculos en MATLAB se realizan en doble precision, el formato
de los datos de salida puede ser controlado con los siguientes comandos:

f ormat short Punto fijo y 4 decimales (es el que hay por defecto)
f ormat long Punto fijo y 14 decimales
f ormat short e notacion cientfica con 4 decimales
f ormat long e notacion cientfica con 14 decimales
35

1.11. Graficos
Aunque ya hemos mencionado anteriormente la utilizacion del comando plot, vamos
a dar en esta seccion algun detalle adicional sobre las posibilidades graficas de MATLAB.
MATLAB permite generar representaciones graficas de curvas en 2D y 3D. Los co-
mandos basicos con los que nos manejaremos seran plot, plot3, mesh y surf.

1.11.1. Representaciones en 2D
El comando plot crea graficos de curvas en el plano x-y; si x e y son vectores de la
misma longitud, el comando plot(x,y) abre una ventana grafica y dibuja en el plano x-y
los elementos de x versus los elementos de y. Podemos, por ejemplo, dibujar el grafico de
la funcion seno en el intervalo -4 a 4 con los siguientes comandos:

x=-4:.01:4; y=sin(x); plot(x,y)

El vector x es una particion del dominio en intervalos de longitud 0.01; el vector y es


un vector que proporciona los valores del seno en los nodos de la particion.
2
Como segundo ejemplo vamos a dibujar el grafico de y = ex en el intervalo -1.5 a
1.5:

x=-1.5:.01:1.5; y=exp(-x.^2); plot(x,y)

Demonos cuenta de que la operacion de elevar al cuadrado esta precedida por un


punto para que opere sobre cada una de las componentes del vector x.
MATLAB posee ademas la utilidad fplot para representar de forma eficiente y sim-
ple el grafico de una funcion: para representar el ejemplo anterior podemos, de forma
alternativa, definir la funcion en un fichero M (que llamaremos, por ejemplo, expcu.m):

function y=expcu(x) y=exp(-x.^2)

Entonces el comando

fplot(expcu,[-1.5,1.5])

nos proporcionara el grafico en cuestion.


Podemos generar tambien graficos de curvas definidas parametricamente. Por ejem-
plo,
36

t=0:.001:2*pi; x=cos(3*t); y=sin(2*t); plot(x,y)

De forma complementaria, podemos asignar a los graficos: ttulos, etiquetas en los


ejes y texto (en la zona del grafico). Para ello utilizaremos los comandos

title ttulo del grafico


xlabel etiqueta del eje x
ylabel etiqueta del eje y
gtext situa texto sobre el grafico utilizando el raton
text situa texto en las coordenadas especificadas
Ejemplo, el comando:

title(Hola caracola)

proporciona al grafico el ttulo en cuestion.


Los ejes del grafico son, por defecto, autoescalados. Para modificar esto podemos
utilizar el comando axis:

axis([xmin,xmax,ymin,ymax])

El comando axis debe utilizarse despues de plot.


Es posible realizar distintas representaciones en un mismo grafico. Por ejemplo,

x=0:.01:2*pi;y1=sin(x); y2=sin(2*x); y3=sin(4*x);


plot(x,y1,x,y2,x,y3)

Otra posibilidad es utilizar hold. El comando hold on congela la terminal grafica


en la que estamos trabajando, de modo que se pueden superponer diversos graficos en
ella. Los ejes pueden, sin embargo, ser reescalados. El comando hold off descongela la
terminal grafica.
Dentro de las opciones graficas podemos elegir el tipo de lnea, el tipo de punto y el
color. Por ejemplo,

x=0:.01:2*pi;y1=sin(x); y2=sin(2*x); y3=sin(4*x);


plot(x,y1,--,x,y2,:,x,y3,+)
37

dibuja una lnea discontinua y punteada, respectivamente, para los dos primeros graficos
mientras que el tercer grafico se muestra con el smbolo +. Los tipos de lnea y marca
son:
Tipos de lnea: solida (-), discontinua (), punteada (:), discontinua y punteada (-.)
Tipos de marca: punto (.), mas (+), estrella (*), crculo (o), x (x)
Se pueden especificar colores para los distintos tipos de lnea y marca:
Colores: amarillo (y), magenta (m), rojo (r), verde (g), azul (b), blanco (w), negro
(k)
El comando subplot puede utilizarse para hacer una particion de la terminal grafica,
de modo que pueden situarse varios subgraficos en una misma figura.

1.11.2. Representaciones en 3D
Graficos de lnea
El comando plot3 en 3 dimensiones es el analogo al comando plot en 2 dimensiones:
produce curvas en el espacio tridimensional. Si x, y y z son vectores del mismo tamano,
entonces el comando plot3(x,y,z) producira un grafico de perspectiva de la curva en el
espacio tridimensional que pasa por los puntos especificados por x, y y z. Estos vectores
suelen estar definidos de forma parametrica. Por ejemplo,

t=.01:.01:2*pi; x=cos(t); y=sin(t); z=t.^3; plot3(x,y,z)

proporciona una helice que esta comprimida cerca del plano x-y.

Graficos de malla y de superficie


Pueden obtenerse graficos tridimensionales mallados de superficies utilizando el co-
mando mesh. Si tecleamos mesh(z) obtenemos un grafico de perspectiva tridimensional
de los elementos de la matriz z. La superficie representada esta definida por las coorde-
nadas z de los puntos sobre un retculo rectangular en el plano x-y. El siguiente ejemplo
muestra un grafico de estas caractersticas de los elementos de la matriz identidad 10 10
(comando eye(10)):

mesh(eye(10))

Analogamente pueden obtener graficos tridimensionales compactos de superficies


utilizando el comando surf:
38

surf(eye(10))

Para dibujar el grafico de una funcion z = f (x, y) sobre un rectangulo debemos,


en primer lugar, definir vectores xx e yy que proporcionan particiones sobre los lados
del rectangulo. Con la funcion meshgrid creamos una matriz x, cada fila de la misma
contiene las componentes del vector xx y cuyo numero de columnas es igual a la longitud
del vector yy. De manera analoga creamos la matriz y, cuyas columnas contienen las
componentes del vector yy. Esto lo conseguimos con la instruccion:

[x,y]=meshgrid(xx,yy);

Una vez hecho esto, obtenemos la matriz z haciendo actuar f sobre las matrices x
e y. La representacion de la matriz z se puede hacer acudiendo a los comandos mesh y
surf.
Veamos un ejemplo:
2 2
Vamos a dibujar el grafico de z = ex y sobre el cuadrado [2, 2] [2, 2] del
siguiente modo:

xx=-2:.2:2; yy=xx; [x,y]=meshgrid(xx,yy); z=exp(-x.^2-y.^2);


mesh(z)

Las caractersticas del comando axis introducido previamente son aplicables tambien
a los graficos tridimensionales, as como lo son las de los comandos para ttulos, etiquetado
de ejes y el comando hold.
El color de las superficies se ajusta utilizando el comando shading. Hay 3 opciones
para este comando: faceted (el que esta por defecto), interpolated y flat. Se accede a
estas opciones tecleando:

shading faceted, shading interp, shading flat

El comando shading debe introducirse despues del comando surf. La utilizacion de


shading interp y shading flat causa la desparicion del mallado en la superficie.
El perfil de colores de una superficie se controla mediante el comando colormap.
Mapas de colores predefinidos son:

hsv (por defecto), hot, cool, jet, pink, copper, flag, gray, bone

Por ejemplo, el comando colormap(cool) proporciona un determinado perfil de col-


ores en la figura en cuestion.
39

1.12. Resumen de funciones elementales y matrices


especiales
En la tabla que se muestra a continuacion se presentan algunas funciones de MATLAB
que nos pueden ser de utilidad:

abs valor absoluto o modulo


sqrt raz cuadrada
real parte real
imag parte imaginaria
conj complejo conjugado
exp exponencial
log logaritmo natural
log10 logaritmo en base 10
sin, asin, sinh, asinh seno, arcseno, seno hiperb., arcseno hiperb.
cos, acos, cosh, acosh idem para el coseno
tan, atan, tanh, atanh idem para la tangente
cot, acot, coth, acoth idem para la cotangente
sec, asec, sech, asech idem para la secante
csc, acsc, csch, acsch idem para la cosecante

Finalmente, algunas matrices especiales de MATLAB:

zeros matriz de ceros


ones matriz de unos
eye identidad
diag diagonal
rand numeros aleatorios distribuidos unif.
40
Parte II

Introduccion a la construccion de
algoritmos

41
Captulo 2

Sistemas de numeracion; errores y


sus fuentes

En este tema se introducen los distintos sistemas de numeracion y se describe como


realizar la conversion entre distintos sistemas, as como el estandar IEEE de representacion
de numeros en el sistema binario. A continuacion, se introducen las nociones de error abso-
luto y relativo y se analizan las causas mas frecuentes de error en un calculo computacional,
ilustrandolo con ejemplos. Finalmente, se introducen los conceptos de (in)estabilidad y
condicion.

2.1. Sistemas de numeros y conversiones


Es necesario conocer como se representan los numeros enteros y decimales en forma-
to digital para entender las limitaciones intrnsecas que nos encontraremos al programar
un algoritmo numerico, tanto en cuanto a la mayor precision alcanzable como en cuanto
al rango de valores admisibles. Veremos ademas como un mnimo conocimiento del sis-
tema de representacion estandar sirve para evitar la aparicion de desastrosos errores de
programacion (como bucles infinitos).

2.1.1. Sistemas de numeracion en base q


El sistema de numeracion decimal es el sistema posicional de numeracion mas uti-
lizado, que utiliza como base de numeracion el 10 (dgitos 0...9). Como es bien sabido, se
puede utilizar cualquier numero natural mayor que 1 como base de numeracion.

43
44

Un numero en base q se denota como (an an1 ...a1 a0 .b1 b2 ...bk ...)q donde ai y bj pertenecen
al conjunto de los q dgitos elementales 1 . Estos q dgitos representaran valores desde 0
hasta q 1. La conversion a decimales es, por definicion:

(an an1 ...a1 a0 .b1 b2 ...bk ...)q = an q n + an1 q n1 + ... + a1 q + a0 q 0


(2.1)
+b1 q 1 + b2 q 2 + ... + bk q k + ...
El sistema natural de numeracion digital es el binario (base 2), utilizando solo los
dgitos 0 y 1.

Ejemplo 2.1.1. Decimal: (123.25)10 = 1 102 + 2 101 + 3 100 + 2 101 + 5 102 .

Binario (base 2) con 2 dgitos 0 y 1: 0 + 1 = 1, 1 + 1 = 10.

(1011.01)2 = 1 23 + 0 22 + 1 21 + 1 20 + 0 21 + 1 22 = 11.25.

Hexadecimal (base 16) tiene 16 dgitos: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E y F ,


que representan los valores desde 0 hasta 15 respectivamente. Por tanto:

(7B.4)15 = 7 161 + B 160 + 4 161 = 123.25.

Los sistemas de numeracion octal y hexadecimal, tambien son muy utilizados, en


parte debido a que es muy sencilla su conversion a binario con la ventaja de que un
mismo numero se representa con menos cifras cuanto mayor es la base.

2.1.2. Conversion de base decimal a base q


Ya sabemos como convertir un numero en base q a base decimal (2.1). La conversion
de base decimal a base q se base en el hecho de que, acudiendo a la definicion (2.1)
observamos que (eliminamos el subndice 10 para numeros en base decimal):

(an an1 ...a1 a0 .b1 b2 ...bk ...)q q = (an an1 ...a1 a0 b1 .b2 b3 ...bk ...)q
(2.2)
(an an1 ...a1 a0 .b1 b2 ...bk ...)q q 1 = (an an1 ...a1 .a0 b1 b2 ...bk ...)q
1
Vamos a utilizar el punto decimal (.) en lugar de la coma decimal ( ) para ser consistentes con los
ejemplos MATLAB.
45

Utilizaremos esto para obtener la conversion de un numero en base 10 a base 2. Para


esto, conviene separar la conversion de la parte entera (antes del punto decimal) de la
fraccionaria (despues del punto); observemos que un numero entero es necesariamente
entero en cualquier base y que un numero fraccionario lo es en cualquier base.

Conversion entera
De (2.2) deducimos que:

(an ...a0 )q 1 = (an ...a1 )q + (.a0 )q


es decir, que

(an ...a0 )q = (an ...a1 )q q + (.a0 )q q = (an ...a1 )q q + (a0 )q (2.3)

que es una identidad entre numeros, que podemos evaluar en cualquier base, y en par-
ticular en base 10 (observese que de hecho mezclamos base numeros en distintas bases).
Vemos pues que al dividir un numero entero entre q el resto es el dgito menos significativo
del numero en base q. Dividiendo sucesivamente (hasta llegar al cociente 0) obtenemos
los sucesivos dgitos del numero en base q.

Conversion fraccionaria
A partir de (2.2) vemos que:

(.b1 b2 ...bk )q q = (b1 )q + (.b2 ...bk )q


Vemos pues que la parte entera del resultado de multiplicar nuestro numero por q
es el primer dgito tras el punto decimal. Reteniendo la parte fraccionaria que resulta en
cada paso y repitiendo sucesivamente el proceso, vamos obteniendo el resto de cifras tras
el punto.

Ejemplo 2.1.2. Escribamos (26.1)10 en base 2.

1. Parte entera. Dividiendo sucesivamente, tenemos que:

26 = 2 13 + 0 ; 13 = 2 6 + 1 ; 6 = 2 3 + 0 ; 3 = 2 1 + 1 ; 1 = 2 0 + 1

Leyendo de izquierda a derecha los numeros subrayados: (26)10 = (11010)2


46

2. Parte fraccionaria. Multiplicando sucesivamente por dos y separando la parte frac-


cionaria:

0.12 = 0.2 ; 0.22 = 0.4 ; 0.42 = 0.8 ; 0.80.2 = 1.6 ; 0.62 = 1.2 ; 0.22 = ...

Leyendo de izquierda a derecha tenemos los dgitos de la parte fraccionaria (sub-


rayados) luego:
(0.1)10 = (0.00011)2
donde las cifras subrayadas son las cifras periodicas.
Observese que el numero 0.1 tiene infinitas cifras distintas de cero cuando se escribe
en base 2 (se repiten indefinidamente desde la segunda a la quinta cifra fraccionaria).

Sumando los resultados de la parte entera y la fraccionaria tenemos que

(26.1)10 = (11010.00011)2

En el anterior ejemplo hemos aprendido que un numero fraccionario con un numero


finito de dgitos en cierta base no tiene por que tener un numero finito en otra base. En
efecto, (0.1)10 es un numero periodico con infinitas cifras cuando se escribe en base 2. Esto
es importante puesto que en un procesador digital los numeros se almacenar en binario
utilizando un numero finito de cifras. Esto quiere decir que el numero 0.1 no se representa
exactamente en un ordenador. Esto hay que tenerlo en cuenta para evitar errores que
conduzcan a bucles que se repiten indefinidamente. El siguiente algoritmo en Matlab es
un ejemplo de bucle infinito,

Algoritmo 2.1. Bucle infinito en precision finita binaria:


x=0;
while x=10 (Nota: en Matlab esto significa x 6= 0)
x=x+0.1;
end

Esto nos debera prevenir de utilizar bucles que terminan cuando se alcanza cierto
valor concreto de una variable que involucra numeros no enteros.

Ejercicio 2.2. Si en la tercera lnea del anterior algoritmo cambiamos 0.1 por 0.125,
seguiramos teniendo un bucle infinito?.
47

2.1.3. Estandar IEEE de representacion de numeros enteros y


en coma flotante
Numeros enteros
Asumamos, como es comun en la mayor parte de los procesadores, que cada palabra
tiene una longitud de 32 bits, es decir, que cada numero vendra representado por 32
dgitos binarios. La forma mas sencilla de representar un numero entero es asignando uno
de los 32 bits para designar el signo (0 para +, 1 para menos) y utilizando las 31 restantes
posiciones para representar los dgitos del modulo del numero entero. En consecuencia, el
mayor numero entero que se puede representar es 231 1.
Este es el estandar IEEE salvo porque, por lo general, no se suele reservar un bit para
el signo, sino que se utiliza una ordenacion distinta para guardar los enteros negativos.
Sin embargo, en la practica una y otra prescripcion son practicamente equivalentes.
Tambien pueden utilizarse enteros en longitud doble, utilizando dos palabras de 32
bits, con lo que se aumenta el rango de enteros admisibles.

Numeros no enteros
Para representar numeros con parte fraccionaria se utiliza el formato de punto (o
coma) flotante. Esta representacion es la correspondiente version binaria de la conocida
notacion cientfica o exponencial para los numeros decimales:

M 10E , 1 M < 10
pero utilizando base 2:
x = M 2E , 1 M < 2
donde M es la mantisa y E el exponente. Inevitablemente el numero de dgitos que se
pueden almacenar de la mantisa y exponente es limitado. Hay dos tipos de precision, la
simple y la doble, que difieren en el numero de bits de los que se dispone para almacenar
las cifras; la distribucion estandar es:

1. Precision simple: 32 bits, de los cuales:

a) uno corresponde al signo,


b) 8 al exponente, luego 128 E 127 (2 128 = 28 )
c) 23 a la mantisa
48

2. Precision doble

a) uno para el signo


b) 11 al exponente (1022 E 1023)
c) 52 para la mantisa

Ejemplo 2.1.3. Veamos de forma simplificada como se guardara el numero 5.5 en pre-
cision simple. Primero lo pasamos a binario: 5.5 = (101.1)2 y normalizamos para que la
mantisa 1 < M 2, de forma que 5.5 = (1.011)2 22 , que tiene exponente E = 2 (que
se guardara en binario), signo + (bit 0) y mantisa 1.011. Normalmente, salvo para el
caso del numero cero, que se almacenan de distinta forma, el numero delante del punto
sera siempre 1, por lo que no se suele almacenar.

Ejemplo 2.1.4. El anterior es un ejemplo de un numero decimal que se puede guardar


de forma exacta en una palabra de 32 bits. Un ejemplo en el que esto no sera as es
el ya conocido caso de 0.1 = (0.00011)2 = (1.1001)2 24 , que necesariamente ha de
redondearse antes de almacenarse; esquematicamente (sin entrar en detalles de como se
almacena el exponente), tendramos, en precision simple, la representacion (recordemos
que el 1 antes del punto decimal no se suele almacenar)

0|E = 4|10011001100110011001101

donde la 23a cifra tras el punto se ha redondeado a 1 porque la siguiente era 1. De esta
forma, lo que realmente se almacena es:

(1.10011001100110011001101)2 24 = 0.10000000149011611938

Esto muestra explcitamente que, efectivamente, el algoritmo 2.1 es un bucle infinito.

Debemos resaltar que la especificacion del numero de bits que se utilizan para al-
macenar mantisa y exponente es lo unico que necesitamos para determinar cuales son
los mayores y menores numeros que se pueden almacenar en coma flotante as como la
maxima precision que se puede obtener. Veamos como obtener estos parametros en el caso
de doble precision (que es la precision utilizada por Matlab).

Ejemplo 2.1.5. Obtener los numeros de overflow y underflow as como la precision


maquina en doble precision, es decir:
49

1. Obtener el mayor numero entero positivo representable en formato de coma flotante


en el caso de doble precision (lmite de overflow)
Puesto que el mayor exponente es 1023, el mayor numero representable es (1.1....1)2
21023 1.8 10308 (hay 52 unos detras del punto decimal).

2. Obtener el menor numero entero positivo representable en formato de coma flotante


en el caso de doble precision (lmite de overflow). El menor decimal representable
con 52 dgitos significativos binarios es (1.00...01)2 101022 2.2310308 . Sin em-
bargo, el estandar IEEE admites numeros mas pequenos, aunque tengan menos cifras
significativas (es lo que llaman numeros sub-normales); estrictamente el numero
mas pequeno representable en coma flotante es: (0.00..01)2 21022 = 21074
4.94 10324 (52 dgitos tras la coma decimal). Para no perder dgitos significativos
es mejor moverse en el rango (1/Nov , Nov ), donde Nov es el numero de overflow
Nov 2.23 10308 .

3. Obtener la diferencia entre 1 y el menor numero positivo mayor que 1 en coma


flotante (epsilon-maquina).
El numero que se nos pide es (1.0...01)2 (1.0...0)2 = (0.0...01)2 = 252 2.2
1016 . Este numero representa el mejor error relativo que se puede manejar en
doble precision (definimos este conocido concepto a continuacion). Este valor de
epsilon-maquina significa que todos los numeros con 15 cifras significativas se pueden
guardar de forma exacta en doble precision y que ocurre lo mismo para la mayor
parte de los numeros de 16 cifras.

Nota 2.3. Es importante tener en cuenta que MATLAB trabaja en doble precision2
aunque por defecto solo muestre 5 cifras significativas. Para que el sistema muestre mas
cifras se puede utilizar el comando format long.

Ademas de los detalles senalados hay otras caractersticas fundamentales del estandar
IEEE que no describiremos como son:

1. Redondeo correcto de la aritmetica (volveremos mas adelante sobre este punto)3 .


2
La version 7.0 ya permite trabajar en precision simple y con aritmetica entera, aunque doble precision
sigue siendo la disponible por defecto.
3
Un error en el hardware de punto flotante de los Intel Pentium (1994) le dio una considerable mala
publicidad a la compana. El problema fue solventado reemplazando los procesadores defectuosos
50

2. Tratamiento de excepciones. Es decir, que un operacion del tipo log(0.0) no da error


e interrumpe la ejecucion del programa, sino que se asigna un valor especial para
representar esta excepcion (para significar ).

3. Compatibilidad entre procesadores. Esta es por supuesto, una de las grandes ven-
tajas de los estandares.

2.2. Errores y sus causas


El analisis numerico trata de la construccion de metodos discretos para la resolucion
de problemas continuos. Esta discretizacion, que se presenta tanto en la representacion
numerica en un ordenador como en los propios algoritmos de calculo, necesariamente
implica la aparicion de errores cuyo origen y propagacion debemos estudiar 4 .

2.2.1. Definiciones
Si xA es una aproximacion del verdadero valor xT , definimos entonces:

Error absoluto: Eabs = |xT xA |

xA
Error relativo: Erel = |1 |, si xT 6= 0.
xT
Tambien se pueden utilizar estas definiciones con signo (es decir, sin el valor absoluto).
El error relativo en ocasiones se expresa tambien en tanto por ciento.

2.2.2. Fuentes de errores


Las fuentes de error en un calculo numerico pueden ser de variada naturaleza, algunas
de ellas independientes del metodo numerico empleado.

1. Un metodos numerico para resolver determinado problema cientfico puede dar lugar
a resultados erroneos si el modelo no es una fiel descripcion de la realidad.
4
No por ello se debe adoptar la vision reduccionista consistente en definir el analisis numerico como
el area de la matematica que analiza los errores de calculo
51

2. Un algoritmo numerico puede depender de ciertos datos de entrada (por ejemplo,


datos fsicos) afectados de cierto error. Se debe vigilar que el metodo numerico no
sea crucialmente dependiente de la exactitud de tales valores de entrada y que la
precision de estos valores sea suficiente para nuestros propositos. En el caso en que
el propio modelo fsico/matematico sea muy sensible a estos parametros, tendremos
un problema mal condicionado e imposible de resolver numericamente de forma
estable.
3. Los errores de programacion son practicamente inevitables durante la construccion
de un metodo numerico. Una vez construido un algoritmo numerico que en aparien-
cia funciona correctamente es necesario certificar su funcionamiento mediante todos
los tests que esten a nuestro alcance.
4. Errores en la aritmetica de punto flotante: errores de redondeo, perdida de cifras
significativas por cancelaciones, problemas de underflow/overflow. Estos son los
problemas derivados de la representacion en punto flotante, en la cual se dispone de
un numero finito de bits para representar la mantisa y el exponente. Como ya vimos,
esto limita tanto la mejor precision relativa alcanzable (15-16 dgitos decimales en
doble precision) como el rango de valores disponible.
Aunque la segunda de las limitaciones no suele presentar graves problemas, es nece-
sario evitar la evaluacion de cantidades demasiado grandes o pequenas.
La limitacion de la precision tiene por lo general mayores consecuencias. Por ejem-
plo, cuando se sustraen cantidades muy parecidas, el error relativo empeora drasti-
camente por perdida de cifras significativas.
5. Errores de truncamiento o de discretizacion, inherentes al hecho de aproximar un
problema continuo mediante una aproximacion discreta. Por ejemplo, veremos que
la regla trapezoidal sirve para aproximar integrales mediante:

b N 1
h ba
Z X
f (x)dx (f (a)+f (b))+h f (a+kh) S(h) , donde h = , h = (b1)/N
a 2 k=1
N

El significado de es aproximadamente, lo cual significa que


Z b
f (x)dx = S(h) + (h)
a
52

donde (h) es el error de truncamiento, que es de esperar que sea menor cuanto menor
sea h (N N lo mayor posible). Un calculo explcito de los errores de truncamiento
es al menos igual de difcil que el calculo del problema original. Nos conformaremos
con un conocimiento cualitativo de estos errores y con buscar acotaciones lo mas
finas posible.

Trataremos de estimar los errores de truncamiento en cada algoritmo numerico que


se presente.
Discutamos en este punto acerca de los errores debidos a las limitaciones en la repre-
sentacion de punto flotante, en particular por lo que respecta a la precision limitada del
sistema

Redondeo y perdida de cifras significativas


Puesto que la representacion en coma flotante es limitada en cuanto al numero de
cifras significativas que se pueden almacenar, los numeros reales se redondearan a un de-
terminado numero de cifras (siempre utilizando el sistema de numeracion binario) cuando
el valor verdadero tenga mas cifras de las que se pueden almacenar.
Asimismo, tras cada operacion aritmetica se vuelve a redondear el resultado. En el
estandar IEEE esto se hace de la mejor manera posible en el sentido de que el resultado de
la operacion aritmetica esta redondeado de forma que se almacena el valor mas proximo
al resultado exacto. As, por ejemplo, supongamos que, para simplificar, la precision fuese
de tres dgitos binarios tras el punto (y no consideremos limitacion en el exponente),
si se suman los numeros en punto flotante x = (1.010)2 , y = (1.001)2 24 tenemos
que el resultado exacto es (1.0101001)2 que no sera un numero en punto flotante (solo
disponemos de 3 posiciones tras el punto). El resultado IEEE sera redondear la ultima
cifra, aumentandola si la siguiente fuese 1 y dejandola como esta en otro caso. As, x + y
se almacenara como (1.011)2 .
Otra posibilidad (menos recomendable) es, sin mas, eliminar las cifras que no quepan
(truncamiento). Esta desafortunada prescripcion se utilizaba en los supercomputadores
Cray, pero esta en total deshuso.
Aun cuando en el estandar IEEE se redondea al numero en coma flotante mas cercano,
que es la opcion mas conveniente, es necesario estudiar como pueden afectar sucesivos
redondeos al resultado de un algoritmo numerico.
Por otra parte, la limitacion en el numero de bits para la mantisa tiene como conse-
cuencia la posible perdida de cifras significativas en ciertos calculos donde dos cantidades
53

tienden a cancelarse entre s 5 . Para evitar este tipo de errores, es recomendable:

a) O bien reescribir la formula en cuestion de modo que se eviten las restas de cantidades
de la misma magnitud.
b) O bien utilizar (cuando sea posible) un desarrollo de Taylor para aproximar la formula
hasta la precision requerida.

Veamos algunos ejemplos en los que se da perdida de cifras significativas


Ejemplo 2.2.1. Obtener las races de x2 106 x + 1.
En una
modesta calculadora con 10 decimales y aplicando la archiconocida formula
x = b 2ab2 4ac , vamos obteniendo los resultados:

106 1012 4 106 106
x=
2 2
que da x = 106 para la mayor raz y x = 0 para la menor. Es evidente que hemos perdido
todas las cifras significativas para la menor raz. De hecho, la famosa formula debera ser
desterrada de cualquier metodo numerico. Es mucho mejor reescribir la solucion de la
ecuacion de segundo grado como:

x1 = L/2a , x2 = 2c/L , L = b signo(b) b2 4ac
De esta forma la mayor raz es como antes y en la calculadora la menor saldra x = 106 ,
cuyo error relativo respecto a la solucion verdadera es 1012 .

Ejemplo 2.2.2. Consideremos por ejemplo f (x) = ( x + 1 x) para x > 0. Cuando x
esgrande, se producen errores de redondeo importantes puesto que los valores de x + 1
y x se aproximan considerablemente. Como evitaramos esta fuente de error?. Lo que
podemos hacer es reescribir f (x) del siguiente modo:

x+1+ x 1
f (x) = ( x + 1 x) = .
x+1+ x x+1+ x
En la expresion resultante podemos apreciar que no se producen cancelaciones de
cantidades de la misma magnitud.
5
Un famoso y lamentable error de este tipo fue el que motivo le fallo de los misiles Patriot para derribar
los misiles Skud iraques durante la guerra del golfo: se medan intervalos de tiempo restando tiempos
desde el reinicio del sistema con la consiguiente perdida progresiva de precision
54

1 cos(x)
Ejemplo 2.2.3. Consideremos g(x) = . Cuando se evalua g(x) para |x| << 1
x2
se produce una perdida considerable de cifras significativas. En este caso, para remediar
el problema consideramos el desarrollo de Taylor de cos(x) entorno a 0. De este modo:

1 [1 x2 /2! + x4 /4! + ...] 1 x2 x4


g(x) = + .
x2 2 4! 6!
Esta expresion es apropiada entonces para evaluar g(x) cuando x << 1.

Errores de overflow /underflow


Aunque los lmites de overflow/underflow son considerablemente generosos, conviene
escribir las expresiones que se utilicen de manera que se minimice esta posibilidad. Por
ejemplo,
p es preferible calcular el modulo de un numero complejo, z = x + iy, |z| =
x2 + y 2 , como
p
|z| = |x| 1 + (y/x)2
De esta forma, no hay que elevar al cuadrado numeros que pueden ser muy grandes. De
la misma forma, hay que tomar precauciones para calcular la argumento de un numero
complejo de manera que no se produzcan overflows/underflows en el calculo de y/x.

Ejercicio 2.4. Escribir un programa en Matlab que obtenga la representacion polar de


un numero complejo dado z = rei , 0 < 2, eliminando el riesgo de problemas de
overflow-underflow.

2.3. Propagacion de errores: condicion y estabilidad.


Un error en un calculo numerico contamina las sucesivas evaluaciones. Esta propa-
gacion del error puede describirse en terminos de dos conceptos relacionados, los de
(in)estabilidad y condicion.
La condicion de una funcion f (x) mide la sensibilidad de los valores de f (x) a
pequenos cambios en x y se define como

Erel (f (x))
C =
Erel (x)
donde Erel (f (x)) es el error relativo de f (x) para un error relativo Erel (x) en x.
55

6
Entonces, como

f (xT )
f (xT ) f (xA ) f (xt )(xT xA ) Erel (f (x)) (xT xA )
f (xT )
luego
f (xT )
C xT

f (xT )
Utilizaremos esta ultima expresion como definicion de condicion para funciones f (x)
de una variable real. Definimos entonces los numeros de condicion como

f (x)
C(x) = x
f (x)
Cuando para un x dado 0 < C(x) < 1 para ese x se dira que el problema (calculo
de f) esta bien condicionado (y cuanto menor sea C mejor condicionado), mientras que si
C(x) > 1 el problema estara mal condicionado. Si C(X) = 1, el error relativo se mantiene.

Ejemplo 2.3.1. La funcion f (x) = x esta bien condicionada, pues C(x) = 1/2, luego
el error relativo se reduce.
2

En cambio f (x) = x2 1 esta mal condicionada para x 1 pues C(x) = 22x

x 1
El concepto de condicionamiento se puede extender a situaciones mas generales que la
de una funcion de una variable continua. Por ejemplo, un problema clasico que involucra
funciones de una variable discreta, es el estudio del condicionamiento de relaciones de
recurrencia:

Ejemplo 2.3.2. Las funciones de Bessel Jn (x) satisfacen la relacion de recurrencia:


Jn+1 (x) = Jn1 (x) + 2n x Jn (x), pero como las funciones de Bessel de segunda especia
cumplen la misma relacion y lmn Jn (x)/Yn (x) = 0, el calculo de las funciones Jn a
partir de J0 y J1 esta mal condicionado, pues una pequena perturbacion en los datos ini-
ciales J0 y J1 contamina nuestra secuencia de funciones {Jn } con la secuencia {Yn }, que
crece mas rapido con n.
As, por ejemplo, empezando con los valores en precision simple J0 (2) = 0.22389078
y J1 (2) = 0.57672481, y aplicando la recurrencia obtenemos J8 (2) = 4.00543213 105
que no tiene bien ni siquiera un cifra significativa: J8 (2) = 2.2180 105 .
6
Recordemos el teorema del valor medio: Si g(x) continua en [a, b] y derivable en (a, b) entonces
c (a, b) : f (b) f (a) = f (c)(b a)
56

Un concepto relacionado, que no equivalente, es el de (in)estabilidad de un algoritmo,


que describe la sensibilidad de un metodo numerico especfico respecto a los inevitables
errores de redondeo cometidos durante su ejecucion en aritmetica de precision finita.
Observemos que la condicion no depende de errores de redondeo pero que la estabilidad
de un algoritmo s depende del condicionamiento de la funcion que queramos evaluar. Un
ejemplo puede servir para distinguir estos dos conceptos relacionados:

Ejemplo 2.3.3. Dada la funcion f (x) = x + 1 x, su numero de condicion es:

f (x) x
C(x) = x =
f (x) 2 x x + 1

y vemos que C(x) < 1/2 para x > 0, luego la funcion esta bien condicionada (su error
relativo es menor que el error relativo en x).
Sin embargo, el algortmo
para
calcular x consistente en ir realizando las operaciones
implicadas en f (x) = x + 1 x, a saber:

1. Input: x

2. y = x + 1

3. f1 = x + 1

4. f2 = x

5. f = f1 f2

es inestable para x grande por culpa del paso 5 (hay cancelaciones entre numeros simi-
lares). Como sabemos, un algoritmo estable lo proporciona la siguiente reescritura de la
funcion:
1
f (x) =
x+1+ x

2.4. Eficiencia de un algortmo numerico


Por supuesto, cualquier algoritmo numerico sensato debe evitar ser inestable. Por
otra parte, si existieran varios metodos para evaluar una misma funcion, entonces conven-
dra adoptar aquel metodo que sea mas eficiente, es decir, mas rapido. Con la mejora en
proporcion geometrica de la velocidad de los procesadores, podramos estar tentados en
57

despreocuparnos por la rapidez de calculo. Esta es, sin embargo, una pesima filosofa: se
trata de aprovechar los recursos para poder resolver problemas mas complejos y no para
resolver peor problemas simples. La eficiencia es y siempre sera de importancia capital en
el desarrollo de buenos metodos numericos.
La diferencia en tiempos de ejecucion pueden llegar a ser muy considerables si ciertas
operaciones elementales, que se pueden repetir miles y miles de veces, no se realizan con
cuidado. Por ejemplo, para calcular x4 para cierto valor de x, es muy mala idea calcular
x4.0 (exponente en coma flotante); hay que tener cuidado en utilizar un exponente entero
ya que los metododos de exponenciacion en coma flotante son distintos que los de enteros
y mucho mas lentos; aun es mejor idea considerar el calculo en dos pasos: x2 = x x,
x4 = x2 x2 , con lo que se economizar un producto frente a x4 = x x x x.

2.4.1. Ejemplo: Evaluacion de polinomios, metodo de Horner


Otro ejemplo notable (y por desgracia no suficientemente) conocido es la evaluacion
de polinomios. Por ejemplo, supongamos que nos planteamos evaluar el polinomio
P (x) = 2 + 4x 5x2 + 2x3 6x4 + 8x5 + 10x6
Contando con que cada potencia de exponente k entero cuente como k 1 productos,
tendramos que el numero total de productos para evaluar el polinomio de forma directa
es:

1 + 2 + 3 + 4 + 5 + 6 = 21
y el numero de sumas es 6.
Una forma mejor de proceder es ir calculando primero las potencias de forma sucesiva:
x2 = x x , x 3 = x x 2 , x4 = x x 3 , x5 = x x 4 , x6 = x x 5
con lo que solo se anade una nueva multiplicacion por potencia, par un total de
1 + 2 + 2 + 2 + 2 + 2 = 11
Pero aun se puede hacer mejor reescribiendo

P (x) = 2 + x(4 + x(5 + x(2 + x(6 + x(8 + x10)))))


con lo que solo necesitamos 6 multiplicaciones (y el numero de sumas no cambia). Vemos
pues que para evaluar un polinomio de grado n en el que ninguno de los coeficientes
58

es cero, se necesitan n(n + 1)/2 multiplicaciones por el primer metodo, 2n 1 por el


segundo y n para el tercero. De forma que se debe procurar utilizar el ultimo metodo,
particularmente cuando n es grande.
Este metodo es ademas sencillo de programa, en efecto:

Algoritmo 2.5 (Algoritmo de Horner o de division sintetica).


Algoritmo de Horner
Dado el polinomio

P (x) = a0 + a1 x + ... + an xn , an 6= 0

la evaluacion de P (x) para cierto valor x = z se puede realizar en n


pasos mediante

(1) bn = an

(2) bn1 = an1 + z bn

(3) bn2 = an2 + z bn1


...

(n) b0 = a0 + z b1

donde P (z) = b0 .

Es facil programa este algoritmo en forma de bucle, sobretodo si no nos interesan los
calculos intermedios. As, se puede escribir:

(1) b = an

(2) Repetir mientras n > 0

(3) n = n 1

(4) b = an + z b

(5) Volver a (2)

(6) p(z) = b.
59

Esta forma de evaluar polinomios es mucho mejor que el metodo directo, especial-
mente para ordenes grandes. Dependiendo del orden de un polinomio y las veces que se
repita el calculo, sera importante aplicar el metodo de Horner.
60

2.5. EJERCICIOS PRACTICOS


Introduccion a la construccion de algoritmos

El objetivo de estos ejercicios es el de poner en practica algunos conceptos introducidos


en este tema desarrollando algunos ejemplos con MATLAB.
Ejercicios:
Se propone realizar los siguientes ejercicios y responder a las cuestiones que se plantean:

1. Comprobar que el epsilon-maquina es 252 = 2.2204 1016 , tecleando en la lnea de


comandos:

>> a=1+2^(-53);b=a-1

y comparando con

>> a=1+2^(-52);b=a-1

2. Escribir la secuencia de comandos:

x=0; while x~=10


x=x+0.1
end

en un fichero (con extension .m) y ejecutarlo en MATLAB. Para interrumpir la


ejecucion, pulsar CTRL+C. Que ocurre si en lugar de incrementarse la variable en
0.1 lo hace en 0.125?. Por que?.

3. Obtener el mayor y el menor numero positivo en punto flotante (numeros de over-


flow y underflow). Para obtener el numero de overflow escribir un bucle que vaya
calculando las sucesivas potencias de 2 y que finalice cuando se produce overflow. Se
recomienda utilizar el comando isinf para detectar cuando se produce el overflow
(teclear help isinf) para obtener informacion sobre este comando. Otra instruccion
que puede resultar util es break para interrumpir el bucle cuando se produce el over-
flow. El numero de underflow se puede obtener calculando las sucesivas potencias
negativas de 2 hasta obtener un numero indistinguible del cero en punto flotante.
61

4. Escribir dos funciones MATLAB para la resolucion de ecuaciones de segundo grado


ax2 + bx + c = 0, una de ellas (que llamaremos mala.m) implementando la formula:

b b2 4ac
x=
2a
y otra (buena.m) utilizando el metodo alternativo:

x1 = L/2a , x2 = 2c/L

donde L = b signo(b) b2 4ac.
La sintaxis de la llamada a la funciones ha de ser

>> [x1,x2]=buena(a,b,c);

y similarmente para mala.m.


Discutir la ventaja de buena.m sobre mala.m escribiendo un fichero con un ejemplo
ilustrativo.

5. Escribir una rutina que implemente el algoritmo de Horner (horn.m) para la eval-
uacion de polinomios. La sintaxis de llamada a la rutina habra de ser:

>> p=horn(coefs,x);

donde p es el valor del polinomio, coefs es un vector con los coeficientes del poli-
nomio, de mayor a menor grado y x es el valor de la variable independiente. Es decir
que si, por ejemplo, hacemos:

>> p=horn([1 -5 6 2],2);

entonces en la variable p se almacenara el valor P (2) donde P (x) = x3 5x3 +6x+2.

También podría gustarte