Sei sulla pagina 1di 41

Taller de Octave

Rubén Agapito

Verano 2018
Contenidos

Listado de Programas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . iii

Prefacio v

1 Introducción a Octave 1
1.1 Algunas Definiciones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
1.2 Fundamentos de Programación . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
1.2.1 Problemas Propuestos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
1.3 Bucles For y While . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
1.3.1 Problemas Propuestos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
1.4 Ploteo en Dos Dimensiones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
1.4.1 Problemas Propuestos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
1.5 Simulación Monte Carlo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
ii CONTENIDOS
Programas

1.1 Función biseccion.m . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2


1.2 Script AreaSup.m . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
1.3 Script IncrementoAreaSup.m . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
1.4 Script ValorMinimo.m . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
1.5 Script AproximaPi.m . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
1.6 Script AproximaPiConBucleWhile.m . . . . . . . . . . . . . . . . . . . . . . . . . . 22
1.7 Script UsoDeBreakConFor.m . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
1.8 Script UsoDeContinueConFor.m . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
1.9 Script miploteo2d.m . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
1.10 Script mcprog01.m . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
1.11 Script mcprog02.m . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
1.12 Script mcprog03.m . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
1.13 Script mcprog04.m . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
1.14 Script mcprog05.m . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
1.15 Script mcprog06.m . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
1.16 Script mcprog07.m . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
iv PROGRAMAS
Prefacio

Los contenidos de estas notas están bajo constante supervisión. Si existe alguna sugerencia o
error, por favor mandar un correo electrónico al autor: ruben.agapito@pucp.pe

Rubén Agapito
San Miguel, enero de 2018
Lima, Perú.
vi Prefacio
Capítulo 1

Introducción a Octave

1.1 Algunas Definiciones


Un algoritmo1 es un conjunto de reglas que deben seguirse ordenadamente para resolver un
problema dado. Cuando escribimos un algoritmo en papel, comúnmente usamos palabras del
habla común mezcladas con lenguaje técnico. El resultado de este proceso es llamado seu-
docódigo,2 y por la estrecha relación entre ambos, usaremos algoritmo y seudocódigo como
sinónimos.
Un lenguaje de programación (como C, C++, Java, Python, etc.) es un lenguaje formal
que nos permite controlar el comportamiento de una máquina, en especial, una computadora.
Debemos tener en cuenta que un seudocódigo es escrito independientemente del lenguaje de
programación que uno escoja. Cuando implementamos un seudocódigo en la computadora, vía
algún lenguaje de programación, obtenemos un programa. Un programa es así un conjunto de
instrucciones que una computadora puede interpretar y ejecutar. A diferencia del seudocódigo,
un programa debe elaborarse cumpliendo ciertas reglas de sintaxis y de formato (determina-
das por el lenguaje de programación que se use), caso contrario, el programa no funcionará (o
compilará) correctamente.
Ilustramos los conceptos mencionados en el siguiente ejemplo.
Deseamos encontrar una solución de la ecuación f ( x) = 0, donde se sabe que f es continua
en el intervalo [a, b] y f (a) · f ( b) < 0.3 De los varios algoritmos que existen presentamos el
siguiente:

Algoritmo de Bisección
INPUT extremos a, b; tolerancia TOL; maximo numero de iteraciones N0 .
OUTPUT solucion aproximada r o mensaje de no exito.

Paso 1: Inicializar i = 1;
Poner F A = f (a).
Paso 2: Mientras que i ≤ N0 hacer Pasos 3-6.
Paso 3: Poner r = a + (b − a)/2; (Calcula los p i )
FR = f (r).
Paso 4: Si FR = 0 o (b − a)/2 < TOL entonces
1
Léase http://es.wikipedia.org/wiki/Algoritmo para más información.
2
Léase http://es.wikipedia.org/wiki/Algoritmo#Pseudoc.C3.B3digo.
3
El requerimiento f (a) · f ( b) < 0 implica que f evaluada en los extremos del intervalo [a, b] toma valores con
signos opuestos y como f es continua la gráfica de la función debe pasar necesariamente por el eje X .
2 Capítulo 1. Introducción a Octave

OUTPUT (r); (Procedimiento completado exitosamente)


PARAR.
Paso 5: Poner i = i + 1
Paso 6: Si F A · FR > 0 entonces (calculo de nuevo intervalo [a i , b i ])
poner a = r ;
F A = FR ;
sino
poner b = r . (F A conserva su valor)
Paso 7: OUTPUT('Metodo no converge despues de N0 iteraciones');
(El procedimiento no tuvo exito).
PARAR.

Este algoritmo es implementado en el siguiente programa implementado en Octave.4

Programa 1.1: Función biseccion.m


1 function r = biseccion (f ,a ,b , tol , nmax )
2 % Esta funci ó n calcula el valor aproximado de la
3 % ra íz de la ecuaci ó n f ( x ) =0 , localizada en [a , b ]
4 % Input :
5 % f : funci ón , lado izquierdo de la ecuaci ó n
6 % a ,b : extremos del intervalo [a , b ]
7 % tol : tolerancia
8 % nmax : n ú mero m á ximo de iteraciones
9 % Output :
10 % r : soluci ó n ( ra í z ) aproximada de f ( x ) =0
11 i =1;
12 FA = f(a);
13 while i <= nmax
14 r = a + (b - a ) /2;
15 FR = f( r ) ;
16 if FR ==0 || (b - a ) /2 < tol
17 fprintf ( 'El valor aprox . de la ra í z es %6.3 f ' ,r ) ;
18 return ;
19 end
20 i = i +1;
21 if FA *FR >0
22 a = r;
23 FA = FR ;
24 else
25 b = r;
26 end
27 end
28 disp ( 'El m é todo no converge , n ú mero m á ximo de \ n ') ;
29 disp ( ' iteraciones alcanzado .\ n ') ;

En estas notas usaremos el lenguaje de programación desarrollado en el software Octave (la


versión gratuita del software Matlab). Este lenguaje es un híbrido de los lenguajes conocidos
como C, C++ y Fortran. La conveniencia de usar Octave es que tiene “casi todo en un solo
4
Cuando profundicemos más en el curso nos daremos cuenta que este programa puede ser mejorado u optimi-
zado, en un sentido que estableceremos más adelante.
1.2. Fundamentos de Programación 3

lugar”, esto es, librerías gráficas, de funciones, de manejo de data, etc. La documentación de
Octave puede ser leída al abrir el GUI (la interface gráfica del software), pero se recomienda,
al estar mejor estructurada y con ejemplos, el manual online del software Matlab:

http://la.mathworks.com/help/matlab/index.html?s_tid=gn_loc_drop

pero en estas notas introduciremos el manejo de este software poco a poco resolviendo proble-
mas.

1.2 Fundamentos de Programación


Problema 1 (Incremento del Area de una Esfera): El área de la superficie de una es-
fera con radio r está dada por la fórmula

A ( r ) = 4π r 2 .

Deseamos averiguar cómo se incrementa el área de la superficie cuando el radio se incre-


menta por una pequeña cantidad δ r :

∆ A = 4π( r + δ r )2 − 4π r 2 (1.1a)
∆ A = 4π(2 r + δ r ) · δ r (1.1b)
∆ A ≈ 8π r · δ r (1.1c)

Las dos primeras fórmulas son exactas, mientras que la tercera es una aproximación que
ignora el término (δ r )2 .
Escribir un programa en que solicite (input) el radio de la esfera r (en kilómetros), el
incremento δ r (en milímetros), y exhiba (output) en pantalla el incremento en el área de la
superficie (en metros cuadrados). ¿Cuál es el incremento (∆ A ) cuando el radio de un planeta
esférico ( r = 6367 km) se incrementa por unos pocos milímetros (δ r )? Explore la respuesta
a esta pregunta usando cada una de las tres fórmulas dadas arriba.

Solución del Problema


Un número irracional como π no puede ser almacenado en la computadora, así que convenga-
mos en aproximarlo a cinco cifras: 3.1416. En el command prompt de Octave, >>, asignamos el
número 6367 a la variable r:

>> r = 6367;

Ponemos el punto y coma al final de la sentencia y luego presionamos Enter para llevar a cabo
esta asignación en la memoria del computador (¿qué sucede si no hubiésemos puesto el punto
y coma? 5 ). Podemos ahora hallar el área de la esfera usando la variable r :

>> 4 * 3.1416 * r ^2

5
Rpta: Después de presionar Enter, aparte de almacenar la asignación en memoria también se mostrará nue-
vamente esta línea en el prompt de Octave. Además, obsérvese que no hemos tipeado una ecuación, sino una
asignación, el signo de igualdad en Octave está dado por ==, y veremos más adelante cómo utilizarlo.
4 Capítulo 1. Introducción a Octave

lo cual nos da en pantalla (ventana de comandos o “Command Window”)

ans =
5.0943 e +08

Si deseamos mostrar más dígitos podemos usar el comando format con el estilo long:6

>> format long


>> 4 * 3.1416 * r ^2
ans =
5.094253814496000 e +08

