Documentos de Académico
Documentos de Profesional
Documentos de Cultura
Ion Zaballa
1. Introducción
Aunque desarrollado con mi propio lenguaje y motivación, el contenido e ideas de esta Intro-
ducción a MATLAB está sacadas de los Capı́tulos 1 de los excelentes libros de Cleve Moler [1]
y Charle van Loan [2]. El primero está disponible por capı́tulos separados totalmente gratis en
la dirección:
http://www.mathworks.com/moler
Esta introducción a MATLAB tiene como objetivo que el/la estudiante se familiarice rápidamen-
te con algunas de las muchas posibilidades que ofrece MATLAB para trabajar las matemáticas.
La idea es presentar varios problemas que investigan algunos problemas elementales y al mismo
tiempo, espero que, interesantes de matemáticas. Quienes tengan experiencia en otros lenguajes
de programación enseguida apreciarán la potencia y sencillez de manejo de MATLAB estudian-
do estos ejemplos. Para todos, iniciados o no iniciados, se ha confeccionado una Guı́a básica de
MATLAB para el Curso de Análisis Matricial, disponible en la misma página web en la que
está esta introducción. Pero para quienes ésta sea la primera vez que tienen contacto con un len-
guaje de programación, hay multitud de manuales “on-line” y MATLAB, propiamente, dispone
de una guı́a de ayuda para empezar a trabajar:
Ejercicio 2 Tómate otros pocos minutos para ver una de las “demos” que vienen con MATLAB.
Se accede a ellas a través del menú Help que aparece en el menú principal tanto de la ventana de
comandos como de la de ayuda. Una demostración recomendable es Basic Matrix Operations
que aparece al seleccionar Mathematics en el menú principal.
1
Ejercicio 3 .- Utiliza helpwin para echar un vistazo a las funciones matemáticas elementales
de MATLAB.
1 φ−1
2. La razón áurea
Para ir aprendiendo algunos comandos de MATLAB vamos a tomar como disculpa la razón
áurea. Se trata de una práctica dirigida en la que debes ir haciendo lo que se indica para
familiarizarte con algunos comandos básicos de MATLAB.
La razón áurea aparece en muchas partes de la matemática y aquı́ veremos unas pocas. La
razón áurea toma su nombre del reactángulo áureo que se muestra en la Figura 1. Éste tiene
la propiedad caracterı́stica siguiente: al suprimir un cuadrado unidad se obtiene un rectángulo
menor con las mismas proporciones que el original. Es decir,
1 φ−1
= .
φ 1
La razón áurea es el lado de tal rectángulo. Debe ser entonces la raı́z cuadrada positiva de la
siguiente ecuación de segundo grado
φ2 − φ − 1 = 0.
Las dos soluciones de esta ecuación son
√
1± 5
φ=
2
Ejercicio 4 Asigna el valor positivo a la variable phi y calcula el valor en formato short y
long.(Indicación: Puedes utilizar el comando help format para consultar la ayuda sobre los
posibles formatos en que se presentan los números).
2
Se puede usar MATLAB para hallar las raı́ces de un polinomio. MATLAB representa los poli-
nomios como un vector: el de sus coeficientes. Ası́, el vector
representa el polinomio
p(x) = x2 − x − 1
Las raı́ces se calculan mediante la función roots:
>> r=roots(p)
produce
r =
-0.61803398874989
1.61803398874989
Ejercicio 5 Compruébalo.
Hay muchas formas de calcular la razón áurea con MATLAB. Una de ellas es definir la función
1
f (x) = − (x − 1)
x
y calcular sus ceros. Para definir una función a partir de la versión 7 de MATLAB se puede
utilizar el siguiente código
>> f=@(x)1/x-(x-1)
Ası́ queda definida f como función de x. Se pueden definir funciones de varias variables. Por
ejemplo
>> f=@(x,y)y/x-(x-y)
>>f(2,1)
3
Supongamos que tenemos definida la función f (x) = x1 − (x − 1). Queremos calcular las raı́ces
de esta función. Para ello necesitamos una estimación de donde pueden estar aproximadamente.
Una forma de obtener esta aproximación es dibujar la gráfica de esta función. El comando ezplot
lo hace
>> ezplot(f,0,4)
1/x−(x−1)
7
−1
−2
−3
0 0.5 1 1.5 2 2.5 3 3.5 4
x
1
Figura 2: Gráfica de la fucnión f (x) = x − (x − 1).
produciendo la Figura 2 sin el cı́rculito que marca el cero de la función f . Los argumentos 0 y
4 especifican el intervalo (0, 4) en el que se dibuja la gráfica. Nótese que f tiene una ası́ntota
vertical en x = 0.
>> phi=fzero(f,1.5)
se obtiene
phi =
1.61803398874989
que es una aproximación a la razón áurea tan buena como se podrı́a desear. Los comandos
>> hold on
>> plot(phi,0,’o’)
sirven para colocar un circulito en en la posición (φ, 0) en la misma figura donde se habı́a
dibujado la curva (ver la Figura 2).
4
Ejercicio 7 Escribe los comandos anteriores y comprueba los resultados. Usa la ayuda (help
hold, help plot) para saber lo que hacen dichas órdenes.
MATLAB necesita conocer de antemano los directorios donde se encuentran los programas que
quieres ejecutar. Si los programas vienen en la distribución, no hay problema, ya sabe donde
buscarlos. Pero no tiene por qué saber donde se encuentran los programas confeccionados por
cada usuario; ası́ que éste tiene tres opciones:
(a) ponerlos en la carpeta que utiliza MATLAB por defecto. Esto puede cambiar de una
versión a otra y de un sistema operativo a otro. En el momento actual Windows guarda,
por defecto, los ficheros de los usuarios en la carpeta MATLAB de Mis Documentos.
(b) colocarlos en una carpeta personal (incluyendo un “lápiz de memoria” o disquete) y añadir
esta carpeta personal al MATLAB search path, y
(c) colocarlos en una carpeta personal y cambiar el directorio de trabajo (ventana superior
izquierda) a dicha carpeta personal.
En tu propio ordenador personal cualquiera de las tres opciones es buena, pero en los ordenadores
de la Facultad, en los que muchas personas diferentes pueden usar MATLAB, no tienes garantı́as
de que un programa dejado en una carpeta del ordenador vaya a encontrarse allı́ la siguiente
vez que lo necesites. Es conveniente, por lo tanto, que cada cual venga provisto de un disquete
o “lápiz de memoria” para almacenar allı́ tus programas.
Por el momento comprueba que estás en la capeta MATLAB de Mis Documentos, y si no, cambia
a ella. Si no sabes cómo hacerlo pregúntalo.
Se abrirá, en otra ventana, el editor de MATLAB. Escribe en él las siguientes lı́neas:
5
phi = (1+sqrt(5))/2;
x = [0 phi phi 0 0];
y = [0 0 1 1 0];
u = [1 1];
v = [0 1];
plot(x,y,’b’,u,v,’b--’);
text(phi/2,1.05,’\phi’);
text((1+phi)/2,-.05,’\phi - 1’);
text(-.05,.5,’1’);
text(.5,-.05,’1’);
axis equal;
axis off;
set(gcf,’color’,’white’);
>> rectaureo
MATLAB ejecutará todos los comandos escritos en el fichero y aparecerá la Figura 1 en una
nueva ventana.
Ejercicio 8 Trata de adivinar lo que hace cada una de las lı́neas del programa y, una vez que
lo hayas conseguido (usando la ayuda o preguntando, si es necesario), responde a las siguientes
cuestiones: En los paı́ses europeos la medida estándar del papel es DIN A4. Sus dimensiones son:
210 mm de ancho y 297 mm de largo. La razón entre estas dos cantidades no es la razón áurea
pero es próxima a otro número irracional. ¿Cuál?. Si divides por la mitad una hoja DIN A4 ¿cuál
es la razón entre las dimensiones de cada una de las mitades? Modifica el fichero rectaureo.m
para ilustrar esta propiedad.
La razón áurea φ se puede obtener como una fracción continua; i.e. una expresión de la forma
1
a0 + 1 .
a1 + a2 + a 1
3 +···
6
0.8
0.6
u
0.4
0.2 60o
1
0
−0.2
−0.4 v
−0.6
−0.8
−1 −0.5 0 0.5 1
Esto permite confeccionar una función de MATLAB que genera y evalúa la fracción continua
truncada al número de fracciones que se desee. Abre un editor y escribe lo que viene a conti-
nuación. Una vez escrito, guárdalo con el nombre fracaurea.m.
function fracaurea(n)
%FRACAUREA Fraccion continua para la razon aurea.
% FRACAUREA(n) presenta n terminos de la fraccion continua
% y varias formas de evaluar la razon aurea.
p = ’1’;
for k = 1:n
p = [’1+1/(’ p ’)’];%Se debe dejar un espacio enter ’ y p y entre p y ’
end
p
p = 1;
q = 1;
for k = 1:n
s = p;
p = p + q;
q = s;
end
p = sprintf(’%d/%d’,p,q)
format long
7
p = eval(p)
format short
err = (1+sqrt(5))/2 - p
Uno de los objetivos de este curso es llegar a escribir algunas funciones y scripts en el lenguaje
de programación de MATLAB. Es importante que leas atentamente el Capı́tulo 4 de la Guı́a;
en particular, la sección 4.2. En cualquier caso vamos a analizar un poco esta función.
Todas las funciones de MATLAB son ficheros con la extensión .m y empiezan con la palabra
function. Esta es una de las diferencias con los scripts. Otra diferencia es que, suelen recibir
valores (en este caso n) y, aunque no es el caso de esta función, también suelen devolver valores
(enseguida veremos un ejemplo de función que cumple estos dos requisitos). Y una tercera
diferencia muy importante es que las variables de las funciones son locales mientras que las
de los scripts son globales. Es decir, las variables en las funciones se almacenan en la memoria
mientras se ejecuta la función; una vez terminada ésta desaparecen de la memoria del ordenador.
Para los scripts sin embargo, las variables se mantienen en la memoria con el valor que toman
en el script hasta que es sustituı́do por otro valor o se cierra MATLAB. Es decir, las variables
de los scripts actúan como si se ejecutaran en la ventana de comandos.
>> fracaurea(6)
p =
1+1/(1+1/(1+1/(1+1/(1+1/(1+1/(1))))))
p =
21/13
p =
1.61538461538462
err =
0.0026
8
La primera p es la fracción continua truncada a 6 términos. Se produce de la siguiente forma:
se le asigna a la variable p el valor ’1’. Las tildes son importantes. Es la forma de decirle a
MATLAB que se trata de una variable de tipo string, cadena de caracteres. De esta forma, al
principio p es el string ’1’. Luego entramos en un bucle for ...end que repetidamente inserta
los strings ’1+1/(’ y ’)’ por delante y por detrás, respectivamente, del string almacenado en p.
Independientemente de lo largo que este string llegue a ser, es una expresión válida en MATLAB.
Finalmente, el comando p (sin ;) muestra el valor de p al salir del bucle.
enseguida nos daremos cuenta de que empezando con los valores p = q = 1 (i.e., con la fracción
1
1 ) y reemplazando la fracción
p
q
por
p+q
p
obtenemos el valor de la fracción continua truncada al término deseado. Finalmente el comando
p = sprintf(’%d/%d’,p,q)
escribe la fracción obtenida en la forma p/q con p y q en formato de número decimal (aunque en
este caso sean enteros). Debe notarse que después de p = sprintf(’ %d/ %d’,p,q), la variable
p vuelve a ser un string.
El tercer p es el valor numérico del segundo p obtenido usando el comando eval. Esta función
devuelve el valor numérico de un string formado por una operación válida para MATLAB. Por
ejemplo, los comandos
>> A=rand(2);
>> s=’det(A)’;
>> eval(s)
producirı́an el valor del det(A) (aunque, claro, ésta es una forma muy tonta de calcularlo).
Todo lo anterior nos ha servido para aprender algunas funciones de MATLAB pero se podrı́a
haber obtenido el mismo resultado de forma más rápida. El código
p = sprintf(’%d/%d’,p,q)
format long
p = eval(p)
9
se podrı́a haber sustituı́do por
format rat
p=p/q
format long
p
De esta forma p serı́a siempre una variable numérica, primero en formato racional, y después,
en formato decimal.
3. Números de Fibonacci
La razón áurea aparece en muchos lugares de forma que podrı́a considerarse misteriosa. Un
ejemplo son los números de Fibonacci. En un libro publicado en 1202, Liber Abaci, Leonardo
Pisano Fibonacci propuso el siguiente problema:
Un hombre coloca un par de conejos en un lugar rodeado por un muro de forma que
queden completamente aislados. Este par de conejos y los sucesivos que vayan na-
ciendo engendran un nuevo par cada mes a partir del segundo mes de vida. ¿Cuántos
conejos habrá al cabo de un año?
Si no se pusiera la condición de que los conejos no son productivos hasta el segundo mes,
la respuesta serı́a sencilla y no habrı́a habido números de Fibonacci. Si cada par de conejos
engendrara otro par cada mes, el número de éstos se duplicarı́a cada mes; y al cabo de n meses
habrı́a 2n conejos. Pero la condición de que sólo se pueden producir nuevos pares de conejos a
partir del segundo mes de vida, hace que el problema sea más interesante.
Si fn representa el número de pares de conejos después de n meses, este número debe ser igual
al número de conejos en el mes anterior fn−1 más el de conejos que ha producido una nueva
pareja (que son los que habı́a un mes antes, fn−2 ). Ası́
fn = fn−1 + fn−2
Con estos datos podemos producir una función de MATLAB que nos proporcione la secuencia
de Fibonacci con tantos términos como queramos. Usa el editor para escribirla y salvarla con el
nombre de fibonacci.m
10
function f = fibonacci(n)
%FIBONACCI secuencia de Fibonacci
% f = FIBONACCI(n) genera los primeros n números de Fibonacci.
f = zeros(n,1);
f(1) = 1;
f(2) = 2;
for k = 3:n
f(k) = f(k-1) + f(k-2);
end
fibonacci es una verdadera función de MATLAB, sencilla, pero con todos los ingredientes:
empieza con la palabra function, admite datos de entrada: n, y produce una salida: f, que
es un vector. La función define primero un vector (matriz) de tamaño n × 1 con todas sus
componentes iguales a 0. A continuación cambia la primera componente a 1 y la segunda a 2
iniciando la secuencia de Fibonacci. Después entramos en un bucle para sustituir las restantes
componentes del vector f .
Entre el nombre de la función y los comandos que la componen hay dos (o más) lı́neas que
comienzan por el sı́mbolo %. Son lı́neas de comentarios que sirven para orientar a quien use la
función sobre lo que ésta realiza. Si una vez escrita la función y salvado el fichero escribimos
Esta información es muy útil para los posibles usuarios de la función. Es muy buena costumbre
colocar un par de lı́neas de comentarios para ayudarnos a nosotros mismos y a los demás.
>> g=fibonacci(12)
obtendremos
g =
11
1
2
3
5
8
13
21
34
55
89
144
233
Por lo general, no necesitaremos todos los datos del vector, quizá sólo unos pocos, o ni tan
siquiera eso: quizá sólo queramos tener el vector con los datos para usarlo posteriormente. Por
ejemplo, si hacemos
>> g=fibonacci(12);
No hay respuesta visible por parte de MATLAB, pero en g está el vector con los 12 primeros
números de la sucesión de Fibonacci. Aunque no lo parezca éstos están relacionados con φ, la
razón áurea. Veamos, escribamos
La respuesta es
ans =
21/13
Este número nos resulta familiar: es el número que producı́a fracaurea(6). ¿Es una casualidad?.
Ejercicio 11 Comprueba para varios valores de n (no mayores que 40, ¿por qué?) que la fracción
que se obtiene como resultado de fracaurea(n) coincide con el valor de f(n+1)/f(n) donde f
es el vector que devuelve fibonacci(n+1).
12
4. Cuadrados Mágicos
obtenemos
Los cuadrados mágicos eran conocidos en China 2000 años antes de nuestra era, y el cuadrado
mágico de orden 3 se conoce con el nombre de Lo Shu. Cuenta la leyenda que fué descubierto en
el caparazón de una tortuga en el rı́o Lo en el siglo 23 antes de Cristo. Hay cantidad de mitologı́a
y esoterismo asociado a los cuadrados mágicos. Una rápida consulta en Google proporciona un
sin fin de páginas relacionadas con los cuadrados mágicos. Tal y como dice la ayuda de magic este
comando proporciona un cuadrado mágico de cualquier orden, salvo de orden 2. Por ejemplo,
Lo Shu se consigue de la siguiente forma:
>>A=magic(3)
que produce
A =
8 1 6
3 5 7
4 9 2
El comando
>> sum(A)
devuelve un vector cuya i-ésima componente es la sumas de los elementos de la i-ésima columna:
ans =
15 15 15
Para obtener la suma de los elementos en cada fila podemos usar el mismo comando sobre la
transpuesta:
13
>> sum(A’)’
ans =
15
15
15
Para sumar los elementos de la diagonal principal (elementos en la posición (i, i)):
>> sum(diag(A))
ans =
15
El comando flipup pasa la primera fila a la última, la segunda a la penúltima y ası́ sucesiva-
mente. Si queremos comprobar que la contradiagonal (elementos en la posición (i, n − i + 1))
también suman lo mismo podemos utilizar el comando
>> sum(diag(flipud(A)))
ans =
15
El mismo efecto habrı́amos conseguido con el comando fliplr que hace lo mismo que flipud
pero por columnas.
Todo lo anterior certifica que A es un cuadrado mágico. Pero ¿por qué la suma es 15?. El
comando
>> sum(1:9)
ans =
45
nos permite observar que la suma de los primeros 9 números enteros positivos es 45. Como éstos
están colocados en A de tres en tres y sumando siempre lo mismo, la suma de cada fila, columna,
etc. debe ser 15.
Hay 8 formas posibles de colocar una transparencia en un retroproyector (no olvidemos que
una transparencia se puede leer por delante y por detrás). De la misma forma hay 8 maneras
posibles de escribir el mismo cuadrado mágico de orden 3 que corresponden a las posibles formas
de rotar y reflejar el cuadrado. Se pueden obtener mediante los siguientes simples comandos que
se explican por sı́ solos:
14
Ahora un poco de álgebra lineal:
>> det(A)
ans =
-360
nos da el determinante,
>> X=inv(A)
X =
0.1472 -0.1444 0.0639
-0.0611 0.0222 0.1056
-0.0194 0.1889 -0.1028
Volvemos al formato decimal para calcular la norma espectral, los valores propios y los valores
singulares de A:
La suma “mágica”, 15, aparece en los tres casos porque el vector (1, 1, 1) es vector propio y
vector singular a izquierda y derecha de A.
15
>> load durer
Ahora veamos las variables que contiene. El comando whos devuelve las variables que han sido
definidas en una sesión. Es posible que tengas otras variables, aparte de las definidas al cargar
el fichero durer.mat, de modo que lo que aparece a continuación puede ser sólo parte de lo que
se muestra en tu ventana de comandos.
>> whos
Name Size Bytes Class Attributes
Hay libros especializados en cómo MATLAB maneja los colores y las imágenes, pero no estu-
diaremos este asunto aquı́. Como curiosidad veamos cómo conseguir el grabado La Melancolı́a.
Los tres siguientes comandos lo proporcionan:
>> image(X)
>> colormap(map)
>> axis image
Hay una lupa en la barra de herramientas, utilı́zala para agrandar un cuadrado que se aprecia
debajo de la campana. Observarás una matriz 4 × 4. Quizá no la distingas muy bien. MATLAB
tiene otro fichero, detail.mat, en el que están los datos de ese detalle del grabado con mucha
mejor resolución. Los siguientes comandos te proporcionan la imagen:
Se trata de un cuadrado mágico, pero no el que produce MATLAB con el comando magic(4):
>> A=magic(4)
A =
16 2 3 13
5 11 10 8
9 7 6 12
4 14 15 1
16
A =
16 3 2 13
5 10 11 8
9 6 7 12
4 15 14 1
Al permutar dos filas o dos columnas se puede destruir la “magia” del cuadrado, pero casualmen-
te en este caso no. En efecto, las diagonales siguen sumando 34 (la sumas de filas y columnas, por
supuesto, no se modifican). Probablemente Durero escogió este cuadrado mágico porque juntado
las cifras de los dos números que están en el centro de la última fila se consigue el número 1514,
que fué el año en que Durero hizo el grabado.
Hemos visto dos cuadrados mágicos diferentes de orden 4; hay 880. Y de orden 5, 275305224.
No se sabe cuántos hay de orden 6 o más.
Curiosamente, o no, para nuestros cuadrados mágicos de orden 4 tenemos que det(A) = 0. Y si
intentamos calcular la inversa obtenemos
>> inv(A)
Warning: Matrix is close to singular or badly scaled.
Results may be inaccurate. RCOND = 9.796086e-18.
ans =
1.0e+15 *
Ya veremos el significado del mensaje obtenido. En cualquier caso, esto nos indica que hay
cuadrados mágicos que son matrices singulares (no invertibles) ¿cuáles?. El siguiente código
produce una tabla de dos columnas, en la primera se coloca el orden del cuadrado mágico
producido por MATLAB y en la segunda su rango:
17
11 11
12 3
13 13
14 9
15 15
16 3
17 17
18 11
19 19
20 3
21 21
22 13
23 23
24 3
20
15
10
0
0 5 10 15 20 25
Ejercicio 12 A=magic(4) es singular; i.e., sus columnas son linealmente dependientes. Los si-
guientes comandos te informan sobre cómo es esa dependencia: null(A), null(A,’r’), rref(A).
¿Qué información te proporcionan?
Ejercicio 13 Sea A=magic(n) para n=3,4,5. ¿qué efecto producen los comandos
>> p=randperm(n);q=randperm(n);A=A(p,q);
sobre sum(A),sum(A’)’,sum(diag(A)),sum(diag(flipud(A))),rank(A)?
18
5. Procesos Aleatorios
1.5
0.5
−0.5
−1
−1.5
−1.5 −1 −0.5 0 0.5 1 1.5
relación entre las áreas de ambas figuras geométricas. Si el cuadrado lo pensamos centrado en
el punto (0, 0) y de lado 2, la circunferencia tendrá radio 1 y tal probabilidad es
π
.
4
Con un ordenador podemos simular el lanzamiento de un dardo a la diana: cada lanzamiento
es asociado a la elección aleatoria de un par de números (x, y) comprendidos entre −1 y 1.
Este punto representarı́a el punto del cuadrado donde se ha clavado el dardo. Realizando esta
simulación un número muy alto de veces la frecuencia relativa de elección de puntos en el interior
del cı́rculo se deberá aproximar a la probabilidad buscada:
Número de lanzamientos en el interior del cı́rculo
π≈ ·4
Número total de lanzamientos
El punto clave en esta simulación es el de la elección aleatoria del par de puntos que deter-
minan las coordenadas del cuadrado. Todos los puntos deberı́an tener la misma probabilidad
de ser elegidos; y esto nos indica que los números aleatorios que los determinan deben estar
uniformemente distribuidos. MATLAB proporciona, mediante el uso repetido del comando rand
una sucesión de puntos uniformemente distribuı́dos entre 0 y 1. Cómo es generada tal sucesión
no es un problema trivial, pero se puede modificar el comienzo de la misma con el comando
rand(’seed’,n) con n un número entero positivo.
19
También se pueden obtener números aleatorios normalmente distribuı́dos. El comando que lo
hace es randn. El siguiente script puede servir para comprender la diferencia entre ambos tipos
de números aleatorios:
close all
clc
subplot(2,1,1)
x=rand(1000,1);
hist(x,30)
axis([-1 2 0 60])
title(’Distribución de los valores en rand(1000,1)’)
xlabel(sprintf(’Media= %5.3f. Mediana=%5.3f.’, mean(x),median(x)))
subplot(2,1,2)
x=randn(1000,1);
hist(x,linspace(-2.9,2.9,100))
title(’Distribución de los valores en randn(1000,1)’)
xlabel(sprintf(’Media= %5.3f. Desviacion standard=%5.3f.’, mean(x),std(x)))
Ejercicio 14 Copia este script en un fichero con el nombre randhisto.m y ejecútalo. Trata de
comprender lo que hace cada comando.
Una vez que entendemos mejor la diferencia entre los comandos rand y randn, podemos volver
a nuestra simulación para el cálculo aproximado del número π. Vamos a escribir una función
que produzca la simulación del lanzamiento de los dardos. Recordemos que la parte importante
es la selección aleatoria de un par de puntos (x, y) en el interior del cuadrado (por lo tanto, con
distribución uniforme) y la determinación de si tal punto está o no en el interior del cı́rculo. La
función admite un número entero positivo
function pi=dardos(n)
20
%DARDOS admite un número entero n que es el número de
%cientos de lanzamientos y devuelve una
%aproximación a pi y la gráfica de la convergencia a
%pi del método
if (ceil(n)-n ~= 0 || n<0)
error(’n debe ser entero’);
return
else
close all; clc
rand(’seed’,0);
ndentro=0;
piestimada=zeros(n,1);
for k=1:n
x=-1+2*rand(100,1);y=-1+2*rand(100,1);
ndentro=ndentro+sum(x.^2+y.^2<=1);
piestimada(k)=(ndentro)/(100*k)*4;
end
plot(piestimada)
pi=piestimada(n);
title(sprintf(’Valor estimado de pi= %5.6f’,pi));
xlabel(’Cientos de lanzamientos’);
end
La ejecución de esta función con n = 500 (esto es, 50000 lanzamientos) produce el valor de
π = 3,1302 y la Figura 6. Debe observarse que el valor estimado de π mejora gradualmente a
3.24
3.22
3.2
3.18
3.16
3.14
3.12
3.1
3.08
0 50 100 150 200 250 300 350 400 450 500
Cientos de lanzamientos
medida que n aumenta, pero que el “progreso” hacia 3’14159 no es ni estable ni, mucho menos,
rápido. Simulaciones de este tipo se conocen con el nombre de Montecarlo (o Monte Carlo).
21
Hay una sentencia en el programa que merece atención especial: sum(x.^2+y.^2<=1). x y y son
vectores de 100 componentes cada uno y x.^2 eleva cada componente de x al cuadrado (y lo
mismo y.^2). Ahora, x.^2+y.^2 es un vector cuyas componentes son la suma de los cuadrados de
las componentes de x y de y. Finalmente, x.^2+y.^2<=1 también es un vector: sus componentes
son 0 o 1. Es 0 si la correspondiente componente no cumple la condición y 1 si la cumple. Por
lo tanto, sum((x.^2+y.^2<=1) cuenta el número de componentes del vector x.^2+y.^2 que son
menores que 1; es decir, el número de dardos que han impactado en el interior del cı́rculo.
Otros dos comandos útiles para trabajar con vectores de ceros y unos son any y all. any(x)
devuelve un 1 (“true”) si alguna componente de x es distinta de cero; si no devuelve un 0
(“false”). Y all(x) devuelve un 1 si todas las componentes de x son distintas de cero; si no
devuelve un cero. Si x es una matriz, any y all actúa por columnas. Ası́
>> x=[ 0 1 0; 1 -1 0; -1 1 0]
x =
0 1 0
1 -1 0
-1 1 0
>> any(x)
ans =
1 1 0
>> all(x)
ans =
0 1 0
Dado que los ordenadores utilizan un número finito de bits para representar los números reales,
sólo pueden representar un número finito de ellos; es decir, un subconjunto finito de números
reales (o de números complejos). Esta limitación conlleva dos dificultades:
Los números representados no pueden ser arbitrariamente grandes (en valor absoluto).
Lo primero conduce a los fenómenos conocidos con los nombres de “overflow” y “underflow”
(rebosamiento por arriba o por abajo) y lo segundo produce el “roundoff” (redondeo). Por lo
general, es posible usar MATLAB sin preocuparse de estas cuestiones, pero de vez en cuando
22
puede que nos encontremos con problemas que un somero conocimiento del funcionamiento de
la aritmética en punto flotante puede ayudar a solucionar.
Hace 20 años la situación era mucho más complicada de lo que es ahora porque cada ordenador
tenı́a su propio sistema de números en punto flotante. Algunos eran binarios, otros decimales.
Incluso hubo algunos ordenadores rusos que usaban aritmética ternaria. Además, entre los bi-
narios los habı́a que usaban aritmética de base 2, otros octal o hexadécimal. Y cada uno tenı́a
su propia precisión. En 1985 la IEEE Standard Board y el American National Standard Insti-
tute decidieron adoptar para la aritmética binaria de punto flotante lo que se conocce como el
ANSI/IEEE Standard 754-1985. Esta decisión fue la culminación del trabajo de casi una déca-
da de trabajo de un grupo de 92 personas integrado por matemáticos, ingenieros e informáticos
procedentes de universidades y empresas dedicadas a la construcción de ordenadores y micropro-
cesadores. Todos los ordenadores diseñados a partir de 1985 usan la aritmética IEEE de punto
flotante. Esto no significa que todos ellos producen los mismos resultados porque hay una cierta
flexibilidad en la norma ANSI/IEEE, sino que el modelo de funcionamiento de la aritmética en
punto flotante es, hoy en dia, independiente del ordenador que se utilice.
MATLAB ha usado siempre el formato IEEE de doble precisión. Hay un formato de precisión
simple que salva espacio pero que no supone una mejora en la velocidad con los ordenadores
actuales. Nosotros hablaremos sólo de la precisión doble. Para entender bien este concepto
debemos recordar la forma en la que los ordenadores
√ trabajan con los números en punto flotante.
La mayorı́a están normalizados. Si calculamos 1/ 120 en una calculadora de bolsillo con notación
cientı́fica obtendremos (esto es lo que marca la mı́a)
9, 128709292e − 2 (1)
o algo similar. Es la notación cientı́fica para el número
9, 12870929 · 10−2 .
El número en punto flotante de (1) no está normalizado. Para considerarlo normalizado debemos
escribirlo de la siguiente forma:
0, 912870929 · 10−1 o 0, 912870929e − 1.
Es decir, un número en punto flotante es normalizado si la parte fraccionaria es de la forma
0.x1 x2 . . . con x1 6= 0. Para los números representados en base 10, 1 ≤ x1 ≤ 9, pero para los
números en base 2 x1 = 1 siempre, de modo que la parte fraccionaria tendrá la forma 0,1x2 x3 . . .
con xi = 0 o 1. Nótese que un número de esta forma puede escribirse como (1 + f )2−1 siendo
f = 0.x2 x3 . . .. Por lo tanto, en un ordenador que representa los números en base binaria (que es
el que consideraremos nosotros), los números en punto flotante normalizados tienen la siguiente
forma:
x = ±(1 + f ) · 2e
con
0≤f <1 y e un número entero.
Al número f se le llama fracción o mantisa y a e exponente o caracterı́stica.
23
para almacenar f , 11 bits para e y 1 bit para el signo del número, 0 para + y 1 para − (Figura
7). Puesto que la fracción debe estar entre 0 y 1 y se debe almacenar en 52 bits, debe resultar
s exponente fracción
0 1 11 63
Y como 252 ≈ 4,5 · 1015 , los números en punto flotante en doble precisión se expresan, en base
decimal, con 15 decimales. Debe notarse, finalmente que la parte fraccional completa de los
números en punto flotante no es f sino 1 + f , que necesita 53 bits. Sin embargo, como la primera
cifra decimal siempre es 1 (si el número está normalizado), no es necesario almacenarlo. De
hecho, el formato IEEE empaqueta 65 bits de información en una “palabra” de 64 bits.
Por otra parte, para el exponente se reservan 11 bits, ası́ que e es un numero entero en el intervalo
0 ≤ e ≤ 211 = 2048.
Sin embargo, debemos permitir exponentes negativos almacenándolos en los 11 bits disponibles.
Para conseguirlo lo que se hace es acomodar en los 11 bits el número e+1023. Ası́, si el número
almacenado en los 11 bits de e es 1250 entonces e = 1250 − 1023 = 227; mientras que si el
número almacenado es 1000 entonces e = 1000 − 1023 = −23. Los valores extremos posibles en
estos 11 bits: 0 y 211 − 1 se reservan para definir números especiales que veremos más adelante.
Los restantes son valores admisibles para e. Por lo tanto el exponente debe encontrarse en el
intervalo
−1022 ≤ e ≤ 1023.
Teniendo en cuenta que
éstos son el mayor y menor números representables en doble precisión. En MATLAB estos
números reciben un nombre especial
Si algún cálculo intenta producir un valor mayor que realmax se dice que produce un rebosa-
miento por arriba (“overflow”) dando como resultado un número especial llamado “infinity”,
Inf en MATLAB. Se representa tomando e = 1024 y f = 0 y cumple propiedades tales como
1/Inf=0 o Inf+Inf=Inf. Por ejemplo
24
>> realmax^2
ans =
Inf
>> Inf*Inf
ans =
Inf
Para operaciones tales como 0/0 o Inf-Inf el resultado es un valor excepcional denotado por
el sı́mbolo NaN por “not a number”.
>> 0/0
Warning: Divide by zero.
ans =
NaN
>> Inf-Inf
ans =
NaN
Si algún cálculo intenta producir un número inferior a realmin, se dice que produce un re-
bosamiento por abajo (“underflow”). En realidad, algunos sistemas como MATLAB permiten
números más pequeños llamados números en punto flotante denormales (o subnormales, aun-
que esta denominación en castellano tiene connotaciones negativas). El número más pequeño
en MATLAB es 2 ^ (-1074) ≈ 0.494e-323. Veremos más adelante de donde proviene este
número.
>> 2^(-1074)
ans =
4.9407e-324
> 2^(-1075)
ans =
0
El rebosamiento por arriba (que rara vez ocurre en la práctica) puede, a veces, evitarse escalando
adecuadamente los datos del problema para convertirlo en un rebosamiento por abajo que no
tiene consecuencias importantes. Por ejemplo, supongamos que tenemos que calcular la cantidad
p
c = a2 + b2
con a = 10200 y b = 1. Una respuesta aceptable serı́a c = 10200 debido a que b es insignificante
en comparación a a. Si hacemos este cálculo directamente en MATLAB:
25
La respuesta es debida a que se ha producido un rebosamiento por arriba. Teóricamente, el
mismo resultado se obtendrı́a si hiciéramos
s
a 2 b 2
c=s +
s s
> s=max(abs(a),abs(b));c=s*sqrt((a/s)^2+(b/s)^2)
c =
1.0000e+200
que es la respuesta que hemos dado como aceptable. Este resultado es debido al rebosamiento
por abajo ocurrido al calcular (b/s)2 :
>> (b/s)^2
ans =
0
Los fenómenos de rebosamiento tienen su origen en las cotas superior e inferior de los exponentes
admisibles. Hay otro fenómeno importante que es consecuencia de la finitud de las posibles
mantisas o fracciones: el redondeo. Comencemos con la siguiente pregunta: ¿Cuántos números
en coma flotante hay entre 1 y 2? Son los de la forma
+(1 + f ) · 20 .
Y como f está representado por 52 bits (i.e., 52 posiciones cada una de ellas conteniendo un 0
o un 1), el número posible de fracciones es 252 = 4,503599627370496e + 15 (las formas posibles
de colocar 0 y 1 en 52 posiciones distintas). Ası́ pues, los posibles valores de f son:
De la misma forma, los números en punto flotante en el intervalo [2, 4) son de la forma
+(1 + f ) · 21 ,
y son, concretamente:
En general, los números en el intervalo [2j , 2j+1 ] son los de (2) multiplicados por 2j .
26
eps = 1/8
||||||| |||||||| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
Figura 8: Floatgui.
Esta “equidistribución” se hace más evidente si utilizamos una escala logarı́tmica. La Figura 9
muestra el resultado de floatgui cuando se marca la casilla de log scale con t = 5, emı́n = −4
y emáx = 3.
eps = 1/32
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
||
Figura 9: Floatgui.
Experimenta con floatgui para comprender la distribución de los números en punto flotante y
responde a las siguientes preguntas: ¿Para un valores concretos de t, emı́n y emáx cuántos números
positivos son representables exactamente en punto flotante? ¿Cuántos números positivos contiene
el conjunto de números en punto flotante del sistema IEEE?
Cualquier número real que no coincida con uno de los números en punto flotante del sistema
IEEE debe ser aproximado por uno de ellos; concretamente por el más próximo. A este fenómeno
se le llama redondeo. Si x es un número real, se denota por fl(x), el número en punto flotante
más próximo a x. Resulta que si realmin≤ x ≤realmax entonces
| fl(x) − x|
≤ 2−53 .
|x|
En efecto, suponiendo que x ∈ [2j , 2j+1 ] y que fl(x) = (1 + a · 2−52 )2j entonces
(1 + a · 2−52 )2j ≤ x < (1 + (a + 1) · 2−52 )2j o (1 + (a − 1) · 2−52 )2j < x ≤ (1 + a · 2−52 )2j
27
Pero como fl(x) = (1 + a · 2−52 )2j se tiene
o
(1 + a · 2−52 )2j − x < x − (1 + (a − 1) · 2−52 )2j = x − (1 + a · 2−52 )2j − x + 2j−52 .
En cualquier caso
Un razonamiento similar nos permite ver que, en términos relativos, la distancia entre dos
números en punto flotante consecutivos es 2−52 . En particular, ésta es la distancia de 1 al
siguiente número en punto flotante tal y como hemos visto en (2). A este número, se le conoce
con el nombre de épsilon de la máquina y se denota en MATLAB por eps. Ası́
>> eps
ans =
2.220446049250313e-16.
Algunos autores prefieren llamar épsilon de la máquina al máximo error relativo posible al
redondear un número real por el número en punto flotante más próximo; i. e. eps/2=2−53 . En
cualquier caso, el nivel de error relativo es de aproximadamente 16 dı́gitos decimales.
Nótese que 2−52 · 2−1022 = 2−1074 . Este número ya lo hemos visto antes: era el menor valor
denormal (o subnormal) admisible en MATLAB.
En el cálculo binario del número t=0.1 se produce un redondeo que suele afectar a muchas
operaciones aritméticas. El valor almacenado en t no es exactamente 0,1 porque la fracción
decimal 1/10 expresada en base 2 requiere una serie infinita. Esto se entiende mejor si expresamos
1/10 en base 16; es decir, si usamos la representación hexadecimal :
1 −4 9 9 9
=2 1+ + + + ··· . (3)
10 16 162 163
En efecto
∞
X 1 1/6 1
j
= = ,
6 1 − 1/6 15
j=1
y
−4 9 24 1
2 1+ = = .
15 16 · 15 10
28
Para pasar (3) a formato binario observamos que
9 23 + 1 1 1
2−4 = 8
= 5 + 8,
16 2 2 2
9 23 + 1 1 1 (4)
2−4 = = 9+ 1 ,
162 212 2 2 2
etc.
Por lo tanto
1 1 1 0 0 1 1 0 0 1
= 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + · · · .
10 2 2 2 2 2 2 2 2 2
La representación en número de punto flotante de 1/10 se obtiene tomando 52 términos de esta
serie (en formato binario), o 13 términos de la serie en formato hexadecimal, y redondeando el
último término al entero más próximo. En formato hexadecimal tendrı́amos que si
−4 9 9 9 9
t1 = 2 1+ + + + · · · + 13
16 162 163 16
9 9 9 10
t2 = 2−4 1+ + + + · · · + 13
16 162 163 16
entonces
t1 < 1/10 < t2 .
Pero resulta que 1/10 está más próximo a t2 que a t1 . Es decir,
1/10 = (1 + f ) · 2e
donde
9 9 9 10
f= + 2 + 3 + · · · + 13
16 16 16 16 (5)
e = −4
Hemos escrito f en formato hexadecimal. Para pasarlo a binario y conseguir los 52 bits que lo
representan se procederı́a como en (4). En realidad, la conversión de números entre las bases 2 y
16 es muy sencilla. Por ejemplo, en consonancia con (5), el comando de MATLAB format hex
aplicado a t=0.1 produce:
>> t=0.1
t =
0.1000
>> format hex
>> t
t =
3fb999999999999a
29
Las letras a a f representan los números 10 a 15 en base hexadecimal. Para pasar t a binario
basta observar que cada cifra es una “palabra” de cuatro bits. Ası́ 3fb en binario serı́a
que son los 12 primeros bits de t. El primer bit, 0, es el signo; por lo tanto t es positivo. Los
primeros 12 bits para −0,1 serı́a
1011 1111 1011,
que en hexadecimal es bfb. Los restantes 11 bits representan el exponente (en realidad, recor-
demos, 1023+e). Como 3fb en base diez es 3 · 162 + 15 · 16 + 11 = 1019, resulta que e = −4. Las
restantes cifras 999999999999a representan la fracción que en binario serı́a
Una vez más, 3 es 0011 en binario, de modo que φ es positivo. Además 3ff en base 10 es 1023,
por lo que e = 0. Las restantes 13 cifras hexadecimales contienen la fracción f :
9 14 10 8
f= + 2 + · · · + 12 + 13 .
16 16 16 16
Con estos valores de e y f
(1 + f ) · 2e ≈ φ.
t = 0.1
n = 1:10
e = n/10 - n*t
30
Dos últimos ejemplos en los que los efectos del redondeo se ponen de manifiesto. El primero
consiste en la resolución del siguiente sencillo sistema
17x1 + 5x2 = 22
(6)
1,7x1 + 0,5x2 = 2,2
Dado que la primera ecuación es 10 veces la segunda, este sistema tiene infinitas soluciones y la
más simple es x1 = x2 = 1.
Ejercicio 19 1. Resuelve el sistema (6) con MATLAB y comprueba que la solución obtenida
no es x1 = x2 = 1.. (Indicación: MATLAB utiliza el comando A\b para resolver el sistema
Ax = b mediante eliminación gaussiana.)
2. Utiliza MATLAB para hacer la eliminación gaussiana en etapas con formato cientı́fico; i.e.
format short e:
>> A(2,:)=A(2,:)-1.7/17*A(1,:)
>> b(2)=b(2)-1.7/17*b(1)
Considera el siguiente polinomio p(x) = (x − 2)9 y utiliza el comando conv para calcular los
coeficientes de este polinomio, Llámalo q.
Referencias
[1] C. B. Moler: Numerical computing with MATLAB. SIAM, 2004.
[2] Ch. F. van Loan: Introduction to scientific computing. Prentice Hall.
31