Observemos que Octave utiliza internamente 16 dígitos para sus cálculos (en la mantisa de la
representación punto flotante de un número7 ), pero como en la respuesta final es común usar
de 3 a 5 dígitos, volvemos al formato original usando format short.
Si deseamos usar el área calculada en operaciones posteriores, es preferible almacenar la
respuesta en una variable8 , por ejemplo:

>> A = 4 * 3.1416 * r ^2;

Es importante aprender de memoria algunas palabras reservadas (keywords, en inglés) de Oc-


tave, ya que usarlas como posibles nombres de variables (definidas por el usuario), nos traería
problemas. Tenemos constantes con valores predefinidos.

Tabla 1.1: Constantes predefinidas más usuales en Octave

ans Nombre por defecto para los resultados


inf Infinito
eps Número más pequeño para el cual 1+eps>1
NaN No es un número (Not a number)
p
iój Unidad imaginaria −1
pi Número irracional π aproximado a 16 cifras significativas
realmin Número positivo más pequeño que puede usarse
realmax Número positivo más grande que puede usarse

y tenemos algunas palabras reservadas usuales muy útiles en programación:

for end while if else elseif fprintf case disp


save load max min sum print doc help format
mod sin cos tan exp log abs sqrt plot
grid doc help input size title ones zeros length
Ahora consideremos el siguiente programa, el cual resuelve parcialmente nuestro problema.
En Octave existen dos clases de programa: scripts (llamados script M-files en inglés) y funciones
6
para conocer más variaciones de estilo, digitar doc format.
7
más sobre esto en la sección de Aritmética Punto Flotante.
8
En Octave una variable siempre empieza con una letra y luego pueden usarse sólo letras, números y el símbolo
de subrayado, con un máximo de 64 caracteres. Octave también es sensible a las letras mayúsculas, así que las
variables Area, area, arEa, son todas diferentes.
1.2. Fundamentos de Programación 5

(o function M-files). La diferencia entre ellos es que un programa del tipo función necesita al
ser invocado de uno o más inputs y da como resultado uno o más outputs9 . Un script no necesita
de input al ser invocado. En nuestro caso utilizaremos un script y lo llamaremos AreaSup.m (la
terminación .m es añadida por defecto por el software). Comenzamos invocando el editor de
Octave para tipear el programa:

>> edit AreaSup

Se abre una nueva ventana10 y tipeamos el siguiente código:

Programa 1.2: Script AreaSup.m


1 % Programa que calcula el á rea superficial de una esfera
2 % dado el radio provisto por el usuario
3 clc ;
4 r = input ( ' Ingrese radio r : ') ;
5 A = 4* pi *r ^2; % f ó rmula del á rea de una esfera
6 fprintf ( ' Para un radio r = %10.3 f el á rea es A = %10.3 e \ n ' ,r , A ) ;

Para usar este programa hacemos clic izquierdo en el triángulo verde de la parte superior,
etiquetado con Run, o simplemente tipeamos el nombre del script en el Command Window

>> AreaSup

e inmediatamente la pantalla es limpiada y aparece

Ingrese radio r :

digitamos el valor 5940.32, presionamos Enter y obtenemos la siguiente línea:

Para un radio r = 5940.320 el á rea es A = 4.434 e +08

En caso quiera usarse otro valor para r, simplemente hay que invocar el programa de nuevo.
Pasamos a describir lo que hace cada línea.

Líneas 1-2: Cualquier código escrito a la izquierda del símbolo % es un comentario, y no son
vistos por el compilador a la hora de correr el programa. Los comentarios son útiles para
hacer el código más entendible.

Línea 3: El comando clc borra los contenidos del Command Window, es un acrónimo para
clear command window.

Línea 4: El comando input pide entrada de data al usuario. La sentencia entre signos de após-
trofe es una data del tipo string,11 la cual aparecerá en pantalla al correr el programa.
El radio ingresado se almacenerá en la variable r.
9
Brindaremos varios ejemplos más adelante para que la diferencia entre scripts y funciones quede más claro.
Es posible construir una función que no necesite input y no dé outputs, este tipo de función tiene sus fines, pero
no la usaremos aquí.
10
Dependiendo de la configuración de Octave que uno tenga, es posible que la ventana del Editor aparezca
incrustada en la ventana principal.
11
En caso necesitemos saber más sobre un comando determinado, por ejemplo input, podemos usar los coman-
dos help o doc. Por ejemplo, úsese help input.
6 Capítulo 1. Introducción a Octave

Línea 5: Se calcula el área de la esfera y el resultado se almacena en la variable A. Obsérvese


que debido al punto y coma al final de la línea, no se exhibe el valor de A en pantalla.

Línea 6: Se exhibe en pantalla la sentencia indicada dentro de los apóstrofes, con los reem-
plazos de %10.3f por el valor almacenado en r y %10.3e por el valor almacenado en A. El
símbolo \n significa Enter o cambio de línea.

Expliquemos ahora el formato %10.3f. Primero recordemos que esta expresión será reempla-
zada por el valor que tenga la variable r, el cual está representando un número real. El número
10 significa que se reservarán 10 espacios en pantalla para el valor de r, incluyendo el punto
decimal. El número 3 significa que se reservarán 3 espacios comenzando desde la derecha para
la parte decimal del valor de r. En caso el valor de r contenga más de 3 cifras decimales, Octave
utilizará redondeo para forzar la exhibición a sólo tres cifras. Quedan entonces 6 espacios libres
para exhibir la parte entera de r. En caso la parte entera contenga más de 6 cifras, entonces
se exhibirá TODA la parte entera de r. Si la parte entera tiene menos de 6 cifras, entonces se
usarán espacios en blanco (a la izquierda del número) para completar los espacios que faltan.
Por último, la letra f indica que se usará notación decimal estándar.12 Otras opciones son %d
(para valores enteros) y %e (para exhibir valores en formato exponencial).
Se recomienda correr el programa para diversos valores de r para entender cómo funciona
este formato.
Ahora nos concentramos en cómo implementar en Octave el incremento del área usando
las tres fórmulas dadas en (1.1a)–(1.1c).

delta_A1 = 4* pi *( r + delta_r ) ^2 - 4* pi * r ^2
delta_A2 = 4* pi *(2* r + delta_r ) * delta_r
delta_A3 = 8* pi * r * delta_r

Las operaciones usadas arriba son parte de las operaciones aritméticas usuales predefinidas
en Octave (Ver Tabla 1.2). ¿Cuál es el orden de operaciones que efectúa la computadora en la
siguiente expresión?

4*pi*(r + delta_r)^2 - 4*pi*r^2

Tabla 1.2: Operaciones Aritméticas más usuales en Octave

Símbolo Significado
+ Adición
- Sustracción
* Multiplicación
/ División
^ Exponenciación

Para responder esto es importante recordar la jerarquía en el orden de operaciones aritméticas


(ver Tabla 1.3) que está implícito en las computadoras. El nivel 1 es el que se ejecuta primero,
y así sucesivamente subiendo de nivel.
12
Es útil observar que se pudo usar simplemente %f. El número 10.3, o el que elija el usuario, simplemente nos
brinda mayor flexibilidad.
1.2. Fundamentos de Programación 7

Tabla 1.3: Jerarquía en el Orden de Operaciones Aritméticas

Nivel Operaciones
1 Las expresiones dentro de todos los paréntesis son evaluadas, comenzando del
más interno hacia afuera.
2 Todas las expresiones exponenciales son evaluadas, comenzando de izquierda
a derecha.
3 Todas las multiplicaciones y divisiones son evaluadas, de izquierda a derecha.
4 Todas las adiciones y sustracciones son evaluadas, de izquierda a derecha.

En adición a las operaciones aritméticas básicas existen varias funciones predefinidas en


Octave. La lista de las funciones más usuales puede ser invocada así

>> help elfun

El siguiente programa resuelve el problema propuesto.

Programa 1.3: Script IncrementoAreaSup.m


1 % Este programa calcula el incremento del á rea
2 % superficial de una esfera
3
4 % Adquirir y exhibir la data de entrada ...
5 r = input ( ' Ingrese radio ( en kil ó metros ) : ') ;
6 delta_r = input ( ' Ingrese incremento ( en mil í metros ) : ') ;
7 clc
8 fprintf ( ' Radio de la esfera = %12.6 f kil ó metros \ n ',r )
9 fprintf ( ' Incremento radial = %12.6 f mil í metros \ n \ n ', delta_r )
10 disp ( ' Incremento del Area superficial : ')
11
12 % Convertir de mil í metros a metros ...
13 dr = delta_r /10^3;
14 r = r *10^3
15
16 % Mé todo 1
17 delta_A1 = 4* pi *( r + dr ) ^2 - 4* pi * r ^2;
18 fprintf ( '\n M é todo 1: %15.6 f metros cuadrados \ n ' , delta_A1 )
19
20 % Mé todo 2
21 delta_A2 = 4* pi *(2* r + dr ) * dr ;
22 fprintf ( ' M é todo 2: %15.6 f metros cuadrados \ n ' , delta_A2 )
23
24 % Mé todo 3
25 delta_A3 = 8* pi * r * dr ;
26 fprintf ( ' M é todo 3: %15.6 f metros cuadrados \ n ' , delta_A3 )

Para los valores de r = 6367 y δ r = 1.234 obtenemos el siguiente output:

Radio de la esfera = 6367.000000 kil ó metros


8 Capítulo 1. Introducción a Octave

Incremento radial = 1.234000 mil í metros

Incremento del Area superficial :

Mé todo 1: 197464.812500 metros cuadrados


Mé todo 2: 197464.881659 metros cuadrados
Mé todo 3: 197464.881640 metros cuadrados

¿Por qué la diferencia en los tres métodos? Es más, los métodos 1 y 2 deberían darnos la misma
respuesta, ya que representan el mismo valor en aritmética exacta. Resulta que la computadora
realiza otro tipo de aritmética, llamada aritmética punto flotante o aritmética computacional,
la cual conlleva a errores, dado que no todo número real puede representarse exactamente en
la computadora.

Tipos de Errores

Cuando usamos la computadora hay que tener en cuenta los tipos de errores que debemos
minimizar, con la finalidad de poder confiar en los resultados que nos dé la computadora. Son
dos los tipos de errores:

Error de redondeo: Ocurren debido a que las computadoras tienen una capacidad limitada
para representar exactamente un número. Por ejemplo, el número irracional π.

Error de truncación: Ocurren cuando formulaciones matemáticas exactas son sustituidas


por aproximaciones. Por ejemplo, en el script que calcula el incremento en el área de la
superficie de una esfera, observamos que si bien el método 3 no es la fórmula exacta, nos
brinda una buena aproximación del incremento de área.

Aprenderemos más adelante a cómo evitar la magnificación del error de redondeo en un


programa.

Problema 2 (Uso de Condicionales: if-elseif): Una función cuadrática de la forma f ( x) =


x2 + bx + c alcanza su mínimo valor en el punto crítico x c = − b/2. Calcule el valor mínimo de
f en un intervalo [L, R ] para el cual se requiere cierta verificación: si x c está en el intervalo,
entonces f ( x c ) es la respuesta; caso contrario, f es minimizado en x = L o bien en x = R .
Escriba un script que solicite los números reales L, R, b y c, e imprima en pantalla el
valor mínimo de la función cuadrática en el intervalo [L, R ]. El script debe también exhibir
el valor de x donde el mínimo ocurre.
1.2. Fundamentos de Programación 9

Solución del Problema


Para adquirir un sentido geométrico del problema, describimos las tres alternativas posibles:

R ≤ xc
Mínimo valor = f (R )

L ≤ xc ≤ R
Mínimo valor = f ( x c )

xc ≤ L
Mínimo valor = f (L)

Dadas estas tres posibilidades, el siguiente seudocódigo identifica y procesa la alternativa


correcta
10 Capítulo 1. Introducción a Octave

Si R < x c
Imprimir f (R) y R
sino si L ≤ x c ≤ R
Imprimir f (x c ) y x c
sino
Imprimir f (L) y L
fin

Para implementar este seudocódigo en Octave usaremos la estructura condicional if-elseif


y expresiones lógicas o booleanas, esto es, expresiones a las que puede asignarse un valor de
verdad (verdadero o falso, true o false, en inglés). Comenzamos listando los operadores de
relación definidos en Octave:
Símbolo Significado
< menor que
<= menor o igual que
== igual
> mayor que
>= mayor o igual que
~= no igual
En Octave una proposición verdadera toma el valor 1, y una falsa el valor cero. Por ejemplo,
sabemos que 5<8 es verdadero, si almacenamos esto en una variable y luego invocamos su valor,
veremos que obtenemos 1:

>> a = 5 < 8;
>> a
a =
1

Cuando los operadores de relación son usados entre dos operandos numéricos siempre nos dan
como resultado un valor lógico, verdadero (1) o bien falso (0). Es importante mencionar ya desde
ahora que debemos tener cierto cuidado al usar los operadores == y ~= al comparar dos valores
numéricos. Esto se debe a los errores de redondeo al aproximar números reales. Estudiemos
el siguiente ejemplo

>> x = 0;
>> y = sin ( pi ) ;
>> x == y
ans =
0

Esto nos dice que sen(π) 6= 0 según la computadora. ¿A qué se debe esto? Si mostramos en
pantalla el valor de sen(π) según Octave obtendremos 1.2246 × 10−16 , lo cual es muy pequeño
y cercano a cero, pero no es exactamente cero. Esto se debe a que la función seno no es evaluada
en el valor exacto de π sino en una aproximación decimal de este número en la computadora,
con un número máximo de cifras significativas. Recordar que al ser π un número irracional,
no puede representarse con un número finito de cifras decimales, ni como el cociente de dos
enteros.
Ahora bien, dado que pedir igualdad exacta entre dos valores reales no es recomendable
¿cómo verificar igualdad entonces? Se sugiere mejor verificar una proximidad cercana. Por
1.2. Fundamentos de Programación 11

ejemplo, podríamos asumir que x y y son iguales en la computadora si la distancia entre ellos
es menor que 10−14 . Esto lo digitamos así

>> abs (x -y ) < 1e -14


ans =
1

A continuación presentamos los operadores booleanos o lógicos. Estos operan sobre uno o
dos operandos lógicos (proposiciones) y conducen a un resultado lógico. Existen cinco operado-
res binarios lógicos: Y (& y &&), O inclusiva (| y ||), y O exclusiva (xor); y un operador lógico
unitario: NO (~), véase la Tabla 1.4. Observemos que existen dos versiones para los operadores
Y y O inclusivo. ¿Cuándo es usada la versión con atajo en evaluación? Para responder esto de-

Tabla 1.4: Operadores Lógicos definidos en Octave


Símbolo Operación
& Y lógico
&& Y lógico con atajo en evaluación
| O lógico inclusivo
|| O lógico inclusivo con atajo en evaluación
xor O lógico exclusivo
∼ NO lógico

bemos recordar la tabla de verdad de estos operadores y tener en cuenta que este tipo de atajo
solo se usa entre expresiones lógicas 1 × 1 ó escalares13 (véase la Tabla 1.5). Es claro que las

Tabla 1.5: Tabla de Verdad de los Operadores Lógicos


Inputs Y O XOR NO
x y x&y x && y x|y x || y xor(x,y) ∼x
0 0 0 0 0 0 0 1
0 1 0 0 1 1 1 1
1 0 0 0 1 1 1 0
1 1 1 1 1 1 0 0

versiones con atajo tienen la misma tabla de verdad, pero la conveniencia radica en que a veces
no necesitamos verificar el valor de verdad de una expresión para obtener el resultado lógico de
verdadero o falso.14 En la siguiente tabla se ha puesto un signo de interrogación en los lugares
donde la computadora no necesita averiguar el valor de verdad de la segunda proposición:
x y x && y x y x||y
0 ? 0 0 0 0
0 ? 0 0 1 1
1 0 0 1 ? 1
1 1 1 1 ? 1

13
Cuando expresiones lógicas están dentro de un arreglo (array, en inglés) no escalares, los operadores lógicos
solo podrán usarse componente a componente. Comprenderemos mejor esta aseveración más adelante.
14
Si analizamos la Tabla 1.5 observamos que para el conectivo lógico Y, el resultado lógico sólo es verdadero (1)
si ambas proposiciones x y y son verdaderas, en los demás casos es falso (0), mientras que para el conectivo O
inclusivo el resultado sólo es falso si ambas proposiciones son falsas.
12 Capítulo 1. Introducción a Octave

¿Qué se gana con esto? TIEMPO, y el tiempo de ejecución de un programa es primordial


cuando resolvemos problemas muy elaborados, sobre todo si nuestro programa tiene que rea-
lizar muchos cálculos intermedios antes de obtener la respuesta final.
En la jerarquía de operaciones, los operadores lógicos son evaluados después de que to-
das las operaciones aritméticas y todos los operadores relacionales han sido evaluados. Ver
Tabla 1.6. Como ocurre con las operaciones aritméticas, paréntesis pueden ser usados para
cambiar el orden por defecto en la evaluación.

Tabla 1.6: Jerarquía en el Orden de Operadores Aritméticos, Relacionales y Lógicos


Nivel Operaciones
1 Todos los operadores aritméticos son evaluados en el orden previamente descrito.
2 Todos los operadores relacionales (==, ∼=, >, >=, <, <=) son evaluados, de
izquierda a derecha.
3 Todas los operadores de negación (∼) son evaluados.
4 Los operadores & y && son evaluados, de izquierda a derecha.
5 Los operadores |, || y xor son evaluados, de izquierda a derecha.

Ahora mostramos cómo implementar en Octave el algoritmo mencionado al principio de la


solución de este problema. Primero pedimos al usuario los extremos del intervalo [L, R ], los
coeficientes b y c de la función cuadrática, y calculamos el punto crítico x c = − b/2:

b = input ( ' Ingrese b : ') ;


c = input ( ' Ingrese c : ') ;
L = input ( ' Ingrese L : ') ;
R = input ( ' Ingrese R ( L < R ) : ') ;
xc = -b /2;

Ahora calculamos f (L), f (R ) y f ( x c ):

fL = L ^2 + b * L + c ;
fR = R ^2 + b * R + c ;
fxc = xc ^2 + b * xc + c ;

y a continuación traducimos en el lenguaje de Octave el algoritmo mencionado arriba:

if R < xc
fprintf ( ' Valor m í nimo f ( R ) = %5.2 f \ n ', fR ) ;
fprintf ( ' alcanzado en R = %5.2 f \ n ' ,R ) ;
elseif L <= xc && xc <= R
fprintf ( ' Valor m í nimo f ( xc ) = %5.2 f \ n ' , fxc ) ;
fprintf ( ' alcanzado en xc = %5.2 f \ n ', xc ) ;
else
fprintf ( ' Valor m í nimo f ( L ) = %5.2 f \ n ', fL ) ;
fprintf ( ' alcanzado en L = %5.2 f \ n ' ,L ) ;
end

En este último bloque de código hemos visto cómo se utiliza la construcción if-elseif. En
general toma la siguiente forma:
1.2. Fundamentos de Programación 13

if " expresi ó n l ó gica 1"


bloque 1 ( a ejecutar si expresi ó n l ó gica 1 es verdadera )
elseif " expresi ó n l ó gica 2"
bloque 2 ( a ejecutar si expresi ó n l ó gica 2 es verdadera )
else
bloque 3 ( a ejecutar si ninguna de las expresiones ...
l ó gicas anteriores son verdaderas )
end

Existen otras variantes de la construcción if-elseif, como if-else o simplemente if.


Antes de presentar en un solo sitio el script que soluciona el problema, sería bueno hacer
una pausa aquí e intentar elaborar por si mismo un script. Luego compare con la solución que
presentamos a continuación.

Programa 1.4: Script ValorMinimo.m


1 % Script ValorMinimo
2 % Calcula el m í nimo de una funci ó n cuadr á tica de la forma
3 % x ^2 + bx + c en el intervalo [L , R ].
4
5 % Adquisici ó n y exhibici ó n de la data de entrada ( input )
6 b = input ( ' Ingrese b : ') ;
7 c = input ( ' Ingrese c : ') ;
8 L = input ( ' Ingrese L : ') ;
9 R = input ( ' Ingrese R (L < R ) : ') ;
10 clc
11 fprintf ( ' Cuadr á tica : x ^2 + bx + c , b = %5.2 f , c = %5.2 f \ n ',b , c ) ;
12 fprintf ( ' Intervalo : [L , R ] , L = %5.2 f , R = %5.2 f \ n \ n ',L , R ) ;
13 % Cá lculo del punto cr í tico
14 xc = -b /2;
15 if xc < L
16 % Mí nimo se encuentra en el extremo izquierdo de [L , R ]
17 fL = L ^2 + b * L + c ;
18 fprintf ( 'M í nimo en x = %5.2 f \ n ',L )
19 fprintf ( ' Valor m í nimo f ( x ) = %5.2 f \ n ', fL )
20 elseif L <= xc && xc <= R
21 % Mí nimo se encuentra en el punto cr í tico
22 fxc = c - ( b /2) ^2;
23 fprintf ( 'M í nimo en x = %5.2 f \ n ', xc )
24 fprintf ( ' Valor m í nimo f ( x ) = %5.2 f \ n ', fxc )
25 else
26 % Minimo se encuentra en el extremo derecho de [L , R ]
27 fR = R ^2 + b * R + c ;
28 fprintf ( 'M í nimo en x = %5.2 f \ n ',R )
29 fprintf ( ' Valor m í nimo f ( x ) = %5.2 f \ n ', fR )
30 end

Funciones adicionales de Octave


Se recomienda usar la palabra help o doc para profundizar en el uso de las siguientes funcio-
nes:
14 Capítulo 1. Introducción a Octave

max y min: El valor de

max ( expresion1 , expresion2 )

es el más grande de los dos valores, obtenidos al evaluar las expresiones. La función min
trabaja de manera similar. Ambas funciones se pueden aplicar a una lista de dos o más
expresiones.

floor, ceil, round: Estas son funciones que son aplicadas a números reales para obtener
valores enteros cercanos. Así, para un número decimal x, tenemos que floor(x) nos da
el mayor número entero menor o igual que x, ceil(x) nos da el menor número entero
mayor o igual que x, y round(x) nos da el número entero más cercano a x. En caso x esté
localizado exactamente entre dos enteros, round(x) nos dará el mayor de los enteros. Por
ejemplo, round(4.5) nos da 5.

rem: Si x y y son enteros positivos, entonces rem(x,y) es el resto de dividir x por y. Por ejem-
plo, rem(23,3) nos da 2. La función rem también puede aplicarse a números reales de
cualquier signo.

1.2.1 Problemas Propuestos


1) Una temperatura puede convertirse de la escala Farenheit a la Celsius usando la fórmula

5
c = ( f − 32),
9
donde f es una temperatura dada en ◦ F y c es la temperatura convertida a ◦ C. Escriba un
script que pida una temperatura en ◦ F, haga la conversión a grados Celsius y exhiba en
pantalla esta temperatura.

2) Un elipsoide, tal como nuestro planeta Tierra, se obtiene al rotar una elipse alrededor de
su eje menor. Se sabe que el radio ecuatorial de la Tierra es aproximadamente 21 km más
largo que su radio polar. El área superficial de un elipsoide está dado por15
2
à ¡ ¢ ¶!
r cos γ
µ
2
A ( r 1 , r 2 ) = 2π r 21 + ln
sen(γ) 1 − sen(γ)

donde r 1 es el radio ecuatorial, r 2 es el radio polar, y

r2
µ ¶
γ = arc cos .
r1

Asumimos r 2 < r 1 . Escriba un script que lea los radios ecuatorial y polar y exhiba en pan-
talla A ( r 1 , r 2 ) y la aproximación
r1 + r2 2
µ ¶
4π .
2
Aplique el script a los datos terrestres ( r 1 , r 2 ) = (6378.137, 6356.752). Exhiba suficientes
dígitos para mostrar la discrepancia entre la fórmula exacta y la aproximación.
15
Recordar que Octave está programada en inglés, y por ende, la función seno es representada por sin. Además,
la función logaritmo natural, escrita comúnmente como ln( x), es escrita en Octave como log(x).
1.2. Fundamentos de Programación 15

3) Una elipse con semiejes a y b está especificada por


µ ¶2 µ ¶2
x y
+ = 1.
a b

Si r = a = b entonces esto define una circunferencia cuyo perímetro está dado por P = 2π r .
Desafortunadamente, si a 6= b entonces no hay una fórmula simple para el perímetro y
debemos recurrir a una aproximación. Se conocen varias posibilidades:16

3h
µ ¶
P 1 = π( a + b ) P 5 = π( a + b ) 1 + p
10 + 4 − 3 h
p 64 − 3 h2
P2 = π 2(a2 + b2 ) P 6 = π( a + b )
s 64 − 16 h
(a − b)2 256 − 48 h − 21 h2
P3 = π 2(a2 + b2 ) − P 7 = π( a + b )
2 256 − 112 h + 3 h2
p
h 2 3− 1−h
µ ¶ µ ¶
P 4 = π( a + b ) 1 + P 8 = π( a + b )
8 2

Aquí,
¶2
a−b
µ
h= .
a+b
Escriba un script que solicite a y b e imprima en pantalla los valores P1 , . . . , P8 en una
manera que facilite la comparación. Los valores de h también deben ser exhibidos. Intente
los siguientes valores de entrada

(a, b) = (1, 1), (1, 0.9), . . . , (1, 0.1).

¿Qué puede afirmar acerca de las diferencias entre las fórmulas del perímetro cuando la
elipse se vuelve más ovalada en forma?

4) Suponga que el valor de x es un entero positivo. Escriba una expresión booleana que es
verdadera si x es divisible por 2, 5 y 7.

5) Escriba un script que solicite números reales L y R e imprima el valor máximo de f ( x) =


cos( x) en el intervalo [L, R ]. Asuma L < R . Recuerde que el coseno alcanza un valor máximo
de uno en múltiplos enteros de 2π.

6) Considere la función cúbica

q( x) = ax3 + bx2 + cx + d, a 6= 0.

Decimos que q es simple si sus tres raíces son reales y distintas. Decimos que q es monótona
si es siempre creciente o bien siempre decreciente. Como ejemplo, consideremos

q 1 ( x) = ( x − 1)( x − 2)( x − 3) = x3 − 6 x2 + 11 x − 6
q 2 ( x) = ( x − 1)( x − 2)( x − 3) + 100 = x3 − 6 x2 + 11 x + 94
q 3 ( x) = − x( x2 + 1) = − x3 − x
16
Véase http://www.mathsisfun.com/geometry/ellipse-perimeter.html
16 Capítulo 1. Introducción a Octave

entonces q 1 es simple pero no monótona, q 2 no es simple ni monótona, y q 3 es monótona


pero no simple. En este problema debe escribir un script que puede ser usado para verificar
estas situaciones. Como sugerencia, observe que la derivada q0 ( x) y sus raíces r 1 y r 2 son
importantes de tener en cuenta.
El script debe comenzar pidiendo al usuario los cuatro coeficientes a, b, c y d . Si r 1 y r 2 no
son reales y distintos, entonces q es monótona y el mensaje Función Monótona debe ser
impreso en pantalla. Caso contrario, los valores de r 1 , q( r 1 ), r 2 y q( r 2 ) deben ser impresos.
En este último caso q no es monótona y podemos deducir de los cuatro valores calculados si
es o no simple. En particular, q es simple si y sólo si q( r 1 ) q( r 2 ) < 0.

1.3 Bucles For y While


Muchas veces es necesario realizar un proceso iterativo varias veces. Si muy bien se podría
realizar esto a mano, resulta aburrido y monótono, y es mucho mejor dejar este trabajo a la
computadora, la cual no se va a quejar.
Estudiaremos dos maneras de iterar en Octave.

bucle for: Es una construcción que permite repetir un bloque de código un número determi-
nado de veces. La repetición está controlada por los valores que toma el indice. Su forma
más simple es:

for indice = valor_inicial : valor_final


Bloque de c ó digo
end

Es posible usar un bucle for dentro de otro. La necesidad de esto se verá más adelante.

bucle while: Es una construcción que permite repetir un bloque de código un número inde-
terminado de veces, hasta que se cumpla cierta condición. Toma la forma

while condici ó n_es_verdadera


Bloque de c ó digo
end

Cada vez que se repite el bloque de código el programa verifica si la condición sigue
siendo verdadera. Esto implica que dentro de este bloque debe existir alguna expresión
que llegará a cambiar el valor de verdad de la condición.

Ilustraremos el uso de estos tipos de bucle con los siguientes problemas resueltos.

Problema 3 (Embaldosado de un Disco. Uso del Bucle For): Supongamos que n es un


entero positivo y dibujemos el círculo x2 + y2 = n2 en un papel cuadriculado con cuadrados
de área unitaria y lado 1. La Fig. 1.1 exhibe el caso n = 10. Nótese que el área del disco es
π n2 y cada baldosa no cortada tiene área unitaria. Si hay N baldosas sin cortar, entonces
concluimos que
N ≈ π n2
ya que las baldosas sin cortar casi cubren el disco. Escriba un script que solicite al usuario
1.3. Bucles For y While 17

un entero n y exhiba la aproximación del número π

N
ρn =
n2

junto con el error ¯ρ n − π¯.


¯ ¯

Figura 1.1: Embaldosado del disco x2 + y2 ≤ n2 .

Solución del Problema


Para simplificar la solución podemos usar simetría. Cada cuadrante tiene exactamente el mis-
mo número de baldosas sin cortar. Así, solo necesitamos contar el número de baldosas sin
cortar en el primer cuadrante, como exhibimos en la Fig. 1.2. Si N1 es el número de baldosas
sin cortar en el primer cuadrante, entonces ρ n = 4 N1 / n2 .
Para calcular N1 sumamos el número de baldosas sin cortar que están localizadas en cada
fila horizontal. Refiriéndonos a la Fig. 1.2, vemos que hay nueve baldosas sin cortar en la fila
1 (row 1, en inglés), nueve baldosas sin cortar en la fila 2, etc. Para un n genérico, procedemos
como sigue:

Inicializar : N1 = 0
Repetir para filas 1 hasta la n
Calcular el n ú mero de baldosas sin cortar en la fila .
Añ adir este n ú mero a N1 .
Poner ρ n = 4N1 /n2 .

Dado que sabemos el número de veces que se va a repetir nuestro programa, utilizaremos
un bucle for. Refinamos nuestro seudocódigo así:

Asumir que n est á inicializada y poner N1 a cero


for k =1: n
Calcular el n ú mero de baldosas sin cortar en la fila k .
Añ adir este n ú mero a N1 .
end
Poner ρ n = 4N1 /n2

Ahora nos concentramos en cómo calcular el número de baldosas sin cortar en la fila k. En la
Fig. 1.2 recordemos que el origen (0, 0) se encuentra en la esquina inferior izquierda. El punto
18 Capítulo 1. Introducción a Octave

Figura 1.2: Embaldosado del Primer Cuadrante, caso n = 10.

(0, 1) (relativo a la fila 1), se encuentra obviamente encima del origen. La recta horizontal que
pasa por (0, 1), esto es, y = 1, interseca a la circunferencia en el punto
³p ´
n 2 − 12 , 1 .

Supongamos que ( h, 1) son las coordenadas del extremo superior derecho del último cuadradito
de la fila 1 que deseamos saber si es cortado o no por la circunferencia x2 + y2 = n2 . Recuérdese
que h es un número entero positivo. Para que este último cuadradito sea considerado como
baldosa sin cortar, debe suceder que
p
h ≤ n 2 − 12 ,

o lo que es mejor, h = floor(sqrt(n^2-1^2)). Podemos generalizar esta idea a la fila k, y


obtener que el número de baldosas sin cortar, en esa fila, debe ser

h = floor ( sqrt ( n ^2 - k ^2) )

Ahora pensemos en cómo calcular N1 . Antes del bucle for debemos inicializar N1 = 0. Para
actualizar este valor dentro del bucle for basta escribir

N1 = N1 + h

Esta sentencia se lee “el valor de N1 se actualiza con el valor que resulte de calcular N1 + h”.
Es importante recordar que el símbolo = no significa igualdad cuando programamos en Octave.
Resumiendo, formamos el siguiente pedazo de código

% asumiendo que ya hemos provisto el valor de n


N1 = 0;
for k = 1: n
h = floor ( sqrt ( n ^2 - k ^2) ) ;
N1 = N1 + h ;
end
ro_n = 4* N1 / n ^2;

Aquí, la variable k, llamada índice del bucle, toma valores del 1 al 10:
1.3. Bucles For y While 19

>> k = 1:10
k =
1 2 3 4 5 6 7 8 9 10

Podemos cambiar el conjunto de valores que toma el índice proveyendo un incremento, por
ejemplo

>> k = 1:2:10
k =
1 3 5 7 9

En general, esta construcción, llamado arreglo (unidimensional), puede construirse así:

nombre_arreglo = valor_inicial:incremento:valor_final

Aquí, el incremento puede ser cualquier número real positivo y asumimos que el valor_inicial
es menor o igual que el valor_final. Estos valores pueden ser números decimales. Por ejemplo:

>> k = -2.35:1.4:4.5
k =
-2.3500 -0.9500 0.4500 1.8500 3.2500

Si el valor_inicial es mayor que el valor_final obtenemos un arreglo vacío. Por otro lado,
es posible también usar un decremento si deseamos un arreglo ordenado en forma decreciente:

nombre_arreglo = valor_inicial:decremento:valor_final

El siguiente script resuelve el problema.

Programa 1.5: Script AproximaPi.m


1 % Este programa aproxima el n ú mero irracional pi usando
2 % conteo de á reas de cuadrados inscritos en un disco
3
4 % Ingrese el radio del disco
5 clc
6 n = input ( ' Ingrese un radio con valor entero n : ') ;
7
8 % Embaldosar solo el primer cuadrante y luego multiplicar por cuatro
9 N1 = 0;
10 for k = 1: n
11 % calcular el n ú mero de baldosas " sin cortar " en fila k
12 h = floor ( sqrt ( n ^2 - k ^2) ) ;
13 N1 = N1 + h ;
14 end
15
16 % cá lculo de la aproximaci ó n de pi
17 ro_n = 4* N1 / n ^2;
18
19 % Exhibici ó n del estimado y del error
20 clc
21 fprintf ( 'n = %12 d \ n ' ,n ) ;
20 Capítulo 1. Introducción a Octave

22 fprintf ( ' ro_n = %12.8 f \ n ' , ro_n ) ;


23 fprintf ( ' error = %12.8 f \ n ' , abs ( pi - ro_n ) ) ;

Por ejemplo, para n = 104 obtenemos

n = 10000
ro_n = 3.14119052
error = 0.00040213

Problema 4 (Polígonos inscritos y circunscritos. Uso del Bucle While): Supongamos


que tenemos n puntos igualmente espaciados sobre el círculo unitario x2 + y2 = 1. Si conec-
tamos estos puntos en orden obtendremos un polígono regular inscrito de n lados. Pero si
conectamos las rectas tangentes en estos puntos obtendremos un polígono regular circuns-
crito de n lados. La Fig. 1.3 exhibe estas construcciones para el caso n = 6. El área del círculo
unitario es π. Las áreas de los polígonos inscrito y circunscrito están dadas por

n 2π
µ ¶
A n = sen ,
2 n
π
µ ¶
B n = n tan ,
n

respectivamente. Es obvio que para todo n

A n < π < Bn.

Usando la Fig. 1.3 para guiarnos, podemos deducir que el promedio de las dos áreas poligo-
nales
A n + Bn
ρn =
2
es una aproximación de π, con error absoluto que satisface

¯ρ n − π ¯ < B n − A n .
¯ ¯

Claramente el error converge a cero cuando n → ∞.


Escriba un script que solicite al usuario una tolerancia positiva real δ y exhiba el valor
de ρ m , donde m es el entero más pequeño tal que

( B m − A m ) ≤ δ.

Esto garantiza que ρ m esté a una distancia menor que δ de π.

Solución del Problema


Es útil comenzar exhibiendo un script que revele la calidad de la aproximación ρ n cuando n
crece:

n = 10;
for k = 1:8
A_n = ( n /2) * sin (2* pi / n ) ;
1.3. Bucles For y While 21

Figura 1.3: Hexágonos inscritos y circunscritos.

B_n = n * tan ( pi / n ) ;
ro_n = ( A_n + B_n ) /2;
n = 10* n ;
end

Los valores de ensayo son n = 10, 102 , 103 , . . . , 108 . Si añadimos más líneas de código para im-
primir en pantalla, conseguimos:

n A_n B_n | ro_n - pi |


------- ----- ----- ---- ----- ---- ----- ----- ---- ----- ---- ----- ---- -
1.00 e +01 2.9389262614623659 3.2491969623290631 4.75 e -02
1.00 e +02 3.1395259764656687 3.1426266043351152 5.16 e -04
1.00 e +03 3.1415719827794755 3.1416029890561563 5.17 e -06
1.00 e +04 3.1415924468812859 3.1415927569440529 5.17 e -08
1.00 e +05 3.1415926515227079 3.1415926546233357 5.17 e -10
1.00 e +06 3.1415926535691225 3.1415926536001288 5.17 e -12
1.00 e +07 3.1415926535895866 3.1415926535898966 5.15 e -14
1.00 e +08 3.1415926535897909 3.1415926535897944 4.44 e -16

Podemos deducir que para un n dado, el error es aproximadamente 1/ n2 .


Nuestra investigación con el bucle for es interesante, pero no nos ayuda directamente con el
problema a mano. Debemos encontrar el mínimo valor de n tal que (B n − A n ) < δ. Supongamos
que este mínimo ocurre en n = m. Como no sabemos cuándo sucederá esto, podemos acercarnos
poco a poco aumentando el valor de n. El siguiente seudocódigo ilustra el proceso a seguir:

Ingrese la tolerancia ( error ) δ y ponga n = 3 .


Calcule A 3 , B3 y la cota del error B3 − A 3 .
Repetir el siguiente bloque mientras la cota del error sea mayor que ←-
δ:
Incrementar n por uno .
Actualizar A n , B n y la cota del error B n − A n .
Poner m = n y exhibir ρ m .

Un bucle for no puede ser usado porque debemos saber el número de iteraciones por ade-
lantado y esto es justo lo que buscamos. Un mecanismo alternativo para iterar es el bucle while.
Su uso en el seudocódigo anterior se implementa en Octave como sigue:

delta = input ( ' Ingrese delta : ') ;


22 Capítulo 1. Introducción a Octave

n = 3; A_n = ( n /2) * sin (2* pi / n ) ; B_n = n * tan ( pi / n ) ;


CotaError = B_n - A_n ;
while CotaError > delta
n = n + 1;
A_n = ( n /2) * sin (2* pi / n ) ;
B_n = n * tan ( pi / n ) ;
CotaError = B_n - A_n ;
end
m = n; ro_m = ( A_n + B_n ) /2;

Si la expresión lógica CotaError > delta es verdadera, entonces el cuerpo del bucle es
ejecutado. Esta ejecución se repetirá hasta que la expresión lógica sea falsa. Cuando el bucle
termina de ejecutarse, el programa continuará ejecutando las líneas debajo de la palabra end.
Debemos tener presente que variables que sean utilizadas por el bucle while deben iniciali-
zarse antes de comenzar el bucle.
La solución final del problema es presentada en el siguiente script.

Programa 1.6: Script AproximaPiConBucleWhile.m


1 % Este programa aproxima el numero pi con una tolerancia dada por el
2 % usuario , en base a á reas de pol í gonos inscritos y circunscritos a ←-
una
3 % circunferencia .
4
5 % Ingresar los par á metros de iteraci ó n
6 clc
7 delta = input ( ' Ingrese la tolerancia del error : ') ;
8 nMax = input ( ' Ingrese numero m á ximo de iteraciones : ') ;
9
10 % Caso primario : triangular
11 n = 3; % N ú mero de lados del pol í gono
12 A_n = (n /2) * sin (2* pi / n ) ; % Area inscrita
13 B_n = n* tan ( pi / n ) ; % Area circunscrita
14 CotaError = B_n - A_n ; % Cota del error
15
16 % Iterar mientras que el error sea demasiado grande y n peque ñ o
17 while ( CotaError > delta ) && ( n < nMax )
18 n = n +1;
19 A_n = ( n /2) * sin (2* pi / n ) ;
20 B_n = n * tan ( pi / n ) ;
21 CotaError = B_n - A_n ;
22 end
23
24 % Exhibir la aproximaci ó n final
25 m = n;
26 ro_m = ( A_n + B_n ) /2;
27 clc
28 fprintf ( ' delta = %10.3 e \ n m = %1 d \ n nMax = %1 d \ n \ n ' , delta ,m , ←-
nMax );
29 fprintf ( ' ro_m = %20.15 f \ n Pi = %20.15 f \ n ' , ro_m , pi ) ;
1.3. Bucles For y While 23

Observemos que la condición al inicio del bucle while en un principio es verdadera (caso
contrario no se ejecutaría iteración alguna), y basta que una de las proposiciones encerradas
entre paréntesis llegue a ser falsa para que el bucle termine. Si no se hubiese tenido el cuidado
de incorporar un número máximo de iteraciones (nMax) podría haberse incurrido en un bucle
infinito (esto ocurriría si damos, por ejemplo, un δ muy pequeño como 10−20 ). Recordar que
en caso el programa tarde mucho en exhibir el output, debe usarse Ctrl-c para abortar la
ejecución.
Para el input δ = 10−6 y nMax=104 obtenemos la siguiente salida

delta = 1.000 e -06


m = 5569
nMax = 1000000

ro_m = 3.141592486963389
Pi = 3.141592653589793

Recomendaciones de Buena Programación


Aunque las siguientes reglas pueden obviarse, recomendamos seguirlas con el fin de evitar
posibles errores dentro de un programa, sobre todo cuando éste se vuelve más largo y complejo.
• Indentar los bloques de código dentro del bucle respectivo. Esto permitirá una
lectura más fácil del programa, no solo para uno mismo, sino para que sea entendido por
otras personas.
• Nunca modificar el valor del índice dentro del bloque de un bucle for. Este error
común de programador novato trae consecuencias desastrosas, y cuando son cometidos,
a veces son difíciles de ubicar.
• Decidir si la iteración es mejor manipulada por un bucle for o un bucle while. Si
el número de iteraciones es conocido por adelantado, entonces un bucle for es apropiado.
• Asegurarse que el rango de valores de un bucle for es el correcto. Con frecuen-
cia, probar primero con un rango de valores pequeño ayuda para verificar si la idea que
queremos llevar a cabo es correcta.

Comandos Adicionales para uso en bucles: break y continue


Podemos controlar las iteraciones de los bucles for y while con los siguientes dos comandos
que se colocan en el cuerpo del bucle:

break: Cuando es ejecutada la línea que contiene al comando break, el bucle es obligado a
terminar y el control del programa pasa a la línea de código ubicada después del fin (end)
del bucle.

continue: Cuando es ejecutado este comando el bucle vuelve a reiniciarse con el próximo valor
de la iteración.

El siguiente programa ilustra el uso del comando break.

Programa 1.7: Script UsoDeBreakConFor.m


1 % uso de break dentro del bucle for
2 clc
24 Capítulo 1. Introducción a Octave

3 x = 0;
4 for i =1:5
5 x = x + 1;
6 if i == 3
7 break ;
8 end
9 fprintf ( ' Para iteraci ó n i = %1d , el valor de x es %1 d \ n ',i , x ) ;
10 end
11 disp ( ' Este aviso aparece despu é s de terminado el bucle ') ;
12 fprintf ( ' El valor actual de x en memoria es %1 d \ n ' ,x ) ;

Si compilamos el programa obtenemos

Para iteraci ó n i = 1 , el valor de x es 1


Para iteraci ó n i = 2 , el valor de x es 2
Este aviso aparece despu é s de terminado el bucle
El valor actual de x en memoria es 3

Queda como ejercicio justificar porqué el valor en memoria para x es 3. El siguiente programa
ilustra el uso del comando continue.

Programa 1.8: Script UsoDeContinueConFor.m


1 % uso de continue dentro del bucle for
2 clc
3 x = 0;
4 for i =1:5
5 if i == 3
6 continue ;
7 end
8 x = x + 1;
9 fprintf ( ' Para iteraci ó n i = %1d , el valor de x es %1 d \ n ',i , x ) ;
10 end
11 disp ( ' Este aviso aparece despu é s de terminado el bucle ') ;
12 fprintf ( ' El valor actual de x en memoria es %1 d \ n ' ,x ) ;

Si compilamos el programa obtenemos

Para iteraci ó n i = 1 , el valor de x es 1


Para iteraci ó n i = 2 , el valor de x es 2
Para iteraci ó n i = 4 , el valor de x es 3
Para iteraci ó n i = 5 , el valor de x es 4
Este aviso aparece despu é s de terminado el bucle
El valor actual de x en memoria es 4

1.3.1 Problemas Propuestos


1) Usando diversos valores de n en el programa aproximapi.m, ¿en cuánto varía el error si n
es incrementado por un factor de 10?, ¿cuánto se incrementaría el tiempo de ejecución si n
es incrementado por un factor de 10? Use el comando tic ... toc para calcular el tiempo
de ejecución.
1.4. Ploteo en Dos Dimensiones 25

2) Modifique el script aproximapi.m para que exhiba el valor de ¯π − ρ n ¯ para n = 10 j , j = 1:8.


¯ ¯

3) Para n suficientemente grande se saben que


1 (−1)n+1 X n (−1) k+1 π
Rn = 1 − +···− = ≈ ,
3 2n − 1 k=1 2 k − 1 4
1 1 n 1
X π2
Tn = 1 + + · · · + = ≈ ,
22 n2 k=1 k2 6
1 1 n 1
X π4
Un = 1 + + · · · + = ≈ ,
24 n4 k=1 k4 90
los cuales nos dan tres maneras diferentes para estimar π:
p p
4
ρn = 4 Rn, τn = 6 T n , µn = 90 Un .

Escriba un script que exhiba los valores de ¯π − ρ n ¯, |π − τn |, y ¯π − µn ¯ para n = 100,200,300,. . . ,


¯ ¯ ¯ ¯

1000.

4) Escriba un script que verifique las desigualdades


2 p Xn p 4n + 3 p
n n≤ k≤ n
3 k=1 6
para n = 1, . . . , 100.

5) Modifique el programa 1.6 de manera que termine el bucle cuando


| A n+1 − A n | ≤ δ ó |B n+1 − B n | ≤ δ.

6) Añada comandos apropiados (fprintf o disp) al fragmento de código (bucle for) de la


pág. 21, para obtener la tabla de valores mostrada en esa página, para n = 10, 102 , . . . , 108 .

7) La implementación del programa 1.6 requiere la constante predefinida pi. Usando repeti-
damente las fórmulas de ángulo mitad
s s
1 + cos(θ ) 1 − cos(θ )
cos(θ /2) = , sen(θ /2) = ,
2 2
podemos evitar esta dependencia y producir un método genuino que “descubra” π. Observe
que el caso n = 3 involucra
p p
cos(π/3) = 1/2, sen(π/3) = 3/2, y sen(2π/3) = 3/2.
Las evaluaciones necesarias para coseno y seno para A 6 y B6 pueden ser obtenidas de es-
tos valores vía las fórmulas de ángulo mitad. Usando estas evaluaciones trigonométricas
actualizadas, podemos obtener los valores necesarios de coseno y seno para A 12 y B12 , etc.
Use esta idea para escribir un script que pida un número positivo δ > 10−12 y calcule un
estimado de π con un error menor que δ.

1.4 Ploteo en Dos Dimensiones


En esta sección aprenderemos a cómo manipular arreglos, tener acceso a sus componentes, y
plotear funciones reales de variable real.
26 Capítulo 1. Introducción a Octave

Problema 5: Escriba un script que exhiba la gráfica de la función

sen(5 x) exp(− x/2)


f ( x) =
1 + x2
en el intervalo [−2, 3].

Solución del Problema

Primero ilustraremos cómo plotear una función más simple g( x) = sen( x) en el intervalo [0, 2π].
Debemos entender que la manera cómo funciona el ploteo en Octave (y en todos los software)
es dibujar en el plano un conjunto finito de puntos y luego unirlos con segmentos de recta. En
otras palabras, lo que se plotea en una computadora es realmente un camino poligonal. Sin
embargo, podemos “engañar” nuestra vista si ploteamos una cantidad suficiente de puntos.
Por ejemplo, grafiquemos la función seno con una cantidad insuficiente de puntos. Primero
construimos los puntos ( x, g( x)) almacenando las abscisas y ordenados en arreglos separados:

>> x = 0:2* pi
x =
0 1 2 3 4 5 6
>> y = sin ( x ) ;

Observar que la función seno se aplica componente a componente, y por ende el arreglo y es
del mismo tamaño que x. Para plotear los puntos y unirlos con segmentos de recta usamos el
comando plot

plot (x ,y ) ;
shg ; % show graph ( mostrar gr á fica )

El comando shg es usado para que la ventana de ploteo (titulada Figure 1), aparezca encima
de todas las ventanas abiertas (lo cual a veces no es necesario). El resultado de este ploteo se
muestra en la Fig. 1.4. Respondemos el problema con el siguiente script

Programa 1.9: Script miploteo2d.m

1 clc , close all


2 x = linspace ( -2 ,3 ,80) ;
3 y = sin (5* x ) .* exp ( - x /2) ./(1+ x .^2) ;
4 plot (x ,y) , grid on
5 shg

lo cual nos da la siguiente gráfica


1.4. Ploteo en Dos Dimensiones 27

Figura 1.4: Ploteo de y = sen( x) usando 7 puntos.

1.4.1 Problemas Propuestos


1. Defina la elipse E (θ , a, b) por

x( t) = a cos( t) cos(θ ) − b sen( t) sen(θ )


y( t) = b sen( t) cos(θ ) + a cos( t) sen(θ )

donde 0 ≤ t ≤ 2π y θ es el “ángulo de inclinación”. Escriba un script que plotee E (0, 3, 1),


E (π/6, 3, 1), E (π/3, 3, 1) y E (π/2, 3, 1) en una misma ventana. Además adjunte en su gráfica
una leyenda para reconocer cual gráfica corresponde con el respectivo ángulo θ .
28 Capítulo 1. Introducción a Octave

2. Para i=1:5 y j=1:5, sea Ei j la elipse ( x/ i )2 + ( y/ j )2 = 1. Escriba un script que exhiba en


una tabla 5 × 5, el perímetro de todas las elipses. Use P_prom con tol colocado a 0.001.

3. Implemente la siguiente función sin bucles:

function L = PolyLine (u , v )
% u y v son vectores columna ( n +1) x 1 , con u (1) = u ( n +1) y v (1) ←-
= v ( n +1) .
% L es el perimetro del poligono con vertices
% (u (1) ,v (1) ) , ... , ( u ( n ) ,v ( n ) )

Sug: Si z es un vector de longitud 5, esto es, z = ( z1 , z2 , z3 , z4 , z5 ), entonces

alfa = sum(abs(z(1:4)-z(2:5)))

asigna a alfa el valor de

α = | z1 − z2 | + | z2 − z3 | + | z3 − z4 | + | z4 − z5 |

4. Implemente una versión libre de bucles para la función P_prom

1.5 Simulación Monte Carlo


Problema 6: Consideremos un objetivo que consiste de un cuadrado de lado de longitud 2
centrado en el origen, y con un disco unitario en su centro (el objetivo).
Un dardo es tirado hacia el objetivo y cae aleatoriamente sobre el cuadrado. El tiro ha
tenido “éxito” si cae dentro de la circunferencia

x2 + y2 ≤ 1.

Si tiramos n dardos (con n grande), entonces la fracción de tiros que tienen éxito debería
aproximar al cociente entre el área de la circunferencia y el área del cuadrado, esto es

Nro. de éxitos πr2


≈ .
n (2 r )2

Esto nos provee de una fórmula para estimar π:

4(Nro. de éxitos)
π= .
n
Escriba un script que simule el tiro de 10 000 dardos y escriba un estimado para π. Los dardos
deben estar uniformemente distribuidos sobre el cuadrado. ¿Qué sucede si los dardos están
predispuestos a caer cercano al origen? ¿Cómo afecta esto en la estimación de π?

Solución del Problema


Veamos cómo usar rand para simular eventos aleatorios. El siguiente script exhibirá una su-
cesión de números que cumple:
1.5. Simulación Monte Carlo 29

• Cada número está en el intervalo abierto ]0, 1[.


• La sucesión no revela algún patrón de formación.

Programa 1.10: Script mcprog01.m


1 clc
2 format long
3 n = input ( ' Ingrese entero positivo : ') ;
4 for k = 1: n
5 r = rand (1) ; % genera un n ú mero aleatorio
6 fprintf ( ' %16.14 f \ n ' ,r ) ;
7 end

La distribución es uniforme en el intervalo ]0, 1[ si dados dos números L y R que satisfagan

0 < L < R < 1,

entonces la probabilidad de que el valor de r=rand(1) esté en el intervalo [L, R ] es R − L.


Consideremos el siguiente script para ilustrar esto.

Programa 1.11: Script mcprog02.m


1 clc
2 n = input ( ' Ingrese nro de repeticiones : ') ;
3 L = input ( ' Ingrese L (0 <L <1) : ') ;
4 R = input ( ' Ingrese R (L <R <1) : ') ;
5 conta = 0; % contador
6 for k = 1: n
7 r = rand (1) ;
8 if L <= r && r <= R
9 conta = conta + 1;
10 end
11 end
12 p = conta /n ;
13 disp ( ' Probabilidad de que los n ú meros caigan ')
14 fprintf ( ' en el intervalo [L , R ]: %6.4 f \ n ' ,p )
15 fprintf ( ' longitud de [L , R ] = %6.4 f \ n ' ,R - L )

Al ejecutar este script para n=10e4 y luego n=10e6 vemos que la probabilidad obtenida
concuerda muy bien con la longitud del intervalo [L, R ]. Para n=100 no se puede apreciar que
la distribución de los números en [L, R ] sea uniforme.
Una consecuencia de la distribución uniforme es que para n grande el comando rand elige
cualquier número entre 0 y 1 con igual probabilidad (la elección es insesgada).
La función rand puede ser usada para construir un vector de números aleatorios. Si n ∈ Z+ ,
entonces

r = rand (n ,1)

crea un vector columna n × 1 de números aleatorios.


Vamos a producir un gráfico de barras que muestre la fracción de valores producidos por
rand que caen en cada decil, esto es, cuántos valores generados por rand caen entre
]0, 0.1], ]0.1, 0.2], ]0.2, 0.3], . . . , ]0.9, 1[.
30 Capítulo 1. Introducción a Octave

Para una mejor visualización construiremos un vector aleatorio de números enteros que varíen
del 1 al 10. Aquí, cada decil formaría los intervalos ]0, 1], ]1, 2], . . . , ]9, 10].

Programa 1.12: Script mcprog03.m


1 clc
2 n = input ( ' Ingrese nro de repeticiones : ') ;
3 r = rand (n ,1) ; % vector aleatorio con entradas entre 0 y 1
4 s = 10* r; % vector aleatorio con entradas entre 0 y 10
5 d = ceil (s ) ; % vector aleatorio de enteros entre {1 ,2 ,... ,10}
6
7 % grafico de barras
8 conta = zeros (10 ,1) ;
9 for k = 1: n
10 j = d( k ) ;
11 conta ( j ) = conta ( j ) + 1;
12 end
13 bar ( conta , 'm ') ; shg

Para el caso n=1e4 obtenemos

Si aumentamos a n=1e6 (un millón de repeticiones) obtenemos una gráfica de barras con al-
turas de casi el mismo tamaño. Esto nos dice que a mayor número de repeticiones el comando
rand nos da una distribución uniforme de números entre 1 y 10, incluyendo extremos. Así, cual-
quier entero entre 1 y 10 tiene igual probabilidad de ser elegido por el comando rand (luego de
haberlo reescalado, trasladado y aplicado el comando ceil).
Podemos concluir que una simulación aleatoria debe realizarse un gran número de
veces, caso contrario se corre el peligro de que no se cumpla una elección al azar con el tipo de
distribución elegida. En nuestro caso, al usar rand estamos usando una distribución uniforme.
Examine qué ocurre cuando ejecuta el script anterior con 20 o 100 repeticiones.
Algunos descriptores estadísticos de un conjunto de datos, más usuales, son:
• La media, que es el promedio de la data (Octave: mean).
• La desviación estándar, que mide el esparcimiento de la data alrededor de la media
(Octave: std).
1.5. Simulación Monte Carlo 31

Programa 1.13: Script mcprog04.m


1 clc
2 m1 = [0 0 14 14];
3 m2 = [0 6 8 14];
4 m3 = [6 6 8 8];
5 fprintf ( ' media1 = %6.4 f , sigma1 = %6.4 f \ n ' , mean ( m1 ) , std ( m1 ) )
6 fprintf ( ' media2 = %6.4 f , sigma2 = %6.4 f \ n ' , mean ( m2 ) , std ( m2 ) )
7 fprintf ( ' media3 = %6.4 f , sigma3 = %6.4 f \ n ' , mean ( m3 ) , std ( m3 ) )

Obtenemos el siguiente output:

media1 = 7.0000 , sigma1 = 8.0829


media2 = 7.0000 , sigma2 = 5.7735
media3 = 7.0000 , sigma3 = 1.1547

El siguiente script resuelve el problema de tirar un dardo n veces sobre el cuadrado [−1, 1] ×
[−1, 1], sin sesgamiento, esto es, con distribución uniforme, para estimar el valor de pi.

Programa 1.14: Script mcprog05.m


1 clc , close all
2 n = input ( ' Ingrese nro de repeticiones : ') ;
3 % elegir n <= 1 e4 para apreciar un buen ploteo de
4 % puntos aleatorios
5 exitos = 0;
6 x = -1 + 2* rand (n ,1) ;
7 y = -1 + 2* rand (n ,1) ;
8 % figure
9 % axis equal
10 % teta = linspace (0 ,2* pi ) ;
11 % xcirc = cos ( teta ) ;
12 % ycirc = sin ( teta ) ; hold on
13 % plot ( xcirc , ycirc , 'r ' ,' LineWidth ' ,2) ;
14 % plot (x ,y , '.b ') ;
15 % hold off
16 for k = 1: n
17 if x(k) ^2 + y ( k ) ^2 <=1
18 exitos = exitos + 1;
19 end
20 end
21 piEst = 4*( exitos / n ) ;
22 fprintf ( ' Valor Est . de pi es : %11.9 f \ n ', piEst ) ;
23 fprintf ( ' Valor exacto de pi es : %11.9 f \ n ', pi ) ;

Compilamos

Ingrese nro de repeticiones : 1 e4


Valor Est . de pi es : 3.162000000
Valor exacto de pi es : 3.141592654

NOTA: No digitar 1e9 porque Octave no soporta crear un vector de ese tamaño.
32 Capítulo 1. Introducción a Octave

Ahora apreciemos cómo está distribuida la data para n=1e4, borrando en el script anterior
los porcentajes al comienzo de las líneas 8 a la 15. Obtenemos la siguiente figura:

Ahora vamos a predisponer los dardos a que caigan cerca al origen. Para ello, usaremos una
distribución normal, lo cual se consigue con el uso del comando randn. La asignación

r = randn(n,1)

produce un vector columna n × 1 cuyas entradas siguen una distribución normal con media cero
y desviación estándar uno. El siguiente script exhibe el comportamiento de una distribución
normal para una muestra de 106 repeticiones, ploteando su histograma.

Programa 1.15: Script mcprog06.m


1 % este programa ilustra el comportamiento de una
2 % distribuci ó n normal con media cero y sigma = 1.
3 clc , close all
4 mu = 0; % cambiar si se desea otra media
5 sigma = 1; % cambiar si se desea otra desviaci ó n est á ndar
6 r = mu + sigma * randn (1 e6 ,1) ;
7 x = linspace ( -3 ,3 ,25) ; % 25 casilleros
8 hist (r ,x) % plotea un histograma de la muestra por
9 % casillero
10 % para cambiar de color
11 h = findobj ( gca , ' Type ', ' patch ') ;
12 h. FaceColor = 'm ';
13 h. EdgeColor = 'w ';
14 shg

Al compilar obtenemos:
1.5. Simulación Monte Carlo 33

La distribución normal, en principio, nos puede dar cualquier número real, pero con mayor
probabilidad de que sea elegido un número cercano a la media, que lejos de ella.
El siguiente script implementa lanzamientos sesgados (con predilección a que los dardos
caigan cercanos al origen).

Programa 1.16: Script mcprog07.m


1 clc , close all
2 n = input ( ' Ingrese nro de repeticiones : ') ;
3 % elegir n <= 1 e4 para apreciar un buen ploteo de
4 % puntos aleatorios
5 exitos = 0;
6 ncuad = 0;
7 sigma = 0.4;
8 x = sigma * randn (n ,1) ;
9 y = sigma * randn (n ,1) ;
10 %--- inicio : codigo de ploteo de figura ( OPCIONAL )
11 figure
12 teta = linspace (0 ,2* pi ) ;
13 xcirc = cos ( teta ) ;
14 ycirc = sin ( teta ) ;
15 plot (x ,y , '. b ') , hold on
16 plot ( xcirc , ycirc , 'r ', ' LineWidth ' ,2)
17 axis ([ -2 ,2 , -2 ,2])
18 plot ([ -1 1 1 -1 -1] ,[ -1 -1 1 1 -1] , ' -k ', ' LineWidth ' ,1.5)
19 axis equal
20 hold off
21 %--- fin : codigo de ploteo de figura
22 for k = 1: n
23 if abs ( x ( k ) ) <=1 && abs ( y ( k ) ) <=1
24 ncuad = ncuad + 1;
25 if x ( k ) ^2 + y ( k ) ^2 <=1
26 exitos = exitos + 1;
27 end
28 end
34 Capítulo 1. Introducción a Octave

29 end
30 piEst = 4*( exitos / ncuad ) ;
31 fprintf ( ' Valor Est . de pi es : %11.9 f \ n ', piEst ) ;
32 fprintf ( ' Valor exacto de pi es : %11.9 f \ n ', pi ) ;

Potrebbero piacerti anche