CMN Un
CMN Un
CMN Un
A Hel`ene, Nicol
as y Sylvie
ii
INDICE GENERAL
Pr
ologo
ix
1 Introducci
on
2 Generalidades
2.1
El primer programa . . . . . . . . . . . . . . . . . . . . .
2.2
2.2.1
g++ . . . . . . . . . . . . . . . . . . . . . . . . . . 10
2.2.2
bcc32 . . . . . . . . . . . . . . . . . . . . . . . . . 10
2.2.3
Turbo C++ . . . . . . . . . . . . . . . . . . . . . . 11
2.2.4
Visual C++ . . . . . . . . . . . . . . . . . . . . . . 12
2.2.5
Dev-C++ . . . . . . . . . . . . . . . . . . . . . . . 14
2.3
Comentarios . . . . . . . . . . . . . . . . . . . . . . . . . . 15
2.4
Identificadores . . . . . . . . . . . . . . . . . . . . . . . . 16
2.5
Tipos de datos . . . . . . . . . . . . . . . . . . . . . . . . 19
2.6
Operador de asignaci
on . . . . . . . . . . . . . . . . . . . 21
2.7
Operadores aritmeticos . . . . . . . . . . . . . . . . . . . . 22
2.8
2.9
Abreviaciones usuales . . . . . . . . . . . . . . . . . . . . 27
INDICE GENERAL
3 Estructuras de control
41
3.1
if . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
3.2
Operadores relacionales y l
ogicos . . . . . . . . . . . . . . 45
3.3
for . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
3.4
while . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51
3.5
do while . . . . . . . . . . . . . . . . . . . . . . . . . . . 54
3.6
switch . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57
3.7
break . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58
3.8
continue . . . . . . . . . . . . . . . . . . . . . . . . . . . 60
3.9
goto y exit . . . . . . . . . . . . . . . . . . . . . . . . 61
4 Funciones
67
4.1
Generalidades . . . . . . . . . . . . . . . . . . . . . . . . . 67
4.2
Funciones recurrentes . . . . . . . . . . . . . . . . . . . . 75
4.3
Par
ametros por valor y por referencia . . . . . . . . . . . 76
4.4
Par
ametros por defecto
4.5
4.6
Sobrecarga de funciones . . . . . . . . . . . . . . . . . . . 83
4.7
Biblioteca estandar . . . . . . . . . . . . . . . . . . . . . . 85
. . . . . . . . . . . . . . . . . . . 81
5 Arreglos
87
5.1
Arreglos unidimensionales . . . . . . . . . . . . . . . . . . 87
5.2
Arreglos multidimensionales . . . . . . . . . . . . . . . . . 94
5.3
Cadenas . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98
5.4
Inicializaci
on de arreglos . . . . . . . . . . . . . . . . . . . 103
6 Apuntadores
109
6.1
6.2
6.3
6.4
6.5
6.6
Asignaci
on din
amica de memoria . . . . . . . . . . . . . . 131
iv
INDICE GENERAL
6.7
6.8
. . . . . . . . . . . . . . . 135
143
7.1
7.2
feof . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 148
7.3
8 Temas varios
157
8.1
sizeof . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 157
8.2
const . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 159
8.3
typedef . . . . . . . . . . . . . . . . . . . . . . . . . . . . 159
8.4
include . . . . . . . . . . . . . . . . . . . . . . . . . . . . 161
8.5
define . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 164
8.6
8.7
8.8
Argumentos de la funcion
main . . . . . . . . . . . . . . 171
9 Estructuras
175
9.1
9.2
183
10.1 C
odigo de algunas funciones . . . . . . . . . . . . . . . . . 184
10.2 Versiones con saltos . . . . . . . . . . . . . . . . . . . . . 190
10.3 Metodo burbuja . . . . . . . . . . . . . . . . . . . . . . . . 194
11 Soluci
on de sistemas lineales
199
. . . . . . . . . . . . . . . . 204
INDICE GENERAL
. . . . . . . . . . . . . . . . 213
11.7 Factorizaci
on LU . . . . . . . . . . . . . . . . . . . . . . . 215
11.8 Metodo de Gauss con pivoteo parcial . . . . . . . . . . . . 217
11.9 Factorizaci
on LU =PA . . . . . . . . . . . . . . . . . . . . 223
11.10 Metodo de Cholesky . . . . . . . . . . . . . . . . . . . . 227
11.10.1 Matrices definidas positivas . . . . . . . . . . . . 227
11.10.2 Factorizaci
on de Cholesky . . . . . . . . . . . . . 229
11.10.3 N
umero de operaciones de la factorizacion . . . . 235
11.10.4 Solucion del sistema . . . . . . . . . . . . . . . . 237
11.11 Metodo de Gauss-Seidel . . . . . . . . . . . . . . . . . . 239
11.12 Solucion por mnimos cuadrados . . . . . . . . . . . . . . 245
11.12.1 Derivadas parciales . . . . . . . . . . . . . . . . . 246
11.12.2 Ecuaciones normales . . . . . . . . . . . . . . . . 247
12 Soluci
on de ecuaciones
255
Rn
. . . . 278
. . . . . . . . . . . . . . . . . . 279
285
13.1 Interpolaci
on . . . . . . . . . . . . . . . . . . . . . . . . . 287
13.2 Interpolaci
on de Lagrange . . . . . . . . . . . . . . . . . . 289
vi
INDICE GENERAL
313
. . . . . . . . . . . . . . . . 317
. . . . . . . . . . . . . . . . 320
337
INDICE GENERAL
389
viii
Pr
ologo
El prop
osito de este libro es presentar los conceptos m
as importantes
del lenguaje C y varios temas de metodos numericos. Tambien estan
algunos temas sencillos y muy u
tiles de C++.
Esta dirigido principalmente, pero no de modo exclusivo, para el
curso Programaci
on y Metodos Numericos que deben tomar los estudiantes de las carreras de Matem
aticas y de Estadstica en la Universidad
Nacional. Estos estudiantes ya han visto calculo diferencial y estan cursando, de manera simult
anea, calculo integral y algebra lineal. Adem
as
se supone que los lectores tienen nociones elementales sobre los computadores, en particular sobre el manejo de un editor de texto.
Los primeros 14 captulos se pueden cubrir en un semestre. En
tiempo, esto corresponde a cinco horas semanales durante quince semanas aproximadamente. Obtener un nivel medio de programaci
on no es
difcil pero requiere de manera indispensable bastante tiempo de practica
frente a un computador.
El captulo 15, sobre solucion numerica de ecuaciones diferenciales
ordinarias, no corresponde al programa del curso, pero est
a incluido para
no dejar por fuera un tema tan importante. Sin embargo, otro tema muy
u
til, solucion numerica de las ecuaciones diferenciales parciales, no esta
incluido. Tampoco se trata el tema del calculo de valores y vectores
propios.
En la pagina electr
onica del autor, se encontrar
a una fe de erratas del
libro, que se ir
a completando a medida que los errores sean detectados.
En esta pagina tambien esta el codigo para algunos metodos y otros
documentos relacionados con el tema. Actualmente la direccion es:
www.matematicas.unal.edu.co/~hmora/
ix
Introducci
on
El lenguaje de programaci
on m
as utilizado para calculos cientficos es el
Fortran, bien sea en sus versiones originales, en Fortran-77 o en Fortran90. Inicialmente Fortran fue el u
nico lenguaje empleado para calculo
cientfico. Posteriormente se utilizaron tambien otros lenguajes, como
Algol, PL-1, Pascal, C, C++...
Actualmente se sigue utilizando ampliamente Fortran en laboratorios de investigacion del m
as alto nivel pues, adem
as de sus buenas
cualidades, hay muchos programas y bibliotecas hechos en ese lenguaje.
Estos programas han sido probados muchas veces y por tanto su confiabilidad es muy grande. No son pues crebles las opiniones, salidas de
algunos sectores informaticos, sobre la obsolescencia del Fortran.
Sin embargo, actualmente una parte importante de programas para
calculo cientfico se hace en C y C++. Entre sus ventajas, algunas
compartidas tambien por Fortran, se pueden citar:
Disponibilidad: es posible encontrar facilmente diferentes compiladores de C y C++, para microcomputadores, minicomputadores,
estaciones de trabajo y computadores grandes (mainframes).
Portabilidad: los programas pueden moverse facilmente entre diferentes tipos de computadores; por ejemplo, un programa en C hecho en un microcomputador debe poder pasar sin problemas a una
estacion de trabajo.
Eficiencia.
1
1. INTRODUCCION
nuevo este libro no es, y no podra serlo, exhaustivo. Los metodos tratados presentan un equilibrio entre eficiencia, facilidad de presentaci
on
y popularidad. Hay muy buenos libros de referencia para metodos
numericos y an
alisis numerico. Algunos de ellos son [GoV96], [IsK66],
[YoG72], [DaB74], [BuF85], [LaT87], [StB93], [Atk78].
Tambien hay libros que al mismo tiempo tratan los dos temas: C (o
C++) y metodos numericos; por ejemplo: [Pre93], [Kem87], [OrG98],
[Flo95], [ReD90].
Los ejemplos de programas de este libro han sido probados en varios compiladores. El autor espera que funcionen en la mayora. Para
algunos ejemplos, aparecen los resultados producidos por el programa.
Estos resultados pueden variar ligeramente de un compilador a otro; por
ejemplo, en el n
umero de cifras decimales desplegadas en pantalla.
En algunos ejemplos no estan todos los detalles ni instrucciones necesarias, aparecen u
nicamente las instrucciones m
as relevantes para ilustrar el tema en estudio. Usualmente aparecer
an puntos suspensivos indicando que hacen falta algunas instrucciones; por ejemplo, las instrucciones donde se leen, se definen o se les asigna un valor a las variables.
1. INTRODUCCION
Generalidades
Hacer un programa en C (o en C++) significa escribir o crear un archivo
texto o archivo ASCII (American Standard Code for Information Interchange) que este de acuerdo con la sintaxis de C y que haga lo que el
programador desea. Este archivo se denomina el programa fuente o el
c
odigo. Generalmente, tiene la extensi
on .c o .cpp, es decir, si el programa se va a llamar progr01, entonces el programa fuente se llamara
progr01.c o progr01.cpp.
El programa fuente se puede escribir con cualquier editor de texto;
por ejemplo, Edit de DOS, Notepad y emacs en Windows, vi, pico, emacs
en Unix y Linux, y muchos otros. Tambien puede ser escrito por medio
del editor del compilador, cuando lo tiene.
Algunos compiladores vienen con ambiente integrado de desarrollo,
IDE (Integrated Development Environment), es decir, un ambiente en
el que estan disponibles, al mismo tiempo, un editor, el compilador, el
ejecutor del programa, un depurador (debugger ) y otras herramientas.
Por ejemplo, Visual C++ (para Windows), Turbo C (para DOS), DevC++ (para Windows, software libre). En otros casos el compilador no
tiene IDE. Por ejemplo, el compilador bcc32 (software libre de la casa
Borland) o el compilador g++ (gcc) para Linux.
El programa fuente debe estar conforme a la sintaxis de C y debe
dar las
ordenes adecuadas para hacer lo que el programador desea. Una
vez construida una primera versi
on del programa fuente, es necesario
utilizar el compilador. El compilador revisa si el programa fuente esta
de acuerdo con las normas de C. Si hay errores, el compilador produce
5
2. GENERALIDADES
2.1
El primer programa
La primera lnea, #include ... , indica que se va a utilizar una biblioteca cuyo archivo de cabecera es stdio.h, es decir, la biblioteca standard
input output. En un archivo de cabecera hay informaci
on y declaraciones
necesarias para el uso correcto de las funciones de la biblioteca correspondiente.
En un programa en C hay una o varias funciones, pero siempre tiene
que estar la funcion main, es decir, la funcion principal. La palabra int,
que precede a main, indica que la funcion main devuelve un valor entero.
Justamente la funcion main, en este ejemplo, devuelve 0 por medio de
la instruccion return 0. Para la funcion main se usa la siguiente convencion: devuelve 0 si no hay errores; devuelve 1 u otro valor no nulo si
hubo errores.
Dentro de los parentesis despues de main no hay nada; esto quiere
decir que la funcion main no tiene par
ametros o argumentos.
Poco a poco el lector entendera el significado del valor devuelto por
una funcion, de los par
ametros o argumentos de una funcion. Por el
momento puede suponer que siempre se debe escribir int main().
El corchete izquierdo, {, indica el comienzo de la funcion main y el
corchete derecho, }, indica el final.
La funcion printf es propia de C y sirve para escribir o desplegar
en la pantalla alg
un resultado. Esta funcion esta definida en el archivo
de cabecera stdio.h . En este ejemplo, el programa ordena escribir en
la pantalla la cadena de caracteres Este es mi primer programa. La
cadena empieza con " y termina con ". Dentro de la cadena tambien
esta \n que sirve para crear una nueva lnea dentro de lo que aparece
en la pantalla. Observe lo que pasa, durante la ejecuci
on del programa,
al cambiar la lnea por una de las siguientes:
printf(" Este es
printf(" Este es
printf(" Este es
printf("\n\n\n\n
mi primer programa.");
mi primer programa.\n\n\n");
mi primer \n\n programa.\n");
Este es mi \n primer programa.\n");
2. GENERALIDADES
int main()
{
cout<<" Este es mi primer programa en C++."<<endl;
return 0;
}
Aqu se utiliza el archivo de cabecera iostream.h, en el cual esta la
funcion cout. Observe la diferencia de sintaxis entre printf y cout.
La orden para cambiar de lnea esta dada por endl. Tambien se puede
meter, dentro de la cadena, \n y se obtienen los mismos resultados.
cout<<" Este es mi primer programa.\n";
Para obtener cambios de lnea adicionales se puede utilizar varias veces
endl, por ejemplo:
cout<<"Este es mi primer programa."<<endl<<endl;
cout<<"Este es mi primer"<<endl<<"programa."<<endl;
cout<<endl<<"Este es mi"<<endl<<"primer programa.";
Algunos compiladores muy recientes no aceptan de buen gusto el anterior programa en C++; por ejemplo, el g++ (gcc) 3.2 de Linux. Lo
consideran anticuado (deprecated or antiquated ). El programa se debera
escribir as:
#include <iostream>
using namespace std;
int main()
{
cout<<" Este es mi primer programa en C++."<<endl;
return 0;
}
Observe que aparece simplemente iostream y no iostream.h. La segunda lnea, using ..., sirve para que no sea necesario escribir
std::cout<<...
sino simplemente
cout<<...
Cuando hay varios espacios seguidos, es lo mismo que si hubiera uno
solo. Las lneas en blanco no se tienen en cuenta, simplemente sirven
8
para la presentaci
on del programa fuente. El programa del ejemplo
tambien se hubiera podido escribir como sigue, pero su lectura no es
facil.
#include <stdio.h>
int
main(){printf
(
" Este es mi primer programa.\n")
;
return
0;}
2.2
En esta secci
on hay algunas pautas generales para poder efectuar el proceso de edici
on, compilaci
on y ejecuci
on de un programa. Estas pautas
pueden variar de computador en computador o de configuraci
on en configuraci
on; adem
as, sirven para los casos m
as sencillos. Poco a poco,
el programador debera aprender a utilizar otras opciones y formas de
compilaci
on.
Suponga que el programa fuente se llama prog01.cpp. Tambien se
supone que el compilador que se va a usar ha sido instalado correctamente.
Para facilitar la escritura se utilizara la siguiente notaci
on:
orden
indica que se activa el bot
on (o parte de un men
u) llamado orden. Esto
se logra, generalmente, picando con el mouse dicho bot
on. En algunos
casos se logra el mismo objetivo mediante el desplazamiento con las
flechas y se finaliza oprimiendo la tecla Enter. Por ejemplo, File indica
que se activa el bot
on File.
La notaci
on Alt-f indica que se mantiene oprimida la tecla Alt
y despues se pulsa ligeramente la tecla f. Finalmente se suelta la tecla
Alt. De manera an
aloga se utiliza la misma notaci
on para la tecla Ctrl o
para la tecla que aqu se denotara por May (may
usculas); por ejemplo,
Ctrl-F5 o May-F2.
9
2. GENERALIDADES
2.2.1
g++
2.2.2
bcc32
ventana de sistema.
La edici
on del archivo se hace con cualquier editor de texto de Windows (bloc de notas, Wordpad, Emacs para Windows...) o de DOS
(edit...).
Una vez editado y guardado el archivo, se compila mediante
bcc32 prog01.cpp
La orden anterior produce, si no hay errores, el archivo prog01.exe.
Este
es un archivo ejecutable. Generalmente no es necesario especificar
la extensi
on .cpp, el compilador la presupone, o sea, bastara con
bcc32 prog01
Para correr el programa basta con digitar
prog01
Como se observa, no es necesario escribir la extensi
on .exe.
2.2.3
Turbo C++
Este compilador para DOS viene con IDE (ambiente integrado). Sin
embargo tambien se puede utilizar u
nicamente el compilador de la misma
forma como se usa el compilador bcc32. Basta con cambiar bcc32 por
tcc.
Para utilizar el IDE, es necesario, como primer paso, disponer de
una ventana de DOS. Desde all, el compilador y su ambiente se activan
por medio de la orden
tc
Ya dentro de Turbo C++, el ambiente muestra directamente la ventana
del editor. Es necesario escribir el programa o hacer las modificaciones
deseadas.
Se tiene acceso a la barra de men
u, en la parte superior de la ventana, por medio del mouse o por medio de la tecla Alt acompa
nada
simult
aneamente de la primera letra de la orden o submen
u. Por ejemplo Alt-F para el submen
u File.
Para grabar el archivo o los cambios:
File Save
11
2. GENERALIDADES
Para algunas de estas secuencias de operaciones hay una tecla que reemplaza la secuencia. La secuencia File Save se puede reemplazar por F2.
Para compilar:
Compile Compile
Alt-F9
Ctrl-F9
2.2.4
Alt-x
Visual C++
En Visual C++, los programas son proyectos. Un proyecto puede abarcar varios archivos, algunos .cpp y algunos archivos de cabecera .h.
Supongamos que el proyecto se llama prog50, y que dentro del proyecto
prog50, hay u
nicamente un archivo .cpp, el archivo parte_a.cpp.
La primera vez es necesario crear el proyecto y agregarle archivos.
File New Projects Win32 Console Application Project Name
prog50 Create a new workspace OK
OK
My Projects\prog50\
Crtl-F7
F7
hace la edici
on de enlaces (link) y, si no hay errores, crea el ejecutable
prog50.exe en la carpeta Debug . Si es necesario, esta secuencia tambien
guarda y compila.
La secuencia
Build Execute
Ctrl-F5
2. GENERALIDADES
2.2.5
Dev-C++
Este compilador para Windows es software libre, viene con IDE. Su direcci
on es www.bloodshed.net. Despues de instalado, para un programa
nuevo, se puede utilizar inicialmente la siguiente secuencia:
File New Source file
Entonces Dev-C++ abre un archivo predefinido que el programador debe
completar.
#include <iostream.h>
#include <stdlib.h>
int main()
{
system("PAUSE");
return 0;
}
Hay dos lneas nuevas: se incluye otro archivo de cabecera, el archivo
stdlib.h (standard library), precisamente para poder usar la orden del
sistema operativo system("PAUSE"). Esto sirve simplemente para que,
cuando el programa haya hecho todo lo que debe hacer, no cierre inmediatamente la pantalla de resultados, sino que haga una pausa.
Una vez que el programador ha escrito su programa, la secuencia
File Save unit
Ctrl-s
permite guardar el archivo. Si es la primera vez, es necesario dar el nombre, para nuestro ejemplo, prog01 . Las veces posteriores, la secuencia
anterior simplemente graba los cambios realizados en el archivo.
La secuencia
Execute Compile and Run
Ctrl-F10
o
14
Ctrl-o
2.3. COMENTARIOS
2.3
Comentarios
2. GENERALIDADES
// Segunda linea de
// Tercera linea de
// ...
printf(" HOLA.\n");
printf(" HOLA.\n");
un comentario en C++
un comentario en C++
// escribe HOLA
/* escribe HOLA */
2.4
Identificadores
auto
class
do
float
inline
break
const
double
for
int
16
case
continue
else
friend
long
catch
default
enum
goto
new
2.4. IDENTIFICADORES
operator
return
struct
try
void
private
short
switch
typedef
volatile
protected
signed
template
union
while
public
sizeof
this
unsigned
register
static
throw
virtual
De los siguientes identificadores posibles, los cuatro primeros son correctos, los cinco u
ltimos son inadecuados. El primer identificador es
diferente del segundo.
a1
A1
peso_especifico_del_mercurio
b1j
peso especifico
peso-especifico
1a
pesoesp
float
Adem
as, para los identificadores, es preferible no utilizar los nombres de
las funciones usuales de C o de C++.
En los siguientes dos ejemplos, para los identificadores se utilizan
nombres de funciones de entrada y salida. En el primer ejemplo no hay
conflicto, pero de todas maneras es aconsejable no usar printf para un
identificador.
double printf = 4.5;
cout<<printf<<endl;
En el segundo ejemplo hay conflicto entre la funcion printf, usada en
la segunda lnea, y el identificador printf.
double printf = 4.5;
printf(" %lf\n", printf);
Los identificadores deben ser explicativos con respecto a la variable que
representan. El tercero, peso especifico del mercurio, es un buen
17
2. GENERALIDADES
2.5
Tipos de datos
2. GENERALIDADES
Tama
no
(bytes)
2
2
4
8
Rango
32768 a 32767
3.4E-38 a 3.4E38
1.7E-308 a 1.7E308
3.45E42 :=
0.345E-38 :=
345
1042 ,
100
345
1038 .
1000
En la notaci
on cientfica de C tambien se puede utilizar la e min
uscula
en lugar de la may
uscula; por ejemplo, 3.45e42.
Para los tipos float y double, en la tabla esta escrito u
nicamente
el rango positivo. Es necesario sobrentender el cero y el rango negativo;
por ejemplo, el tipo float tambien puede ser cero o variar entre 3.4E38
y 3.4E-38 .
Mediante los modificadores
unsigned
long
20
2.6. OPERADOR DE ASIGNACION
Tama
no
(bytes)
2
4
10
Rango
0 a 65535
2147483648 a 2147483647
3.4E-4932 a 3.4E4932
2.6
Operador de asignaci
on
Es el operador m
as utilizado. Mediante su uso se le asigna a una variable
un nuevo valor. La forma general es:
variable = expresi
on;
Lo anterior indica que la variable, que siempre esta a la izquierda del
signo igual, toma el valor dado por la expresi
on de la derecha. La asignaci
on no se debe confundir con el significado de una igualdad en una
expresi
on matem
atica. Algunos ejemplos permiten aclarar el uso y significado de la asignaci
on.
int a;
double x, y;
char c;
a
y
x
a
c
=
=
=
=
=
100;
9.0/4.0;
5.0 + y;
a+3;
A;
21
2. GENERALIDADES
Antes de la instruccion a = 100 la variable a tena un valor determinado, o tal vez ning
un valor especfico. De todas maneras, despues de
la instruccion a = 100 la variable entera a vale cien. Despues de la
instruccion y = 9.0/4.0 la variable y vale 2.25 . Como la variable
y corresponde a un n
umero real, es preferible que la expresi
on de la
derecha sea hecha explcitamente entre n
umeros reales; por esto en este
caso es preferible escribir 9.0/4.0 y no simplemente 9/4 . Como se vera
m
as adelante, el valor de 9/4 es el entero 2. Despues de la instruccion
x = 5.0 + y , la variable x vale 7.25 .
La instruccion a = a + 3 sera un error desde el punto de vista
matem
atico, trabajando en el conjunto de los n
umeros reales. En cambio
en C tiene un sentido preciso, toma el valor que tiene a, le adiciona 3
y el resultado es el nuevo valor de a. O sea, antes de la instruccion, a
vale 100 . Despues de la instruccion, a vale 103 .
En el momento en que se especifica el tipo de una variable, se puede
hacer una asignaci
on inicial. Por ejemplo, la instruccion
int i = 3, j = 5;
dice que las variables i, j son enteras y adem
as a i se le asigna el valor
3 y a j el valor 5 .
2.7
Operadores aritm
eticos
++
--
2.7. OPERADORES ARITMETICOS
cout<<k<<endl;
x = 10.0;
y = 3.0;
cout<<x/y<<endl;
cout<<x*y<<endl;
cout<<i/j<<endl;
produce la escritura en pantalla de los resultados
31
3.33333
30
6
Es importante observar que al efectuar la divisi
on entre dos n
umeros
enteros i, j (j 6= 0), C da como resultado la parte entera de i/j cuando
i/j es positivo y menos la parte entera de i/j en caso contrario. En
resumen, el resultado es
signo(i/j)|i/j| .
Por ejemplo,
int i, j;
i = 27;
j = -4;
cout<<i/j<<endl;
produce la escritura en pantalla de -6 .
El operador - adem
as de representar la sustraccion, operacion
binaria, sirve para indicar el cambio de signo. La instruccion
x = -y;
asigna a la variable x el inverso aditivo del valor de y .
El operador % se aplica u
nicamente a enteros e indica el residuo
entero de la divisi
on. Por ejemplo,
int i, j, k;
23
2. GENERALIDADES
i = 25;
j = 7;
k = i%j;
cout<<k<<endl;
producira como resultado la escritura en pantalla del valor 4 .
El operador ++ es un operador unario, o sea, tiene un solo
argumento. Se aplica a variables enteras. Su efecto es aumentar en una
unidad. Hay dos formas de usarlo, antes o despues de la variable. El
resultado final, para la variable a la que se le aplica, es el mismo, pero
los valores intermedios pueden ser diferentes. En el ejemplo
int i = 4, j = 4, k;
k = i++;
cout<<i<<"
k = ++j;
cout<<j<<"
"<<k<<endl;
"<<k<<endl;
4
5
es equivalente a
k = i;
i++;
k = ++j;
es equivalente a
j++;
k = j;
tambien es equivalente a
++j;
k = j;
24
2.8. PRIORIDAD DE LOS OPERADORES ARITMETICOS
El operador -de ++ .
2.8
2. GENERALIDADES
posincremento
posdecremento
preincremento
predecremento
cambio de signo
multiplicaci
on
divisi
on
resto de la div. entera
adicion
sustraccion
asignaci
on
Asociatividad
izq. a derecha
izq. a derecha
derecha a izq.
derecha a izq.
derecha a izq.
izq. a derecha
izq. a derecha
izq. a derecha
izq. a derecha
izq. a derecha
derecha a izq.
Precedencia
mayor
menor
// x = (a/b)/c;
// x = ( (a*b) + (c/d) ) - (c*b);
// x = a/(-c);
De todas maneras, en caso de duda o para facilitar la lectura, se recomienda el uso adecuado de parentesis o de espacios.
double a = 1.2, b = 3.1, c = -2.5, d = 5.1, x;
x = (a/b)/c;
x = a*b + c/d - c*b;
x = a/(-c);
26
2.9
Abreviaciones usuales
2.10
Funciones matem
aticas
2. GENERALIDADES
"<<raiz2<<endl;
}
El programa anterior producira el siguiente resultado.
Las raices son: 0.709256 -1.15211
Al hacer un programa, la primera preocupacion es que funcione. La
segunda es que sea eficiente. En el programa anterior hay varios calculos
repetidos: b*b-4.0*a*c y 2.0*a . Hacer el programa anterior m
as
eficiente tendr
a una ganancia imperceptible, milesimas de segundo o
menos. Pero cuando se hace m
as eficiente un proceso que se realiza
millones de veces, la mejora puede ser notable.
// Calculo de las raices de una ecuacion cuadratica,
// cuando son reales.
#include <iostream.h>
#include <math.h>
28
2.10.
FUNCIONES MATEMATICAS
int main()
{
double a = 7.0, b = 3.1, c = -5.72;
double raiz1, raiz2, d, a2;
a2 = 2.0*a;
d = sqrt(b*b-4.0*a*c);
raiz1 = (-b + d )/a2;
raiz2 = (-b - d )/a2;
cout<<"\n\n "<<a<<" x*x + "<<b<<" x + "<<c<<endl;
cout<<"Las raices son: "<<raiz1<<" "<<raiz2<<endl;
return 0;
}
En la siguiente tabla estan las principales funciones matem
aticas de C.
Para todas, el resultado es tipo double. Todas, salvo pow , tienen un solo
argumento. pow(x,y) eval
ua xy , ambos argumentos son tipo double y
el resultado tambien lo es.
acos
asin
atan
ceil
cos
cosh
exp
fabs
floor
log
log10
pow
sin
sinh
sqrt
tan
tanh
arco coseno
arco seno
arco tangente
parte entera superior
coseno
coseno hiperb
olico
exponencial: ex
valor absoluto
parte entera inferior
logaritmo neperiano
logaritmo en base 10
xy
seno
seno hiperb
olico
raz cuadrada
tangente
tangente hiperb
olica
29
Argumentos
double
double
double
double
double
double
double
double
double
double
double
double, double
double
double
double
double
double
Resultado
double
double
double
double
double
double
double
double
double
double
double
double
double
double
double
double
double
2. GENERALIDADES
2.11
printf(" a = ");
scanf("%lf", &a);
printf(" b = ");
scanf("%lf", &b);
printf(" c = ");
30
2.11.
scanf("%lf", &c);
printf("\n %lf x*x + %lf x + %lf = 0\n\n", a, b, c);
a2 = 2.0*a;
d = sqrt(b*b-4.0*a*c);
raiz1 = (-b + d )/a2;
raiz2 = (-b - d )/a2;
printf(" Raices: %12.4lf
return 0;
}
Despues de que el programa escribe en la pantalla a = , sigue la orden
scanf . Entonces el usuario, por medio del teclado, debera digitar el
valor de a . Para finalizar esta orden el usuario debera oprimir la tecla
Return o Enter.
All, lo que esta entre comillas es la cadena de formato. Para este
caso, %lf es el formato para n
umeros tipo double. La siguiente lista
muestra otros tipos de formato. Algunos corresponden a conceptos
todava no presentados en este libro. Consulte la documentaci
on del
compilador que usa, sobre los formatos para n
umeros long int y long
double.
%d
%f
%lf
%u
%e
%i
%c
%s
%p
int
float
double
unsigned int
double, float en notaci
on cientfica
int
char
cadena de caracteres
puntero o apuntador
2. GENERALIDADES
x*x +
x +
= 0\n\n"
2.11.
c : ");
cout<<" a = ";
33
2. GENERALIDADES
cin>>a;
cout<<" b = ";
cin>>b;
cout<<" c = ";
cin>>c;
cout<<"\n "<<a<<" x*x + "<<b<<" x + "<<c<<" = 0.\n\n";
a2 = 2.0*a;
d = sqrt(b*b-4.0*a*c);
raiz1 = (-b + d )/a2;
raiz2 = (-b - d )/a2;
cout<<" Las raices son: "<<raiz1<<"
return 0;
"<<raiz2<<endl;
}
En la entrada de datos mediante cin no se requiere colocar el signo &
antes de la variable. Tampoco hay que especificar el formato, no importa
que sea entero, punto flotante o doble precisi
on.
La utilizaci
on de modificadores de formato como longitud de campo
y n
umero de cifras decimales con las ordenes cin y cout, esta fuera del
alcance de este libro.
Tambien es posible hacer una sola orden para entrar varios datos al
tiempo. La entrada de los tres coeficientes se podra hacer mediante:
cout<<" Entre los coeficientes
cin>>a>>b>>c;
c : ";
2.12.
2.12
y float
double
e int
float
e int
short int
e int
double,
double,
float,
int,
35
2. GENERALIDADES
long double,
long double.
En el ejemplo
int i = 8, j = 3;
double x = 1.5, u, z;
u = i/j*x;
z = i*x/j;
cout<<u<<endl;
cout<<z<<endl;
aparentemente u y z tienen el mismo valor, puesto que, seg
un el orden en
que se efect
uan las operaciones, en ambos casos se tiene (i x)/j. Pero
en realidad u vale 3.0 y z vale 4.0. En cada expresi
on hay dos operaciones
de igual prioridad, entonces el orden es de izquierda a derecha. Para u se
hace primero la divisi
on entera, con resultado 2, y enseguida el producto
doble precisi
on, y da 3.0. Para z se hace primero la multiplicaci
on doble
precisi
on, con resultado 12.0, y enseguida la divisi
on doble precisi
on, y
da 4.0.
2.13
Moldes
Algunas veces es necesario utilizar temporalmente el valor de una variable en otro tipo diferente de aquel con que fue definida. Supongamos
que la variable i se va a utilizar muchas veces como entera y por tanto
ha sido definida como entera, pero en alg
un momento se requiere usar
su valor como doble precisi
on. Esto se hace en C, anteponiendo el molde
(double). Por ejemplo:
int i, j;
double x, y;
i
j
y
x
=
=
=
=
3;
4;
(double)i;
y*y/(double)j;
36
2.13.
MOLDES
Ejercicios
Para cada uno de los enunciados siguientes, defina cu
ales son los datos
necesarios. Haga un programa que lea los datos, realice los calculos y
muestre los resultados.
2.1 Resuelva un sistema de dos ecuaciones lineales con dos incognitas.
Suponga que tiene una u
nica solucion.
2.2 Resuelva un sistema de tres ecuaciones lineales con tres incognitas.
Suponga que tiene una u
nica solucion.
2.3 Resuelva una ecuaci
on polin
omica (o polinomial) de tercer grado
por medio de la formula de Tartaglia y Cardano. Suponga que se
tiene el caso m
as sencillo.
37
2. GENERALIDADES
2.13.
MOLDES
39
2. GENERALIDADES
40
Estructuras de control
En los ejemplos vistos hasta ahora, los programas tienen una estructura lineal, es decir, primero se efect
ua la primera orden o sentencia,
enseguida la segunda, despues la tercera y as sucesivamente hasta la
u
ltima. Por el contrario, la mayora de los programas, dependiendo del
cumplimiento o no de alguna condici
on, toman decisiones diferentes.
Tambien es muy usual repetir una o varias instrucciones mientras sea
cierta una condici
on. Estas bifurcaciones y repeticiones se logran mediante las sentencias o estructuras de control.
3.1
if
3. ESTRUCTURAS DE CONTROL
condici
on, se realiza una de las dos secuencias siguientes:
sentencia 1;
sentencia a;
sentencia 2;
sentencia 1;
sentencia b;
sentencia 2;
c;
%lf , b =
c = a;
%lf\n", a, b);
%lf\n", c);
En este ejemplo no estan todas las instrucciones necesarias para el funcionamiento correcto; aparecen u
nicamente las instrucciones m
as relevantes para ilustrar el tema en estudio. Los puntos suspensivos indican que hacen falta algunas instrucciones, por ejemplo, las instrucciones
donde se leen, se definen o se les asigna un valor a las variables a y b .
Mientras no se indique lo contrario, se usar
a la anterior convencion a lo
largo del libro.
En la estructura if no es necesaria la parte else. Se puede tener
una estructura de la siguiente forma.
sentencia 1;
if( condicion ) sentencia a;
sentencia 2;
En este caso, si la condici
on se cumple, se realiza sentencia a, y si no se
cumple, el programa no hace nada y salta a la siguiente sentencia. As,
las dos posibles secuencias de realizacion son:
sentencia 1;
sentencia a;
sentencia 2;
sentencia 1;
sentencia 2;
3.1. if
...
cout<<" a = "<<a<<" , b =
c = a;
if( b > a ) c = b;
cout<<" c = "<<c<<endl;
"<<b<<endl;
sentencia 1;
sentencia b1;
sentencia b2;
..
.
sentencia 2;
sentencia 2;
43
3. ESTRUCTURAS DE CONTROL
c : ");
44
3.2. OPERADORES RELACIONALES Y LOGICOS
3.2
Operadores relacionales y l
ogicos
menor
mayor
menor o igual
mayor o igual
igual
diferente
Los operadores l
ogicos son:
&&
||
!
y
o
no
3. ESTRUCTURAS DE CONTROL
La primera expresi
on es, tal vez, m
as facil de entender, pues concuerda
con nuestra manera l
ogica de razonar. Es m
as claro decir si i es diferente de cero... que decir si i....
Tambien se puede escribir como condici
on del if (y de otras estructuras de control) expresiones menos simples.
if( a*c-b*d )...
M
as a
un, esa expresi
on puede ser de tipo doble precisi
on. Esto es
lcito aunque no muy usual. La condici
on sera falsa u
nicamente cuando
a*c-b*d fuera exactamente 0.0. Para otros valores, a
un muy cercanos a
cero, como 1.0E-20, la condici
on es verdadera. Lo anterior es un poco
inexacto, en realidad depende del compilador, del computador y del tipo
de la expresi
on. Para un valor doble precisi
on, en algunos compiladores,
los valores positivos menores a 2.4E-323 se consideran nulos.
Como las comparaciones dan como resultado un valor entero 0 o
1, se pueden hacer asignaciones con este valor. Esto quita un poco de
claridad, pero es completamente lcito. Por ejemplo, se puede escribir
n = x >= 0.0;
Si x es no negativo, entonces n toma el valor 1. Si x es negativo,
entonces n toma el valor 0. El programa anterior, prog04a, haca el
calculo de las races reales o complejas de una ecuaci
on cuadratica, pero
no consideraba algunos casos muy raros, pero posibles. Por ejemplo, a
puede ser cero, entonces la ecuaci
on no solamente no es cuadratica, sino
que el programa presenta una divisi
on por cero (situaci
on que un programador siempre debe evitar). El siguiente programa usa estructuras
if anidadas y considera todos los posibles casos.
// Raices de una ecuacion cuadratica.
// Considera los casos extremos: a=0, a=b=0...
//#include <iostream.h>
#include <math.h>
#include <stdio.h>
int main()
{
46
3.2. OPERADORES RELACIONALES Y LOGICOS
c : ");
47
3. ESTRUCTURAS DE CONTROL
3.3
for
double suma;
int i;
suma = 0.0;
for( i=1; i <= 15; i++){
suma += 1.0/i;
printf("%5d %12.6lf\n", i, suma);
}
3.3. for
condici
on de continuaci
on,
modificaci
on.
3. ESTRUCTURAS DE CONTROL
3.4. while
3.4
while
X
x2 x3 x4
xn
x
e =1+x+
+
+
+ ... =
2
6
24
n!
n=0
51
3. ESTRUCTURAS DE CONTROL
xk
,
k!
sn =
n
X
ak .
k=0
3.4. while
an = pow(x,n)/nFact;
sn += an;
}
printf(" exp(x) = %lf\n", sn);
return 0;
}
Se puede lograr m
as eficiencia, se evita el uso de pow y el calculo explcito
de n!, si se tiene en cuenta que
an = an1
x
.
n
eps = 1.0e-8;
sn = 1.0 + x;
n = 1;
an = x;
while( fabs(an)/( 1.0 + fabs(sn) ) > eps ){
n++;
an *= x/n;
sn += an;
}
Para la funcion coseno, su serie de Taylor, alrededor de cero, es:
cos x = 1
X
x2n
x6
x2 x4
(1)n
+
+ ... =
2
24 720
(2n)!
n=0
x2
.
2n(2n 1)
La porci
on de programa siguiente calcula una aproximacion del valor de
cos x.
double x, sn, an, eps, xx;
int n2; // 2*n
printf("\n Calculo aproximado de cos(x).\n\n x = ");
scanf("%lf", &x);
53
3. ESTRUCTURAS DE CONTROL
eps = 1.0e-8;
xx = x*x;
an = -xx/2.0;
sn = 1.0 + an;
n2 = 2;
while( fabs(an)/( 1.0 + fabs(sn) ) > eps ){
n2 += 2;
an *= -xx/n2/(n2-1.0);
sn += an;
}
printf(" cos(x) = %lf\n", sn);
3.5
do while
3.5. do while
3. ESTRUCTURAS DE CONTROL
printf("\n p = ");
scanf("%d", &p);
printf(" q = ");
scanf("%d", &q);
printf("\n\n p = %d ,
q = %d\n", p, q);
3.6. switch
3.6
switch
break;
case valor2 :
sentencia 2 1
break;
default :
sentencia d 1
}
sentencia b;
Si la variable de control tiene el primer valor, se efect
uan las sentencias
del primer grupo y despues el programa pasa a realizar sentencia b. Si
la variable de control tiene el segundo valor, se efect
uan las sentencias
del segundo grupo y despues el programa pasa a realizar sentencia b.
Si la variable de control no tiene ninguno de los valores previstos, el
programa realiza las sentencias de la parte default y en seguida efect
ua
sentencia b. La parte default no es indispensable desde el punto de
vista de la sintaxis, pero en la practica puede ser u
til o a veces necesaria.
Cuando para dos valores diferentes de la variable de control se tiene
que hacer el mismo grupo de sentencias, en lugar de hacer case valor i:
grupo de sentencias y case valor j: grupo de sentencias, se coloca simplemente case valor i: case valor j: grupo de sentencias.
57
3. ESTRUCTURAS DE CONTROL
si 40 nota 50,
si 30 nota 39,
Reprueba.
si 0 nota 19,
La siguiente porci
on de programa hace la implementaci
on, basada
en la cifra de las decenas.
int nota, dec;
printf(" nota = ");
scanf("%d", ¬a);
if( 0 <= nota && nota <= 50 ){
dec = nota/10;
switch( dec ){
case 5: case 4:
printf(" %2d Aprueba. Muy bien.\n", nota);
break;
case 3:
printf(" %2d Aprueba.\n", nota);
break;
case 2:
printf(" %2d Puede habilitar.\n", nota);
break;
default:
printf(" %2d Reprueba.\n", nota);
break;
}
}
else printf(" %d Nota inadecuada.\n", nota);
3.7
break
Adem
as del uso en la estructura switch, la instruccion break se puede
utilizar en las estructuras for, while, do while. En estos bucles el
control se hace siempre al comienzo o al final del cuerpo del bucle. En
58
3.7. break
if( condicion 2 ){
sentencia c 1;
sentencia c 2;
break;
}
}
sentencia b;
Si en una pasada del programa por el cuerpo del bucle, se cumple
la condici
on del if, condicion 2, entonces el programa realiza las instrucciones sentencia c 1, sentencia c 2, . . . , y salta a la instruccion
sentencia b.
La siguiente porci
on de programa calcula la suma de los enteros
entre n1 inclusive y n2 inclusive, menores que el mnimo m
ultiplo de 10
en ese mismo intervalo. Si en el conjunto {n1, n1+1..., n2 } no hay
m
ultiplos de 10, calcula la suma de todos ellos. Tambien calcula la suma
de los cuadrados de esos enteros.
int n1, n2, i, div, res;
double sx, sxx;
div = 10;
printf(" n1 n2 : ");
scanf("%d%d", &n1, &n2);
sx = 0.0;
sxx = 0.0;
for( i = n1; i <= n2; i++){
res = i%div;
59
3. ESTRUCTURAS DE CONTROL
3.8
continue
if( condicion 2 ){
sentencia c 1;
sentencia c 2;
continue;
}
sentencia 3;
sentencia 4;
}
sentencia b;
Si en una pasada del programa por el cuerpo del bucle, se cumple la
condici
on del if, condicion 2, entonces el programa realiza las instrucciones sentencia c 1, sentencia c 2, . . . , y vuelve a empezar una nueva
iteraci
on sin ejecutar las sentencias restantes del bloque for (sentencia 3,
60
sentencia 4... ). Como en el esquema anterior se trata de un for, entonces realiza la modificaci
on indicada en MODIF.
La siguiente porci
on de programa calcula la suma de los enteros no
m
ultiplos de 10, entre n1 inclusive y n2 inclusive. Tambien calcula la
suma de los cuadrados de esos enteros.
int n1, n2, i, div, res;
double sx, sxx;
div = 10;
printf(" n1 n2 : ");
scanf("%d%d", &n1, &n2);
sx = 0.0;
sxx = 0.0;
for( i = n1; i <= n2; i++){
res = i%div;
if( !res ) continue; // if( res == 0 ) continue;
sx += i;
sxx += i*i;
printf("%5d\n", i);
}
printf(" suma x = %lf , suma x*x = %lf\n", sx, sxx);
En el ejemplo anterior, cuando i es un m
ultiplo de 10, el programa pasa
a efectuar una nueva iteraci
on; entonces, antes de calcular res, como
esta indicado en este for, incrementa en una unidad el valor de i.
3.9
goto y exit
La instruccion goto no debera usarse en los programas llamados bien estructurados, pues permite salidas m
ultiples de un bucle y adem
as puede
transferir la secuencia del programa a instrucciones diferentes de la siguiente al bucle. Sin embargo, usado con moderacion y en casos de real
necesidad, puede ser u
til, por ejemplo, para salir de varios bucles anidados mediante una sola instruccion.
El goto debe estar seguido del nombre de una etiqueta. Una etiqueta
es simplemente un identificador seguido de dos puntos. La etiqueta debe
61
3. ESTRUCTURAS DE CONTROL
es primo
//#include <iostream.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
int main()
{
int n, i, nPrimo, res;
printf("\n Averigua si el entero
printf("\n n = ");
scanf("%d", &n);
printf("\n\n n = %d", n);
if( n <= 1 ){
62
n > 1
es primo.\n");
Ejercicios
Para cada uno de los enunciados siguientes, defina cu
ales son los
datos necesarios. Haga un programa que lea los datos, verifique que
no hay inconsistencias (por ejemplo, distancias negativas o nulas; dos
vertices de un tri
angulo iguales; recta que pasa por un punto paralela
a d = 0...), estudie todas las posibilidades relajando algunas suposiciones (por ejemplo: solucion u
nica, sin solucion, n
umero infinito de
soluciones...), realice los calculos y muestre los resultados.
3.1 Considere los ejercicios del captulo anterior.
3.2 Dadas las longitudes de los lados de un tri
angulo, averig
ue si este
es acutangulo, rectangulo u obtus
angulo.
3.3 Escriba la expresi
on binaria, en orden inverso, de un entero no
negativo.
3.4 Escriba la expresi
on en base p (p entero, 2 p 9), en orden
inverso, de un entero no negativo.
63
3. ESTRUCTURAS DE CONTROL
X
1
k!
k=0
3.10 Calcule por medio de la serie de Taylor truncada un valor aproximado de seno(x). Muestre el n
umero de terminos de la serie
necesarios para que el valor absoluto de la diferencia entre el valor
obtenido y el valor producido por la funcion sin sea menor que
1.0E-12.
3.11 Convierta coordenadas cartesianas en polares.
3.12 Convierta coordenadas cartesianas en esfericas.
3.13 Convierta coordenadas polares en cartesianas.
3.14 Convierta coordenadas esfericas en cartesianas.
3.15 Dados tres n
umeros, escrbalos en orden creciente.
3.16 Dados tres n
umeros, escrbalos en orden decreciente.
3.17 Dados cuatro n
umeros, escrbalos en orden creciente.
3.18 Dados cuatro n
umeros, escrbalos en orden decreciente.
3.19 Calcule el mnimo com
un m
ultiplo de dos enteros positivos.
3.20 Simplifique un racional.
3.21 Haga las cuatro operaciones entre dos racionales.
3.22 Haga las cuatro operaciones entre dos complejos.
3.23 Calcule z n , donde z es un complejo y n un entero positivo.
64
1
1
1
)(1 )...(1 )
p1
p2
pk
Jn (x) = xn
m=0
m=0
(1)m x2m
,
22m+n m! (n + m)!
x 2m+n
(1)m
m! (n + m)! 2
3. ESTRUCTURAS DE CONTROL
k
2k + 1
x Pk (x)
Pk1 (x) .
k+1
k+1
66
Funciones
Como se mencion
o anteriormente, de manera muy esquem
atica, se puede
decir que un programa fuente en C es una sucesion de funciones que se
llaman (se utilizan) entre s. Siempre tiene que estar la funcion main.
4.1
Generalidades
4. FUNCIONES
4.1. GENERALIDADES
4. FUNCIONES
4.1. GENERALIDADES
4. FUNCIONES
f (3) = 22,
adem
as, f es continua en el intervalo [2, 3], luego se puede iniciar el
metodo de biseccion. Hay por lo menos una raz entre 2 y 3.
El punto medio es m = 2.5, f (2.5) = 2.531, f (a)f (m) > 0, luego el
nuevo intervalo sera [2.5, 3].
El punto medio es m = 2.75, f (2.75) = 5.202, f (a)f (m) < 0, luego el
nuevo intervalo sera [2.5, 2.75].
El punto medio es m = 2.625, f (2.625) = 0.445, f (a)f (m) < 0, luego el
nuevo intervalo sera [2.5, 2.625].
El punto medio es m = 2.562, f (2.562) = 1.239, f (a)f (m) > 0, luego
el nuevo intervalo sera [2.562, 2.625].
El punto medio es m = 2.594, f (2.594) = 0.449, f (a)f (m) > 0, luego
el nuevo intervalo sera [2.594, 2.625].
Los valores anteriores y otros m
as estan en la siguiente tabla. El
proceso se detuvo cuando el tama
no del intervalo fue menor que 0.0005 .
k
0
1
2
3
4
5
6
7
8
9
10
11
a
2.000
2.500
2.500
2.500
2.562
2.594
2.609
2.609
2.609
2.609
2.609
2.610
b
3.000
3.000
2.750
2.625
2.625
2.625
2.625
2.617
2.613
2.611
2.610
2.610
f (a)
-4.000
-2.531
-2.531
-2.531
-1.239
-0.449
-0.016
-0.016
-0.016
-0.016
-0.016
72
f (b)
22.000
22.000
5.202
0.445
0.445
0.445
0.445
0.211
0.097
0.040
0.012
m
2.500
2.750
2.625
2.562
2.594
2.609
2.617
2.613
2.611
2.610
2.610
f (m)
-2.531
5.202
0.445
-1.239
-0.449
-0.016
0.211
0.097
0.040
0.012
-0.002
4.1. GENERALIDADES
4. FUNCIONES
4.2
Funciones recurrentes
A continuaci
on aparece una versi
on recurrente para el calculo de n!.
double
{
//
//
//
factRec( int n)
devuelve 0 si n es negativo,
en los demas casos devuelve n!
Version recurrente.
double i;
if( n < 0 ){
printf(" n = %d inadecuado.\n", n);
return 0.0;
}
if( n < 2 ) return 1.0;
else return( n*factRec(n-1) );
}
75
4. FUNCIONES
4.3
Par
ametros por valor y por referencia
m = %d ,
n = %d\n", m, n);
m = %d ,
n = %d\n", m, n);
}
//=========================================================
void interc0( int i, int j)
{
int t;
printf(" FUNC1:
t = i;
i = j;
j = t;
printf(" FUNC2:
i = %d ,
j = %d\n", i, j);
i = %d ,
j = %d\n", i, j);
}
76
4.3. PARAMETROS
POR VALOR Y POR REFERENCIA
m
i
i
m
=
=
=
=
2
2
5
2
,
,
,
,
n
j
j
n
=
=
=
=
5
5
2
5
n = %d\n", m, n);
n = %d\n", m, n);
77
4. FUNCIONES
}
//=========================================================
void interc1( int *i, int *j)
{
int t;
t = *i;
*i = *j;
*j = t;
}
En C++ el paso de par
ametros por referencia es mucho m
as sencillo.
Por eso a continuaci
on hay u
nicamente explicaciones muy someras sobre
la forma de pasar par
ametros por referencia en C:
En el llamado a la funcion, el par
ametro pasado por referencia
debe ir precedido de & ; m
as adelante, cuando se vea el tema de
apuntadores, el lector entendera que eso significa que se pasa la
direccion del par
ametro.
En la definicion de la funcion, el par
ametro pasado por referencia
debe estar precedido de un asterisco. Esto indica (tema posterior)
que se trata de un apuntador.
A continuaci
on se presenta el ejemplo an
alogo, a la manera de C++.
// Funcion que intercambia dos valores.
// Version a la manera de C++.
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
void interc( int &i, int &j);
//=========================================================
int main()
{
int m, n;
78
4.3. PARAMETROS
POR VALOR Y POR REFERENCIA
m = 2;
n = 5;
printf(" MAIN1:
interc(m, n);
printf(" MAIN2:
return 0;
m = %d ,
n = %d\n", m, n);
m = %d ,
n = %d\n", m, n);
}
//=========================================================
void interc( int &i, int &j)
{
int t;
t = i;
i = j;
j = t;
}
Observe lo sencillo que es pasar par
ametros por referencia en C++.
Basta con colocar el signo & precediendo al par
ametro en la primera
lnea de definicion de la funcion. Consecuentemente debe hacerse lo
mismo donde esta el prototipo de la funcion.
En la funcion del siguiente ejemplo se utiliza el metodo de biseccion
visto anteriormente. Hay algunas diferencias con la funci
on bisec0. La
funcion bisec devuelve un valor que posiblemente corresponde a la raz;
adem
as, en un par
ametro por referencia, se tiene informaci
on sobre el
buen o mal desarrollo del proceso.
double bisec(double a, double b, int &indic,
double epsX, double epsF)
{
// Metodo de biseccion para f(x) = 0.
// f debe ser continua en [a,b] y f(a)f(b) < 0.
// Esta funcion calcula dos valores: r , indic
// Devuelve r, posiblemente una raiz.
// indic
es un parametro por referencia.
// indic
//
valdra:
1
si se obtuvo una raiz,
79
4. FUNCIONES
//
//
//
//
//
//
//
0
-1
-2
80
4.4. PARAMETROS
POR DEFECTO
return m;
}
if( fa*fm < 0.0 ){
// nuevo intervalo
b = m;
fb = fm;
}
else{
// nuevo intervalo
a = m;
fa = fm;
}
[a,m]
[m,b]
}
indic = 1;
if( fabs(fa) <= fabs(fb) ) return a;
else return b;
}
El llamado a la funcion bisec puede ser de la forma siguiente:
raiz = bisec(a, b, result, 1.0e-4, 1.0e-6);
if( result == 1 ) printf("\n raiz = %15.10lf\n", raiz);
else printf("result=%d: ERROR en llamado a bisec\n",
result);
4.4
Par
ametros por defecto
4. FUNCIONES
}
//--------------------------------------------------------int bisec(double a, double b, double &raiz, double epsX,
double epsF)
{
...
...
...
}
Si se hace el llamado bisec(a, b, ind, 1.0E-9, 1.0e-10), entonces
la funcion trabajar
a con esos dos valores pasados explcitamente, es decir, epsX = 1.0E-9, y epsF = 1.0E-10.
Si se hace el llamado bisec(a, b, ind, 1.0E-9), entonces la funcion
tomara para el par
ametro faltante, el u
ltimo, el valor predeterminado,
o sea, epsX = 1.0E-9, epsF = 1.0E-8.
Si se hace el llamado bisec(a, b, ind), entonces la funcion tomara
para los par
ametros faltantes, los dos u
ltimos, los dos valores predeterminados, o sea, epsX = 1.0E-6, epsF = 1.0E-8.
4.5
int main(void)
{
...
...
nLlmadasF = 0;
...
... = sin(t/RADIAN);
}
//-------------------------------------... func1( ... )
{
...
nLlamadasF++;
...
... = 2.0*PI;
}
En el esquema anterior, los valores de las variables PI y RADIAN pueden
ser utilizados en cualquier funcion, sin tener que redefinirlos en cada
funcion. La variable nLlamadasF permite saber, en cualquier parte, el
n
umero de veces que la funcion func1 ha sido llamada. En algunos
metodos numericos, la eficiencia se mide por el n
umero de veces que
se realice una operacion (sumas o multiplicaciones) o por el n
umero de
veces que se haga un llamado a una funcion.
4.6
Sobrecarga de funciones
4. FUNCIONES
84
4.7. BIBLIOTECA ESTANDAR
else return c;
}
En cambio, el siguiente ejemplo no esta permitido:
int factorial( int n);
double factorial( int n);
//================================================
int main(void)
{
...
}
//================================================
int factorial( int n )
{
...
}
//-----------------------------------------------double factorial( int n )
{
...
}
4.7
Biblioteca est
andar
alloc.h
complex.h
ctype.h
errno.h
float.h
iostream.h
limits.h
math.h
stddef.h
stdio.h
stdlib.h
string.h
time.h
Asignaci
on din
amica de memoria.
N
umeros complejos. C++. No es estandar.
Manejo de caracteres.
C
odigos de error.
Definicion de constantes para punto flotante.
Flujo de entrada y salida. C++.
Lmites de enteros, depende de la implementaci
on.
Matem
aticas.
Constantes de uso com
un.
Entrada y salida (Input/Output) estandar.
Declaraciones varias.
Manejo de cadenas de caracteres.
Funciones de tiempo del sistema.
85
4. FUNCIONES
Ejercicios
Para cada uno de los enunciados siguientes, defina cu
ales son los
datos necesarios. Haga un programa que lea los datos, llame la funci
on
que realiza los c
alculos y devuelve los resultados y, finalmente,
en la funcion main, muestre los resultados. La funcion debe analizar los
par
ametros, estudiar su consistencia o inconsistencia e informar sobre
ello por medio de los resultados devueltos. Tambien, cuando se justifica,
haga una funcion para la lectura de los datos. Puede ser u
til, cuando
el proceso es bastante complejo, hacer funciones m
as simples que hacen
partes especficas del proceso y son llamadas desde otra funcion que
coordina los calculos.
4.1 La gran mayora de los ejercicios de los dos captulos anteriores
pueden ser resueltos por medio de funciones.
4.2 Dado un n
umero x y un entero no negativo n, calcule xn . H
agalo
mediante un for. Verifique comparando con el resultado producido por la funcion pow.
4.3 Dado un n
umero x y un entero no negativo n, calcule xn . H
agalo
n
n1
mediante una funcion recurrente, x = x x
.
4.4 Dado un n
umero x y un entero no negativo n, calcule xn , tratando
de efectuar pocas multiplicaciones. Por ejemplo para calcular x8
se requiere calcular x2 = xx, x4 = x2 x2 y finalmente x8 = x4 x4 , o
sea, tres multiplicaciones. El calculo de x6 se puede hacer con tres
multiplicaciones. Aparentemente, para calcular x7 es necesario
hacer cuatro multiplicaciones. Adem
as de calcular xn , muestre el
n
umero de multiplicaciones realizadas entre n
umeros double.
86
Arreglos
Los arreglos (arrays) permiten almacenar vectores y matrices. Los arreglos unidimensionales sirven para manejar vectores y los arreglos
bidimensionales para matrices. Sin embargo, las matrices tambien se
pueden almacenar mediante arreglos unidimensionales y por medio de
apuntadores a apuntadores, temas que se veran en el captulo siguiente.
La palabra unidimensional no indica que se trata de vectores en
espacios de dimension uno; indica que su manejo se hace mediante un
subndice. El manejo de los arreglos bidimensionales se hace mediante
dos subndices.
5.1
Arreglos unidimensionales
5. ARREGLOS
// Arreglos unidimensionales
// Lectura y escritura de un vector y calculo del promedio
//-----------------------------------------------#include <math.h>
#include <stdio.h>
#include <stdlib.h>
//-----------------------------------------------void lectX(double *x, int n, char c );
void escrX(double *x, int n );
double promX( double *x, int n);
//================================================
int main()
{
double v[40];
int n;
printf("\n Promedio de elementos de un vector.\n\n");
89
5. ARREGLOS
90
int i;
double s = 0.0;
if( n <= 0 ){
printf(" promX: n = %d inadecuado\n", n);
return 0.0;
}
for( i = 0; i < n; i++) s += x[i];
return s/n;
}
La funcion lectX tiene tres par
ametros: el arreglo, el n
umero de elementos y una letra. Esta letra sirve para el peque
no aviso que sale antes
de la lectura de cada elemento. En el ejemplo, cuando se llama la
funcion, el tercer par
ametro es v; entonces en la ejecuci
on aparecer
an
los avisos:
v(1) =
v(2) =
...
Observe que en el printf de la funcion lectX aparece i+1; entonces
para el usuario el vector empieza en 1 y acaba en n. Internamente
empieza en 0 y acaba en n 1.
5. ARREGLOS
93
5. ARREGLOS
5.2
Arreglos multidimensionales
La declaraci
on de los arreglos bidimensionales, caso particular de los
arreglos multidimensionales, se hace como en el siguiente ejemplo:
double a[3][4];
int pos[10][40];
char list[25][25];
En la primera lnea se reserva espacio para 3 4 = 12 elementos doble
precisi
on. El primer subndice vara entre 0 y 2, y el segundo vara entre
0 y 3. Usualmente, de manera an
aloga a las matrices, se dice que el
primer subndice indica la fila y el segundo subndice indica la columna.
Un arreglo tridimensional se declarara as:
double c[20][30][10];
Los sitios para los elementos de a estan contiguos en el orden fila por
fila, o sea, a[0][0], a[0][1], a[0][2], a[0][3], a[1][0], a[1][1],
a[1][2], a[1][3], a[2][0], a[2][1], a[2][2], a[2][3].
En el siguiente ejemplo, el programa sirve para leer matrices, escribirlas y calcular el producto. Lo hace mediante la utilizacion de funciones
que tienen como par
ametros arreglos bidimensionales.
// prog14
// Arreglos bidimensionales
94
95
5. ARREGLOS
escrA0(a, m, n);
lectA0(b, n, q, B);
printf(" B : \n");
escrA0(b, n, q);
if( prodAB0(a,m,n, b,p,q, c) ){
printf(" C : \n");
escrA0(c, m, q);
}
else printf("\ ERROR\n");
return 0;
}
//================================================
void lectA0(double a[][40], int m, int n, char c )
{
// lectura de los elementos de una matriz.
int i, j;
for( i = 0; i < m; i++){
for( j=0; j < n; j++){
printf(" %c[%d][%d] = ", c, i+1, j+1);
scanf("%lf", &a[i][j] );
}
}
}
//-----------------------------------------------void escrA0(double a[][40], int m, int n )
{
// escritura de los elementos de una matriz
int i, j;
int nEltosLin = 5; // numero de elementos por linea
for( i = 0; i < m; i++){
for( j = 0; j < n; j++){
printf("%15.8lf", a[i][j]);
96
if((j+1)%nEltosLin == 0 || j==n-1)printf("\n");
}
}
}
//-----------------------------------------------int prodAB0(double a[][40], int m, int n, double b[][40],
int p, int q, double c[][40])
{
// producto de dos matrices, a mxn, b pxq
// devuelve 1 si se puede hacer el producto
// devuelve 0 si no se puede
int i, j, k;
double s;
if(m<0||n<0||p<0||q<0 || n!= p ) return 0;
for( i=0; i < m; i++){
for( j=0; j < q; j++){
s = 0.0;
for( k=0; k<n; k++) s += a[i][k]*b[k][j];
c[i][j] = s;
}
}
return 1;
}
Cuando en una funcion un par
ametro es un arreglo bidimensional, la
funcion debe saber, en su definicion, el n
umero de columnas del arreglo
bidimensional. Por eso en la definicion de las funciones esta a[][40].
Esto hace que las funciones del ejemplo sirvan u
nicamente para arreglos
bidimensionales definidos con 40 columnas. Entonces estas funciones no
son de uso general. Este inconveniente se puede resolver de dos maneras:
Mediante apuntadores y apuntadores dobles. Este tema se vera en
el siguiente captulo.
Almacenando las matrices en arreglos unidimensionales con la convencion de que los primeros elementos del arreglo corresponden a
la primera fila de la matriz, los que siguen corresponden a la segunda fila, y as sucesivamente. Esta modalidad es muy usada,
97
5. ARREGLOS
5.3
Cadenas
=
=
=
=
=
=
=
C;
o;
m;
o;
;
e;
s;
98
5.3. CADENAS
aviso[7] = t;
aviso[8] = a;
aviso[9] = ?;
for(i=0; i<= 9; i++) printf("%c", aviso[i]);
return 0;
}
el arreglo aviso se considero como un simple arreglo de caracteres. El
programa escribe
Como esta?
En el siguiente ejemplo, el arreglo aviso es (o contiene) una cadena,
string, pues hay un fin de cadena. Para la escritura se usa el formato
%s. El resultado es el mismo.
// prog15b
// Cadena de caracteres
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
int main()
{
char aviso[30];
aviso[0] = C;
aviso[1] = o;
aviso[2] = m;
aviso[3] = o;
aviso[4] = ;
aviso[5] = e;
aviso[6] = s;
aviso[7] = t;
aviso[8] = a;
aviso[9] = ?;
aviso[10] =\0;
printf("%s", aviso);
return 0;
}
99
5. ARREGLOS
5.3. CADENAS
<math.h>
<stdio.h>
<stdlib.h>
<string.h>
int main()
{
char aviso[30];
strcpy(aviso, "Como esta?");
101
5. ARREGLOS
printf("%s", aviso);
printf("\n longitud = %d\n", strlen(aviso));
return 0;
}
strcat
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char nombre[41], apell[41], Nombre[81];
printf(" Por favor, escriba su nombre
: ");
gets(nombre);
printf(" Por favor, escriba su apellido : ");
gets(apell);
strcpy(Nombre, nombre);
strcat(Nombre, " ");
strcat(Nombre, apell);
printf("Buenos dias %s\n", Nombre);
102
DE ARREGLOS
5.4. INICIALIZACION
return 0;
}
5.4
Inicializaci
on de arreglos
=
=
=
=
1.1;
1.2;
1.3;
1.4;
=
=
=
=
1.1;
1.2;
0.0;
0.0;
Si no se precisa el tama
no del arreglo en una inicializacion, C le asigna
el tama
no dado por el n
umero de elementos. El ejemplo
double x[] = { 1.1, 1.2, 1.3};
es equivalente a
103
5. ARREGLOS
double x[3];
x[0] = 1.1;
x[1] = 1.2;
x[2] = 1.3;
En este otro ejemplo, con una cadena en un arreglo de caracteres,
char saludo[]= "Buenos dias";
resulta lo mismo que escribir
char saludo[12]= {B, u, e, n, o, s, ,
d, i, a, s, \0};
o igual que escribir
char saludo[12];
saludo[0]
saludo[1]
saludo[2]
saludo[3]
saludo[4]
saludo[5]
saludo[6]
saludo[7]
saludo[8]
saludo[9]
saludo[10]
saludo[11]
=
=
=
=
=
=
=
=
=
=
=
=
B;
u;
e;
n;
o;
s;
;
d;
i;
a;
s;
\0;
Para arreglos bidimensionales, basta con recordar que primero estan los
elementos de la fila 0, enseguida los de la fila 1, y as sucesivamente. La
inicializacion
double a[2][3] = { 1.1, 1.2, 1.3, 1.4, 1.5, 1.6};
produce el mismo resultado que
104
DE ARREGLOS
5.4. INICIALIZACION
double a[2][3];
a[0][0]
a[0][1]
a[0][2]
a[1][0]
a[1][1]
a[1][2]
=
=
=
=
=
=
1.1;
1.2;
1.3;
1.4;
1.5;
1.6;
=
=
=
=
=
=
1.1;
1.2;
1.3;
1.4;
0.0;
0.0;
En las siguientes inicializaciones hay errores. Para los arreglos bidimensionales, C necesita conocer el tama
no de las filas (el n
umero de
columnas).
double a[][] = { 1.1, 1.2, 1.3, 1.4, 1.5, 1.6};
double b[2][] = { 1.1, 1.2, 1.3, 1.4, 1.5, 1.6};
Ejercicios
105
5. ARREGLOS
DE ARREGLOS
5.4. INICIALIZACION
5. ARREGLOS
108
Apuntadores
Los apuntadores, llamados tambien punteros, son variables que guardan
direcciones de memoria de variables doble precisi
on o de variables enteras o de variables de otro tipo. En el siguiente ejemplo, p y q estan
declaradas como apuntadores, p esta disponible para guardar una direcci
on de una variable doble precisi
on. Usualmente se dice que p apunta
a una variable doble precisi
on. El otro apuntador, q, apunta (puede
apuntar) a una variable entera.
double *p, x = 0.5;
int *q, i = 4;
Inicialmente estos dos apuntadores tienen un valor cualquiera. Para
realmente asignarles una direccion, se debe escribir algo de la forma:
p = &x;
q = &i;
Escribir p = &i es un error. El operador & es un operador unario (llamado algunas veces monario) que devuelve la direccion de memoria de
una variable. El otro operador para apuntadores es * , que devuelve
el valor contenido en una direccion. Estos dos operadores son inversos entre s. Por un lado, *(&x) es exactamente lo mismo que x .
An
alogamente, &(*p) es exactamente igual a p .
Considere el siguiente ejemplo:
double *p, x = 0.5, y, *r;
109
6. APUNTADORES
%p
%p
%p
%p
%d %lf\n",
%d %d\n",
%d\n", r,
%d\n", s,
p, int(p), y);
q, int(q), j);
int(r));
int(s));
6618620 0.500000
6618608 4
6618628
6618620
6.1
111
6. APUNTADORES
cout<<" p = "<<p<<endl;
El resultado es el siguiente:
x = 0x0064f924,
p = 0x0064f924
La variable x es un arreglo unidimensional de 156 elementos doble precision, pero para ciertas cosas se considera como una direccion de memoria. Al escribir x, el resultado es una direccion de memoria. Observe
tambien que es exactamente la direccion del primer elemento del arreglo,
o sea, de x[0]. Usando cout la direccion aparece con min
usculas y hay
10 caracteres. En los ejemplos anteriores, con printf hay may
usculas
y 8 caracteres. Siendo p un apuntador, la asignaci
on p = x es correcta.
En la segunda lnea de resultados, aparece efectivamente la misma direcci
on.
En el siguiente ejemplo, a es un arreglo bidimensional; hay varias
coincidencias con el ejemplo anterior, pero la asignaci
on p = a es
incorrecta.
double a[10][20] = {1.1, 1.2, 1.3, 1.4};
double *p;
cout<<" a = "<<a<<" dir. de a[0][0] = "<<&a[0][0]<<endl;
// p = a;
// La instruccion anterior (en comentario) es incorrecta.
p = &a[0][0];
cout<<" p = "<<p<<endl;
El resultado es:
a = 0x0064f7c4
p = 0x0064f7c4
112
p = x;
q = x;
for( i=0; i <= 5; i++){
printf("%6.2lf%6.2lf%6.2lf\n", x[i], *(p+i), *q);
q++;
}
El resultado es el siguiente:
1.10
1.20
1.30
0.00
0.00
0.00
1.10
1.20
1.30
0.00
0.00
0.00
1.10
1.20
1.30
0.00
0.00
0.00
Es m
as facil ver la equivalencia entre x[i] y *(p+i) si esta u
ltima
expresi
on se escribe *(&x[0]+i), o sea, el contenido de la direccion de
x[0] incrementada en i.
En el ejemplo anterior, el uso del apuntador q sugiere el uso de apuntadores para el manejo de los arreglos. A continuaci
on hay varias formas
de una funcion que calcula el promedio de los primeros n elementos de
un arreglo.
double promX1( double *x, int n)
{
// promedio de los elementos del vector
int i;
double s = 0.0;
// error si
n <= 0
6. APUNTADORES
n <= 0
pFin = x+n;
for( p = x ; p < pFin; p++) s += *p;
return s/n;
}
//-----------------------------------------------double promX3( double *x, int n)
{
// promedio de los elementos del vector x
double *p, *pFin;
double s = 0.0;
// error si
n <= 0
p = x;
pFin = x+n;
while( p < pFin){
s += *p;
p++;
}
return s/n;
}
//-----------------------------------------------double promX4( double *x, int n)
{
// promedio de los elementos del vector x
double *p, *pFin;
double s = 0.0;
// error si
n <= 0
114
p = x;
pFin = x+n;
while( p < pFin) s += *p++;
return s/n;
}
En ciertos casos el manejo de un arreglo con apuntadores es m
as eficiente que el manejo con subndices. Sin embargo, para una persona
no muy acostumbrada a la utilizaci
on de los apuntadores, es m
as facil
escribir o leer un programa donde los arreglos se tratan por medio de
subndices. A lo largo de este libro habr
a ejemplos con los dos enfoques:
con subndices para tratar de ofrecer mayor claridad; con apuntadores
para buscar, posiblemente, mayor eficiencia y para ir acostumbrando al
lector a su comprensi
on y manejo. Un programador de nivel intermedio
puede facilmente traducir un programa con subndices a un programa
con apuntadores.
Considere ahora la siguiente porci
on de codigo donde se utiliza cualquiera
de las cuatro funciones que calculan el promedio.
double x[100] = { 0.1, 0.2, 0.3};
printf("%lf\n", promX1(x,4) );
printf("%lf\n", promX1( &x[2], 10) );
El resultado es el siguiente:
0.150000
0.030000
Es claro que el promedio de los primeros cuatro valores del arreglo x:
0.1, 0.2, 0.3 y 0.0, es 0.15 . En la segunda llamada a la funcion promX1,
el primer par
ametro es la direccion de memoria del elemento x[2] y
el segundo es el valor 10; entonces, la funcion promX1, que espera un
arreglo, considera un arreglo que empieza exactamente en esa direccion
y que tiene 10 elementos, o sea, los valores 0.3, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
0.0, 0.0, 0.0; su promedio es 0.03. Esta manera de pasar como par
ametro
un arreglo que en realidad es parte de un arreglo m
as grande, es muy u
til
y eficiente para el manejo de vectores y matrices en metodos numericos.
115
6. APUNTADORES
6.2
Apuntadores a apuntadores
q, es decir, la direccion de p,
6.3
Como los arreglos bidimensionales almacenan las matrices fila por fila,
entonces se puede saber en que posicion, a partir del elemento a[0][0],
esta el elemento a[i][j]. Si n es el tama
no de una fila, es decir, el
n
umero de columnas, entonces el elemento a[i][j] esta i n + j posiciones despues de a[0][0].
El siguiente ejemplo produce como resultado dos valores iguales:
116
=
=
=
=
3;
2;
1;
&c[0][0];
6.4
6. APUNTADORES
118
printf(" A : \n");
escrA1(a, m, n);
lectA1(b, n, q, B);
printf(" B : \n");
escrA1(b, n, q);
if( prodABsub1(a,m,n, b,p,q, c) ){
printf(" C : \n");
escrA1(c, m, q);
}
else printf("\ ERROR\n");
return 0;
}
//================================================
void lectA1(double *a, int m, int n, char c )
{
// lectura de los elementos de una matriz.
// almacenada en un "vector"
int i, j;
for( i = 0; i < m; i++){
for( j=0; j < n; j++){
printf(" %c[%d][%d] = ", c, i+1, j+1);
scanf("%lf", &a[i*n+j] );
}
}
}
//-----------------------------------------------void escrA1(double *a, int m, int n )
{
// escritura de los elementos de una matriz
// almacenada en un vector
// utiliza escrX
int i;
119
6. APUNTADORES
120
Observe que la funcion que escribe la matriz, escrA1, lo hace fila por fila.
Para esto llama varias veces la funcion escrX que escribe los elementos
de un vector. O sea, cada fila de la matriz se considera como un vector
de n elementos que empieza en la direccion de a[i*n].
En el programa anterior, como en un ejemplo ya visto, durante la
lectura de la matriz, aparecen lo subndices i+1 y j+1. Entonces, para
el usuario, aparentemente los subndices empiezan en 1 y acaban en m
o en n.
A manera de ejemplo del paso de manejar los arreglos con subndices
al tratamiento mediante apuntadores, a continuaci
on hay una versi
on
de la funcion que calcula el producto entre matrices, almacenadas en
vectores, mediante el uso de apuntadores.
int prodABap1(double *a, int m, int n, double *b, int p,
int q, double *c)
{
// producto de dos matrices, a mxn, b pxq
// devuelve 1 si se puede hacer el producto
// devuelve 0 si no se puede
// Las matrices estan almacenadas en "vectores"
// el producto se hace por medio de apuntadores
double
double
double
double
double
double
*cij,
*cmq;
*ciq;
*ai0;
*ain;
*b0j;
6. APUNTADORES
ain = ai0+n;
bkj = b0j;
*cij = 0.0;
while( aik < ain ){
*cij += (*aik++)*(*bkj);
bkj += q;
}
cij++;
b0j++;
}
ai0 = ain;
}
return 1;
}
La elaboracion de la funcion prodABsub1 es m
as facil que la de la funcion
prodABap1. Su lectura, por otro programador, tambien es m
as facil. Sin
embargo, la funcion prodABsub1 tiene algunas ineficiencias claras.
Dentro de un bucle for (y dentro de los otros bucles) no se deben
realizar operaciones independientes de las variables que se modifican
dentro del for; es m
as eficiente usar una variable a la que se le asigna,
fuera del for, el valor de la operacion y, en lugar de efectuar la operaci
on
dentro del for, se usa la variable suplementaria. Por ejemplo, en la
funcion prodABsub1, dentro del bucle for(k=...) se realiza varias veces,
quizas muchas, la operacion i*n+k. Como las variables i , n no se
modifican dentro de este for, entonces es preferible utilizar una variable
entera adicional, por ejemplo llamada in, fuera de este for hacer la
asignaci
on in = i*n; y dentro del for(k=...) utilizar a[in+k].
La siguiente funcion, prodABsub2 , es una versi
on m
as eficiente de
la funcion prodABsub1 .
int prodABsub2(double *a, int m, int n, double *b, int p,
int q, double *c)
{
// ...
int i, j, k, in, iq;
double s;
122
6. APUNTADORES
s += a[ink]*b[kq+j];
ink++;
}
c[iqj] = s;
iqj++;
}
iq += q;
}
return 1;
}
//--------------------------------------------------------int prodABap2(double *a, int m, int n, double *b, int p,
int q, double *c)
{
// ...
double
double
double
double
double
double
*cij,
*ai0;
*ain;
*b0j;
*amn;
*b0q;
124
}
ain += n;
}
return 1;
}
Esta funciones pueden ser mejoradas dependiendo, parcialmente, de la
plataforma y del compilador. Todas tienen una eficiencia m
as o menos
semejante, salvo la primera, prodABsub1, que es un poco menos eficiente.
La siguiente tabla muestra los tiempos para el producto de matrices
500 500 y 1000 1000. Estos resultados corresponden a un compilador
Borland C++ 5.2 para Win32 en un microcomputador con procesador
Intel Pentium III MMX de 450 Mhz con 128 Mb de memoria RAM.
El n
umero de operaciones para el producto de dos matrices n n es
proporcional a n3 . Es interesante comprobar que, al duplicar el tama
no
3
de las matrices, el tiempo, aproximadamente, se multiplica por 2 = 8.
subndices
subndices
subndices
apuntadores
apuntadores
prodABsub1
prodABsub2
prodABsub3
prodABap1
prodABap2
n = 500
8.8
8.0
7.7
7.8
7.9
n = 1000
67.8
63.3
60.9
63.1
63.4
Otra manera de hacer el producto de dos matrices almacenadas en vectores, mediante el uso de apuntadores, que permite m
as claridad y que
brinda la posibilidad de tratar de optimizar cada parte por separado,
consiste en utilizar el hecho de que el elemento cij de la matriz producto es simplemente el producto escalar de la fila i de A y la columna
j de B. La fila i de A es simplemente el vector que empieza en la direcci
on del primer elemento de la fila y tiene n elementos, uno despues
del otro, de manera contigua. En la columna j de la matriz B hay un
ligero inconveniente, los elementos estan en un arreglo, pero no consecutivamente. Para pasar de un elemento al siguiente, hay que saltar q
posiciones (suponiendo que B es p q).
A continuaci
on hay dos funciones que hacen el producto escalar de
dos vectores de n elementos. El primero esta almacenado en el arreglo
x ; hay que saltar saltox posiciones para pasar de un elemento al siguiente. Es decir, son los elementos x[0], x[saltox], x[2*saltox], ...,
125
6. APUNTADORES
x[(n-1)*saltox]. De manera an
aloga, los elementos del segundo vector son: y[0], y[saltoy], y[2*saltoy], ..., y[(n-1)*saltoy]. La
primera funcion prodXYsub se hace de manera casi natural; la segunda,
prodXY, es posiblemente m
as eficiente, pero su programaci
on requiere
m
as tiempo. Se puede utilizar el siguiente criterio: es u
til gastar m
as
tiempo haciendo una funcion m
as eficiente si esta se va a usa muchas
veces. Como es m
as eficiente i++ que i += 1 , entonces esta u
ltima
funcion considera por aparte el caso salto == 1 y el caso salto != 1.
127
6. APUNTADORES
else{
// saltox != 1; saltoy != 1
xi = x;
xn = x + n*saltox;
yi = y;
while( xi < xn ){
s += (*xi)*(*yi);
xi += saltox;
yi += saltoy;
}
}
}
return s;
}
Utilizando la funcion prodXY, la funcion que calcula el producto de dos
matrices podra tener la siguiente forma:
int prodAB1(double *a, int m, int n, double *b, int p,
int q, double *c)
{
// Producto de dos matrices, A mxn, B pxq.
// Devuelve 1 si se puede hacer el producto,
// devuelve 0 si no se puede.
// Las matrices estan almacenadas en "vectores".
// El producto se hace por medio de apuntadores.
// Utiliza una funcion de producto escalar.
double
double
double
double
double
*cij;
*cmq;
*ciq;
*ai0;
*b0j;
//
//
//
//
//
apuntador
apuntador
apunt. a
apuntador
apuntador
a Cij
a la direccion de c[m*q]
C(i+1,0) : Ciq : c[i*q]
a Ai0
a B0j
ciq = cij + q;
b0j = b;
while( cij < ciq ){
*cij = prodXY(ai0, 1, b0j, q, n);
cij++;
b0j++;
}
ai0 += n;
}
return 1;
}
Normalmente una funcion es un poco menos eficiente cuando llama otra
funcion para hacer un proceso, que cuando directamente lo hace internamente. Pero, por otro lado, repartir el trabajo en funciones permite
revisar, depurar y tratar de optimizar m
as facilmente cada funcion por
aparte.
En el ejemplo del producto de matrices, resulto a
un m
as eficiente
esta u
ltima funcion prodAB1 que la funcion prodABap1. Esto se
debe tal vez a que la funcion prodXY es bastante eficiente y que muy
posiblemente la funcion prodABsub1 tiene varias partes susceptibles de
ser mejoradas. La siguiente tabla muestra los tiempos, en segundos, para
el producto de dos matrices cuadradas, con n = 500 y con n = 1000.
subndices
apuntadores
apuntadores + prod. escalar
6.5
prodABsub2
prodABap1
prodAB1
n = 500
8.0
7.8
7.0
n = 1000
63.3
63.1
56.0
Arreglos aleatorios
6. APUNTADORES
ba
r.
RAND MAX
[ a, b ]
double r;
r = a + rand()*(b-a)/RAND_MAX;
return r;
}
Utilizando la anterior funcion se puede hacer una funcion que da valores
aleatorios a los elementos de un arreglo unidimensional.
void aleatX( double *x, int n, double a, double b)
{
// vector aleatorio, valores entre a y b
int k;
for( k=0; k<n; k++) x[k] = aleat(a,b);
}
En el siguiente trozo de programa, se hace el llamado a la funcion anterior, primero para un vector, luego para una matriz almacenada en un
arreglo unidimensional.
130
DINAMICA
6.6. ASIGNACION
DE MEMORIA
double x[1000];
double a[250000]; // matriz A
int m, n;
...
m = 400;
n = 500;
...
aleatX(x, n, 0.0, 1.0);
aleatX(a, m*n, -1.0, 1.0);
...
6.6
Asignaci
on din
amica de memoria
6. APUNTADORES
x = malloc( n*sizeof(double) );
if( x == NULL ){
printf(" Memoria insuficiente\n");
exit(1);
}
aleatX(x, n, -1.0, 1.0);
escrX(x, n);
free(x);
A lo largo de este libro se supondr
a que cuando un programa usa funciones definidas con anterioridad, para que funcione, es necesario agregar, al codigo presentado, el prototipo, la definicion y los archivos de
cabecera de cada una de las funciones utilizadas.
La funcion sizeof, del lenguaje C, da como resultado un entero
que indica el n
umero de bytes que utilizan las variables cuyo tipo es
el indicado por el par
ametro. En la mayora de las implementaciones
sizeof(double) es 8. La funcion malloc reserva el n
umero de bytes indicado por el par
ametro. Se hubiera podido escribir x = malloc(n*8),
pero podra no funcionar en un computador con un compilador de C
donde los n
umeros doble precisi
on utilicen un n
umero de bytes diferente
de 8. Cuando no hay suficiente memoria disponible, la funcion malloc
devuelve NULL, o sea, el apuntador valdra NULL. Es muy conveniente
controlar siempre si hubo suficiente memoria. La funcion free libera el
espacio que haba sido reservado para x.
El ejemplo anterior, hecho en C, y suponiendo que las funciones estan
estrictamente en C, puede presentar errores con algunos compiladores,
si se compila como programa C++. Este hecho es muy poco frecuente,
pero puede suceder.
El anterior inconveniente se puede solucionar colocando un molde
para el uso de malloc:
x = (double *)malloc( n*sizeof(double) );
La asignaci
on anterior es valida tanto en C como en C++.
La asignaci
on de memoria en C++ es m
as sencilla; se hace por medio
de new. La memoria que ya fue utilizada y que no se necesita m
as, se
libera mediante delete. Aunque a veces no es absolutamente indispens132
DINAMICA
6.6. ASIGNACION
DE MEMORIA
6. APUNTADORES
Una manera m
as eficiente de evaluar p(t) = a0 + a1 t + a2 t2 + + an tn
consiste en observar la siguiente manera de agrupar.
p(t) = ( (((an )t + an1 )t + an2 )t + + a1 )t + a0 .
Es decir, se empieza con el valor an . A continuaci
on se repite el proceso:
se multiplica por t y se adiciona el siguiente coeficiente (en orden decreciente). Esta manera de calcular se conoce con el nombre de esquema
de H
orner o tambien hace parte del proceso conocido como divisi
on
sintetica. La divisi
on sintetica permite evaluar p(t) y, al mismo tiempo,
proporciona el polinomio cociente al efectuar la divisi
on p(x)/(x t).
Como ejemplo, considere el polinomio p(x) = 3 4x + 5x2 16x3 + 7x4
dividido por x 2.
7
7
16
14
2
5
4
1
4
2
2
3
4
1
double
{
//
//
//
//
//
6.7
500000
0.33
0.03
1000000
0.65
0.06
5000000
3.56
0.29
6. APUNTADORES
del primer elemento de la fila. O sea, cada fila se maneja por medio
de un apuntador. Como hay m filas, entonces hay m apuntadores y se
necesita un arreglo con los m apuntadores. A su vez este arreglo de
apuntadores se puede manejar con la direccion del primer apuntador, o
sea, con un apuntador a apuntador.
Si a es un apuntador doble, entonces a[i] es la direccion de a[i][0]
y a es la direccion de a[0], es decir,
a[i] = &a[i][0],
a = &a[0].
En el siguiente ejemplo se hace un asignaci
on din
amica de memoria
para una matriz, se imprimen ciertas direcciones y valores y se libera la
memoria asignada.
double **a;
int m, n, i, j;
m = 4;
n = 3;
//-------------------------------------------// asignacion de memoria
a = new double *[m] ;
if( a == NULL ){
printf("Memoria insuficiente\n");
exit(1);
}
for( i=0; i<m; i++) {
a[i] = new double [n];
if( a[i] == NULL ){
printf("Memoria insuficiente\n");
exit(1);
}
}
//-------------------------------------------// algunos resultados
for( i = 0; i < m; i++){
136
&a[0][1]=6695116
&a[1][1]=6695144
&a[2][1]=6695172
&a[3][1]=6695200
&a[0][2]=6695124
&a[1][2]=6695152
&a[2][2]=6695180
&a[3][2]=6695208
a[0]=6695108
a[1]=6695136
a[2]=6695164
a[3]=6695192
&a[0]=6695088
&a[1]=6695092
&a[2]=6695096
&a[3]=6695100
a = 6695088
Observe, en el ejemplo anterior, los siguientes hechos:
En la declaraci
on, el nombre del apuntador doble esta precedido
por dos asteriscos.
137
6. APUNTADORES
double **p;
int i;
p = new double *[m] ;
138
m x n
if( p == NULL
) return( NULL );
6.8
Arreglos a partir de 1
6. APUNTADORES
// arreglo entre 1 y n
int n, i;
n = 7;
x = new double[n];
x--;
for( i = 1; i <= n; i++) x[i] = i*i*i;
x++;
delete x;
Suponga que el valor de x , despues de la asignaci
on de memoria, es
la direccion 10328. Entonces las 7 direcciones para los 7 elementos del
arreglo son: 10328+08, 10328+18, 10328+28, ..., 10328+68. La
orden x-- hace que el valor de x se disminuya en una unidad de memoria
doble precisi
on, entonces x pasa a valer 10320. Las posiciones de
memoria para los 7 elementos siguen siendo las mismas, pero se pueden
ver como los valores 10320 + 1 8, 10320 + 2 8, 10320 + 3 8, ...,
10320 + 7 8. Es decir, a partir de ese nuevo valor de x, los elementos
del vector estaran en las posiciones 1 hasta 7.
Para liberar la memoria se requiere que x tenga el valor inicial, entonces es necesario incrementar su valor en una unidad (de memoria
doble precisi
on).
La siguiente porci
on de programa muestra como podra ser el manejo
de arreglos bidimensionales con asignaci
on din
amica de memoria, comenzando en el subndice 1.
double **a; // matriz
int m, n, i, j;
m = 3;
140
n = 4;
a = new double *[m];
if( a == NULL ){
printf(" Memoria insuficiente\n");
exit(1);
}
a--;
for( i = 1; i <= m; i++){
a[i] = new double[n];
if( a[i] == NULL ){
printf(" Memoria insuficiente\n");
exit(1);
}
a[i]--;
}
for( i = 1; i <= m; i++){
for( j = 1; j <= n; j++) a[i][j] = i*j;
}
// liberacion de la memoria
for( i = 1; i <= m; i++ ){
a[i]++;
delete a[i];
}
a++;
delete a;
Fue necesario disminuir en una unidad tanto a , como cada uno de los
a[i]. Para liberar la memoria se requiere el proceso inverso.
A fin de obtener un arreglo con subndice que vare entre i1 y i2,
i1<i2, se necesita asignar memoria para i2-i1+1 elementos y disminuir
el valor del apuntador en i1. El siguiente ejemplo ilustra lo anterior.
double *y;
// arreglo entre
141
i1 e i2, i1 < i2
6. APUNTADORES
i1 = -2;
i2 = 7;
y = new double[i2-i1+1];
y -= i1;
for( i =i1; i <= i2; i++) y[i] = rand();
y += i1;
delete y;
Ejercicios
Para cada uno de los enunciados siguientes, defina cu
ales son los datos
necesarios. Haga un programa que lea los datos, llame la funcion (o las
funciones) que realiza los calculos y devuelve los resultados, y finalmente
que el programa principal (la funcion main) muestre los resultados. En
todos los casos haga asignaci
on din
amica de memoria. Cuando se trate
de matrices, haga el programa de dos maneras, almacenando la matriz
mediante apuntadores sencillos y mediante apuntadores dobles.
6.1 Considere los ejercicios del captulo anterior.
6.2 Haga funciones que realicen las siguientes operaciones elementales
sobre las filas de una matriz: intercambiar dos filas; multiplicar
una fila por una constante; agregar a una fila un m
ultiplo de otra
fila.
6.3 Construya la traspuesta de una matriz.
6.4 Dada una matriz A, calcule AT A.
6.5 Averig
ue si una matriz es simetrica.
6.6 Averig
ue si una matriz es diagonal.
6.7 Averig
ue si una matriz es triangular superior.
142
Lectura y escritura en
archivos
Este captulo presenta las nociones de C sobre la lectura y escritura
en archivos de texto. La lectura de un archivo existente, se hace de
manera secuencial, es decir, lo que esta en el archivo se lee en el orden en
que aparece. No se puede leer un dato al principio del archivo, despues
al final y despues en la mitad. La escritura tambien es secuencial.
En realidad, de manera artificial, s se podra, por ejemplo, leer el
primer dato, leer los datos que siguen pero desechandolos hasta llegar
al final, leer el dato deseado, devolverse hasta el principio, leer datos
desechandolos y leer el dato deseado en un punto intermedio del archivo.
Sin embargo, en este libro, siempre se supondr
a que la lectura y escritura
se hacen de manera natural, es decir, secuencial.
Las principales funciones que se utilizan para la entrada y salida con
archivos estan a continuaci
on. La palabra entrada se refiere a lectura: la
informaci
on entra, desde un archivo, al programa. La palabra salida se
refiere a escritura: la informaci
on sale del programa hacia un archivo.
Observe que por convencion todas empiezan por la letra f (de file).
fopen,
fscanf,
fclose,
fprintf,
feof.
143
7.1
144
El programa usa las variables archDat y archRes. Estas variables apuntan a un FILE, que es el tipo de archivo que se va a utilizar, es decir,
un archivo de texto de acceso secuencial. Simplificando, se puede decir
que archDat es el nombre de un archivo dentro del programa.
El nombre externo del archivo, en el sistema operacional, es datos1.
La funcion fopen hace la correspondencia entre el nombre interno y el
nombre externo, y abre el archivo. El segundo par
ametro de fopen, o
sea la cadena de caracteres "r", indica que se trata de un archivo para
lectura.
Las maneras m
as usuales de manejo de archivos de texto mediante
fopen son:
"r"
"w"
"a"
"r+"
Para
Para
Para
Para
lectura.
escritura.
escritura, al final del archivo.
lectura y escritura.
1.2
4
145
4 5.1
7.2
feof
7.2. feof
fin = 0;
while( !fin ){
res = fscanf(archDat, "%lf", &xi);
if( feof(archDat) || res <= 0 ) fin = 1;
else{
fprintf(archRes, "%12.6lf\n", xi);
n++;
sumax += xi;
sumaxx += xi*xi;
}
}
fclose(archDat);
if( n > 0 ){
prom = sumax/n;
desvEst = sqrt( (sumaxx - n*prom*prom)/n );
fprintf(archRes, "promedio = %12.4lf\n", prom);
fprintf(archRes, "desviacion estandar = %12.4lf\n",
desvEst);
}
else {
fprintf(archRes, " No hay numeros.\n");
}
fclose(archRes);
return 0;
}
Si en el archivo solamente hay n
umeros bien escritos, el programa calcula
su promedio y desviacion estandar. Si antes del fin de archivo la funcion
fscanf detecta errores en la lectura, entonces el programa calcula el
promedio y desviacion estandar de los valores ledos hasta ese momento.
7.3
Algunos ejemplos
A continuaci
on aparecen varios ejemplos de funciones de lectura y de
escritura en archivos, de vectores y de matrices almacenadas en arreglos
unidimensionales o mediante el uso de apuntadores dobles.
int flectX(FILE *arch, double *x, int n)
150
{
// Lectura en un archivo de los primeros
// elementos de un arreglo
x.
// Devuelve 1
//
0
//
//
-1
//
int i, res;
for(i=0; i< n; i++){
res = fscanf(arch, "%lf", &x[i]);
if( feof(arch) ) return 0;
if( res <= 0 ) return -1;
}
return 1;
}
//--------------------------------------------------------void fescrX(FILE *arch, double *x, int n )
{
//escritura en un archivo de los elementos de un vector
int j;
int nEltosLin = 5; // numero de elementos por linea
for( j = 0; j < n; j++){
fprintf(arch, "%15.8lf", x[j]);
if((j+1)%nEltosLin == 0 || j== n-1)
fprintf(arch,"\n");
}
}
A continuaci
on se presenta un ejemplo esquem
atico de la utilizacion de
las dos funciones anteriores.
double *x;
FILE *archDat, *archRes;
151
int n, res;
...
archDat = fopen( ..., "r");
if( archDat == NULL ){
printf("\n\n Archivo inexistente.\n\n");
exit(1);
}
...
archRes = fopen( ..., "w");
152
// Devuelve 1
//
0
//
//
-1
//
// usa :
flectX
int i, res;
for(i=0; i< m; i++){
res = flectX(arch, &a[i*n], n);
if( res <= 0 ) return res;
}
return 1;
}
//-----------------------------------------------void fescrA1(FILE *arch, double *a, int m, int n)
{
// Escritura en un archivo de una matriz m x n
// almacenada en un arreglo unidimensional
// usa :
fescrX
int i;
for(i=0; i< m; i++) fescrX(arch, &a[i*n], n);
}
//-----------------------------------------------int flectA(FILE *arch, double **a, int m, int n)
{
// Lectura en un archivo de una matriz m x n
// almacenada mediante un apuntador doble.
// Devuelve 1
//
0
//
//
-1
si
si
de
si
153
//
con
// usa :
fscanf.
flectX
int i, res;
for(i=0; i< m; i++){
res = flectX(arch, a[i], n);
if( res <= 0 ) return res;
}
return 1;
}
//-----------------------------------------------void fescrA(FILE *arch, double **a, int m, int n)
{
// Escritura en un archivo de una matriz m x n
// almacenada mediante un apuntador doble.
// usa :
fescrX
int i;
for(i=0; i< m; i++) fescrX(arch, a[i], n);
}
Ejercicios
Para cada uno de los enunciados siguientes, defina cu
ales son los
datos necesarios. Haga un programa que lea los datos en un archivo,
llame la funcion que realiza los calculos y finalmente escriba los resultados en un archivo.
7.1 Considere los ejercicios de los captulos anteriores, especialmente
aquellos en que el n
umero de datos puede ser grande.
7.2 Considere un archivo que contiene u
nicamente n
umeros; por ejemplo:
3.141592
-342
154
1.5e-2
-32.1542
32.5E+02 +31 31.45 1000
0.31415E1
Haga un programa que detecte si hay errores. Si los hay, indique
el n
umero de la lnea donde esta el error (por lo menos el primero)
y muestre el trozo de lnea donde esta el error. Si no hay errores, habiendo averiguado el n
umero de n
umeros, asigne memoria din
amicamente y almacene los n
umeros. Sugerencia: lea cada
lnea del archivo como una cadena. En cada lnea determine la
subcadena correspondiente a un posible n
umero y conviertala, si
es posible, en un n
umero.
7.3 Considere un archivo de texto donde estan los resultados de una
encuesta. Defina la estructura del archivo; por ejemplo, de las
columnas 1 a 10 hay un codigo, 11-12 edad, 13 sexo, 14-20 sueldo,
21-22 n
umero de hijos, etc. Haga un programa que lea el archivo
y encuentre las posibles inconsistencias, no solo de cada campo
(edad, sueldo...) sino tambien entre campo y campo; por ejemplo,
en las columnas 14-20 no debe haber letras, la edad no puede ser
negativa, si la edad es 10 no puede tener 4 hijos...
7.4 Considere un archivo con restricciones (igualdades o desigualdades)
escrito de manera semejante al siguiente ejemplo:
2*escritorios + 3*sillas>=24
4.5*mesas+3.1*sillas <= 31.5
Defina las caractersticas que debe tener el archivo. Haga un programa que lea el archivo, detecte si esta bien hecho y escriba en
otro archivo el n
umero de variables, el n
umero de restricciones, la
lista de las variables y las restricciones por medio de una matriz
A, un vector de tipos de restricciones y un vector b de terminos
independientes.
155
156
Temas varios
Este captulo contiene varios temas sueltos, que no son indispensables
pero pueden ser muy u
tiles en algunos casos.
8.1
sizeof
diferentes tipos.\n\n");
sizeof(int));
sizeof(float));
sizeof(double));
8. TEMAS VARIOS
printf(" char
printf("
printf("
printf("
printf("
%d \n\n", sizeof(char));
p = y;
printf(" arreglo
printf(" arreglo
printf(" apuntador
printf(" apuntador
return 0;
y
a
x
p
:
:
:
:
%d\n",
%d\n",
%d\n",
%d\n",
sizeof(y) );
sizeof(a) );
sizeof(x));
sizeof(p));
}
El programa anterior produce los siguientes resultados:
Tama~nos (bytes) de los diferentes tipos.
int
float
double
char
:
:
:
:
4
4
8
1
short int : 2
long int
: 4
unsigned
: 4
long double: 10
arreglo
arreglo
apuntador
apuntador
y
a
x
p
:
:
:
:
80
800
4
4
8.2. const
8.2
const
Si en la declaraci
on de algunas variables, el especificador const precede
al tipo, entonces el compilador sabe que esas variables no pueden ser
modificadas en el programa. M
as especficamente, no puede haber asignaciones donde el lado izquierdo sea una de esas variables. Adem
as, hace
m
as legible el programa fuente, al indicar que se trata de una constante.
const double c = 2.998E8, velSon = 331.0;
// velocidades de la luz y del sonido en m/s
const int nMax = 100;
El compilador producira un mensaje de error si posteriormente se trata
de hacer una asignaci
on. El mensaje de error puede ser an
alogo a
Error...: Cannot modify a const object in function main().
c *= 1.001;
nMax += 0;
Observe que realmente nMax += 0 no trata de modificar la variable nMax,
pero para el compilador es un error por estar en el lado izquierdo de una
asignaci
on.
8.3
typedef
La utilizaci
on de typedef simplemente introduce un sinonimo para un
tipo de datos. El esquema de su uso es el siguiente:
typedef tipo sin
onimo;
Por ejemplo,
typedef int entero;
159
8. TEMAS VARIOS
typedef
#include
#include
#include
#include
#include
#include
<math.h>
<stdio.h>
<stdlib.h>
<time.h>
"misfunc.h"
<iostream.h>
8.4. include
//======================================
numero epsMaq(void)
{
// calculo aproximado del epsilon de la maquina
const numero uno = 1.0;
const numero divisor = 2.0;
numero eps, unoEps;
eps = 1.0;
unoEps = uno+eps;
while( unoEps > uno ){
eps /= divisor;
unoEps = uno+eps;
}
eps *= divisor;
return eps;
}
El resultado puede ser 2.22045e-16. Esto indica que los n
umeros doble
precisi
on utilizan aproximadamente 16 cifras significativas.
Si se desea calcular el epsilon de la m
aquina usando n
umeros de
precisi
on sencilla, basta con cambiar u
nicamente la lnea typedef, para
que quede
typedef float numero;
En este caso el resultado puede ser 1.19209e-07, lo que indica que
los n
umeros de precisi
on sencilla utilizan aproximadamente siete cifras
significativas.
8.4
include
8. TEMAS VARIOS
162
8.4. include
numeros
#include <iostream.h>
#include "mibibl.h"
int main()
{
double a, b, c;
cout<<"\n\n Minimo y maximo de 3 numeros.\n\n";
cout<<" entre los 3 numeros : ";
cin>>a>>b>>c;
cout<<a<<" "<<b<<" "<<c<<endl;
cout<<" minimo = "<<min(a, min(b, c) )<<endl;
cout<<" maximo = "<<max(a, max(b, c) )<<endl;
return 0;
}
Para proyectos de mayor tama
no, el archivo de cabecera, un archivo .h,
tiene u
nicamente los prototipos de las funciones. En otro archivo, un
archivo .c o .cpp, estan las definiciones de las funciones. Este u
ltimo,
cuando ya esta depurado, se compila una sola vez y esta listo para el
enlace o link. El resultado es un archivo .obj. El archivo donde esta
la funcion main tiene un include para el archivo .h, no para el archivo
donde estan las definiciones. As, cuando se compila el programa principal (lo cual se hace muchas veces), este incluye el archivo .h, muy
peque
no, y despues se hace el enlace con el .obj que esta listo. Si el
include abarcara, en un todo, los prototipos y las definiciones, cada vez
que se compila el programa principal habra que recompilar las definiciones de las funciones.
163
8. TEMAS VARIOS
8.5
define
La directriz define tiene dos usos. El primero sirve para definir constantes. Por tradicion estas constantes se escriben en may
usculas. Por
ejemplo:
#define PI 3.14159265358979
Cuando el compilador encuentra el identificador definido por medio de
la directriz define, lo reemplaza por la cadena asociada. En define se
puede usar algo ya definido; por ejemplo,
#define PI 3.14159265358979
#define PI2 2.0*PI
Observe que, como en las otras directrices para el preprocesador, no hay
punto y coma al final de la instruccion. Actualmente se prefiere el uso
de const que explicita el tipo.
const double PI = 3.14159265358979;
El segundo uso de define permite definir macros. Su forma general es
la siguiente:
#define identificador(identificador, ..., identificador) cadena
cout<<CUADRADO(x+y)<<endl;
cout<<CUADRADOB(x+y)<<endl;
cout<<NORMA(x, y)<<endl;
return 0;
}
Los resultados producidos son:
9
9
49
19
5
En la definicion de CUADRADO, aparentemente, hay muchos parentesis;
parece m
as natural definir como se hace en CUADRADOB. Los dos
primeros resultados coinciden, lo cual es absolutamente normal. Sin
embargo, el tercero y el cuarto no coinciden, pero en apariencia deban
coincidir. La razon es la siguiente: cuando el compilador encuentra
CUADRADOB(x+y) , lo reemplaza por x+y*x+y , diferente de lo esperado,
es decir de (x+y)*(x+y). Ahora es comprensible el resultado 19. Algunos autores recomiendan, por seguridad, empezar y terminar la cadena
con parentesis, como en NORMA. Entonces CUADRADO quedara as:
#define CUADRADO(x) ((x)*(x))
8.6
Apuntadores a funciones
f (x) dx.
a
165
8. TEMAS VARIOS
8. TEMAS VARIOS
168
}
Este ejemplo muestra las principales caractersticas del uso de los apuntadores a funciones. En la definicion de la funcion trapecio, un par
ametro
es un apuntador a funcion. El identificador esta precedido de asterisco
y aparece entre parentesis: (*f). Adem
as estan el tipo devuelto por
la funcion y los par
ametros: double (*f)(double x). Esto implica
que trapecio se puede usar para cualquier funcion que devuelva un
n
umero doble precisi
on y que tenga un u
nico par
ametro tipo doble precision. Cuando se utiliza el apuntador dentro de trapecio para evaluar
la funcion en un valor especfico, tambien esta precedido de asterisco y
encerrado entre parentesis: (*f)(a).
8.7
Funciones en lnea
Cuando una funcion, por ejemplo la funcion main, llama a otra, hay
un peque
no incremento en el tiempo de ejecuci
on correspondiente al
llamado en s de la funcion y a la pasada de los par
ametros. Este incremento de tiempo se conoce como overhead, que se puede traducir por
gastos generales o sobrecosto. C++ permite utilizar funciones en lnea
cuyo objetivo es que el compilador coloque una copia de la funcion en
lnea en cada sitio del programa donde se utiliza la funcion. As, no hay
paso de par
ametros y se gana en eficiencia, pero usualmente el programa
ejecutable resulta m
as grande. Las funciones en lnea son aconsejables
para funciones peque
nas, de una o dos instrucciones.
El ejemplo siguiente tiene dos partes. En la primera se hace uso
de la funcion cosGrd, funcion com
un y corriente, que calcula el coseno,
cuando el
angulo esta dado en grados. En la segunda parte se hace uso
de una funcion en lnea con el mismo objetivo.
// coseno de un angulo en grados,
// SIN funciones en linea.
#include <math.h>
#include <iostream.h>
double cosGrd( double x);
//======================================
169
8. TEMAS VARIOS
int main()
{
double a;
cout<<"\n\n Calculo de cos(a), a en grados.\n\n";
cout<<" a = ";
cin>>a;
cout<<"\n\n cos("<<a<<") = "<<cosGrd(a);
return 0;
}
//======================================
double cosGrd( double x)
{
return cos(0.01745329251994*x);
}
8.8. ARGUMENTOS DE LA FUNCION
MAIN
8.8
Argumentos de la funci
on
main
caso1.dat
result
171
8. TEMAS VARIOS
Los par
ametros para main son argc y argv.
El primero es de tipo
entero y sirve para contar el n
umero de palabras (o cadenas) en la lnea
de comandos. El nombre mismo del programa se cuenta como una palabra. En el ejemplo prog28 caso1.dat result hay tres palabras. El
par
ametro argv es un arreglo de cadenas donde se almacenan las cadenas dadas en la lnea de comandos. El siguiente ejemplo muestra un
esquema de su uso.
// prog28
// Parametros en la linea de comandos,
// uso de argc, argv
#include...
int main( int argc, char *argv[])
{
FILE *archDat, *archRes;
if( argc != 3 ){
cout<<"ERROR: el llamado debe ser:\n"
<<"progr28 nombre_arch_datos nombre_arch_result"
<<endl;
exit(1);
}
archDat = fopen(argv[1], "r");
if( archDat == NULL ){
printf("\n\n Archivo inexistente.\n\n");
exit(1);
}
archRes = fopen(argv[2], "w");
if( archRes == NULL ){
printf("Nombre de archivo de resultados erroneo.\n");
exit(1);
}
...
172
8.8. ARGUMENTOS DE LA FUNCION
MAIN
fclose(archDat);
fclose(archRes);
return 0;
}
Como argv es un arreglo de cadenas, entonces empieza en el subndice
cero. Supongamos que el llamado se hace
prog28
caso1.dat
result
173
8. TEMAS VARIOS
174
Estructuras
Una estructura es un agrupamiento de variables, posiblemente de diferentes tipos, que se denomina con un solo nombre y constituye un nuevo
tipo de datos.
9.1
// parte real
// parte imaginaria
9. ESTRUCTURAS
z.pImag*w.pImag;
z.pImag*w.pReal;
parte imag. = %lf\n",
}
Una vez definida una estructura, esta puede servir para describir un
par
ametro de una funcion, para declarar arreglos cuyos elementos sean
estructuras, para declarar apuntadores, para asignar memoria din
amicamente,
para que una funcion devuelva una estructura.
El siguiente ejemplo usa la estructura complejo definida anteriormente. El programa lee en un archivo el valor de n. Asigna din
amicamente
176
memoria para n estructuras complejo, lee en el archivo n parejas de valores (correspondientes a la parte real y la parte imaginaria) y las guarda
en el arreglo de complejos, busca en el arreglo el complejo de mayor
norma y finalmente escribe el cuadrado de ese complejo.
// Estructuras pasadas como parametros,
// arreglos de estructuras,
// funciones que devuelven una estructura.
//-----------------------------------------------#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
//-----------------------------------------------struct complejo {
double pReal; // parte real
double pImag; // parte imaginaria
};
//-----------------------------------------------complejo prodCompl( complejo z1, complejo z2);
int flectXCompl(FILE *arch, complejo *x, int n);
double normaCompl(complejo x);
complejo complMaxNorma(complejo *x, int n);
//================================================
int main( void )
{
// Lee en un archivo n.
// Lee en el archivo n complejos. Para leer un
// complejo lee la parte real y la parte imaginaria.
// Busca el complejo de mayor norma y escribe su
// cuadrado.
complejo *z, w;
int n, resLect;
FILE *archDat;
char nombre[51];
printf("\n Nombre del archivo con los datos: ");
gets(nombre);
177
9. ESTRUCTURAS
}
//================================================
complejo prodCompl( complejo z1, complejo z2)
{
// producto de dos complejos
complejo z3;
z3.pReal = z1.pReal*z2.pReal z3.pImag = z1.pReal*z2.pImag +
178
z1.pImag*z2.pImag;
z1.pImag*z2.pReal;
return z3;
}
//-----------------------------------------------int flectXCompl(FILE *arch, complejo *x, int n)
{
// Lectura en un archivo de los primeros n
// elementos de un arreglo complejo x.
// Devuelve 1
//
0
//
//
-1
//
int i, res;
for(i=0; i< n; i++){
res = fscanf(arch, "%lf", &x[i].pReal);
if( feof(arch) ) return 0;
if( res <= 0 ) return -1;
res = fscanf(arch, "%lf", &x[i].pImag);
if( feof(arch) ) return 0;
if( res <= 0 ) return -1;
}
return 1;
}
//-----------------------------------------------complejo complMaxNorma(complejo *x, int n)
{
// Devuelve el complejo de maxima norma
// en el arreglo de complejos x.
double normaMax = 0.0, normai;
int i, imax = -1;
for( i=0; i < n; i++){
normai = normaCompl( x[i] );
if( normai > normaMax ){
179
9. ESTRUCTURAS
imax = i;
normaMax = normai;
}
}
return x[imax];
}
//-----------------------------------------------double normaCompl(complejo x)
{
// Norma del complejo x
return sqrt(x.pReal*x.pReal + x.pImag*x.pImag);
}
Una vez definida la estructura complejo, esta se puede usar de varias
maneras. En el programa anterior se observa:
Los par
ametros de las funciones pueden ser del tipo complejo:
funciones flectXCompl, normaCompl, complMaxNorma, prodCompl.
Las funciones pueden devolver un complejo: funciones prodCompl,
complMaxNorma.
La variable z en la funcion main es un apuntador a complejo. Un
par
ametro de la funcion flectXCompl es un apuntador a complejo.
En la funcion main, utilizando z, apuntador a complejo, se hace
una asignaci
on din
amica de memoria para n elementos tipo complejo.
En la funcion flectXCompl el segundo par
ametro, x, es un vector de elementos tipo complejo. Para el i-esimo elemento, el
complejo x[i], su parte real es x[i].pReal y su parte imaginaria
es x[i].pImag.
Cuando se tiene un apuntador a una estructura, si se quiere acceder
directamente a uno de sus campos, se usa el operador -> de la siguiente
manera: apuntador->campo.
A modo de ejemplo, la funcion normaCompl anterior, se reescribe a
continuaci
on utilizando -> .
180
double normaComplb(complejo x)
{
// Norma del complejo x
complejo *w;
w = &x;
return sqrt(w->pReal*w->pReal + w->pImag*w->pImag);
}
9.2
Un ejemplo tpico
//
//
//
//
//
//
//
//
apellidos
clase de documento de identidad
numero de doc. identidad
primera linea de la direccion
segunda linea de la direccion
ciudad y departamento
numero de telefono
direccion electronica: e-mail
// fecha de nacimiento
// fecha de ingreso
Ejercicios
Los ejercicios de este captulo se pueden hacer definiendo explcitamente
una estructura por medio de struct , o sin su uso. Haga o estudie las
181
9. ESTRUCTURAS
multiplicar,
restar,
dividir,
En todos los casos controle que numerador y denominador permanecen dentro de los rangos permitidos.
9.2 Un grafo se puede representar por una lista de vertices y una lista
de arcos. Una red es un grafo donde adicionalmente cada arco
tiene un valor (costo o distancia). Defina una estructura para su
manejo. Haga funciones para:
agregar un arco con costo,
quitar un arco,
modificar un costo,
182
10
Algunas funciones
elementales
En este captulo hay algunas funciones elementales que seran u
tiles especialmente para el manejo de matrices, en particular para la solucion
de sistemas de ecuaciones. Sean x, y vectores (cuando sea necesario se
consideran como matrices columna), , k escalares. La tabla siguiente
muestra el nombre de la funcion y su efecto. Se usa la misma convencion
de C, el signo igual indica asignaci
on.
producto xT y
1
Pn
2 2
dist2
||x y||2 =
i=1 (xi yi )
alfaX
x = x
xMasAlfaY x = x + y
xIglY
x=y
xIglAlfY
x = y
xIglK
x = k, es decir, xi = k i
intercXY
intercambio de x , y
maxX
maxi {xi }
maxXPos
maxi {xi } e indica la posicion
maxAbsX
maxi {|xi |}
maxAbsXPos maxi {|xi |} e indica la posicion
ordBurb
ordenar, de menor a mayor, los xi
prodXY
10.
10.1
C
odigo de algunas funciones
A continuaci
on se presenta el codigo en C (y algo de C++) de las funciones para vectores almacenados de manera consecutiva (sin salto).
Para vectores almacenados con salto, es decir, en x[0], x[salto], x[2*salto],
..., x[(n-1)*salto], esta el codigo completo de algunas de ellas. El
codigo de las demas se puede obtener en la pagina del autor. Actualmente la direccion es: www.matematicas.unal.edu.co/~hmora/. Si hay
reorganizacion de las paginas de la Universidad, sera necesario entrar a
la pagina de la Universidad www.unal.edu.co ir a Sede de Bogota, Facultad de Ciencias, Departamento de Matem
aticas y pagina del autor.
double prodXY(double *x, double *y, int n);
double prodXY(double *x, int saltox, double *y, int saltoy,
int n);
double dist2(double *x, double *y, int n);
double dist2(double *x, int saltox, double *y, int saltoy,
int n);
void alfaX(double alfa, double *x, int n);
void alfaX(double alfa, double *x, int salto, int n);
void xMasAlfaY(double *x, double alfa, double *y, int n);
void xMasAlfaY(double *x, int saltox, double alfa,
double *y, int saltoy, int n);
void xIglK(double *x, int n, double k);
void xIglK(double *x, int salto, int n, double k);
void xIglY(double *x, double *y, int n);
void xIglY(double *x, int saltox, double *y, int saltoy,
int n);
void xIglAlfY(double *x, double alfa, double *y, int n);
void xIglAlfY(double *x, int saltox, double alfa,
double *y, int saltoy, int n);
void intercXY(double *x, double *y, int n);
184
10.1. CODIGO
DE ALGUNAS FUNCIONES
10.
pxi = x;
pyi = y;
pxn = x + n;
while( pxi < pxn ){
xiyi = (*pxi++) - (*pyi++);
s += xiyi*xiyi;
}
return sqrt(s);
}
//--------------------------------------------------------void alfaX(double alfa, double *x, int n)
{
// x = alfa * x
double *pxi, *pxn;
pxi = x;
pxn = x + n;
while( pxi < pxn ) *pxi++ *= alfa;
}
//--------------------------------------------------------void xMasAlfaY(double *x, double alfa, double *y, int n)
{
// x = x + alfa * y
double *pxi, *pxn, *pyi;
pxi = x;
pyi = y;
pxn = x + n;
while( pxi < pxn ) *pxi++ += alfa*(*pyi++);
}
//--------------------------------------------------------void xIglK(double *x, int n, double k)
{
// x = k
186
10.1. CODIGO
DE ALGUNAS FUNCIONES
187
10.
pyi = y;
pxn = x + n;
while( pxi < pxn ){
t = *pxi;
*pxi++ = *pyi;
*pyi++ = t;
}
}
//--------------------------------------------------------double maxX(double *x, int n)
{
// maximo xi
double *pxi, *pxn, maxi = -1.0E100, xi;
pxi = x;
pxn = x + n;
while( pxi < pxn ){
xi = *pxi++;
if( xi > maxi ) maxi = xi;
}
return maxi;
}
//--------------------------------------------------------double maxXPos(double *x, int n, int &posi)
{
// maximo xi
// posi contendra la posicion del maximo
double *pxi, *pxn, maxi = -1.0E100, xi;
int i;
posi = -1;
pxi = x;
pxn = x + n;
i = 0;
while( pxi < pxn ){
xi = *pxi++;
188
10.1. CODIGO
DE ALGUNAS FUNCIONES
189
10.
10.2
}
else{
// saltox = 1; saltoy != 1
pxi = x;
pxn = x + n;
pyi = y;
while( pxi < pxn ){
xiyi = (*pxi++) - (*pyi);
s += xiyi*xiyi;
pyi += saltoy;
}
}
}
else{
if( saltoy == 1 ){
// saltox > 1; saltoy = 1
pyi = y;
pyn = y + n;
pxi = x;
while( pyi < pyn ){
xiyi = (*pxi) - (*pyi++);
s += xiyi*xiyi;
pxi += saltox;
}
}
else{
// saltox != 1; saltoy != 1
pxi = x;
pxn = x + n*saltox;
pyi = y;
while( pxi < pxn ){
xiyi = (*pxi) - (*pyi);
s += xiyi*xiyi;
pxi += saltox;
pyi += saltoy;
}
}
}
191
10.
return sqrt(s);
}
//--------------------------------------------------------void alfaX(double alfa, double *x, int salto, int n)
{
// x = alfa * x
// x en x[0], x[salto], x[2*salto], ..., x[(n-1)*salto]
double *pxi, *pxn;
if( salto == 1 ){
pxi = x;
pxn = x + n;
while( pxi < pxn ) *pxi++ *= alfa;
}
else{
pxi = x;
pxn = x + n*salto;
while( pxi < pxn ){
*pxi *= alfa;
pxi += salto;
}
}
}
//-----------------------------------------------void xMasAlfaY(double *x, int saltox, double alfa,
double *y, int saltoy, int n)
{
// x = x + alfa y
// x[0], x[saltox], x[2*saltox], ..., x[(n-1)*saltox]
// y[0], y[saltoy], y[2*saltoy], ..., y[(n-1)*saltoy]
// uso de apuntadores
double *pxi, *pyi, *pxn, *pyn;
if( n < 0 ){
printf("xMasAlfaY: n negativo\n");
192
return;
}
if( n==0 ) return;
if( saltox == 1 ){
if( saltoy == 1 ){
// saltox = saltoy = 1
pxi = x;
pxn = x + n;
pyi = y;
while( pxi < pxn ) *pxi++ += alfa*(*pyi++);
}
else{
// saltox = 1; saltoy != 1
pxi = x;
pxn = x + n;
pyi = y;
while( pxi < pxn ){
*pxi++ += alfa*(*pyi);
pyi += saltoy;
}
}
}
else{
if( saltoy == 1 ){
// saltox > 1; saltoy = 1
pyi = y;
pyn = y + n;
pxi = x;
while( pyi < pyn ){
*pxi += alfa*(*pyi++);
pxi += saltox;
}
}
else{
// saltox != 1; saltoy != 1
pxi = x;
pxn = x + n*saltox;
193
10.
pyi = y;
while( pxi < pxn ){
*pxi += alfa*(*pyi);
pxi += saltox;
pyi += saltoy;
}
}
}
}
10.3
M
etodo burbuja
Para ordenar un arreglo, supongamos en orden creciente, existen numerosos metodos. Uno de ellos es el metodo burbuja, el cual cuenta con
una buena combinacion de sencillez y eficiencia para arreglos no muy
grandes.
Supongamos que se tiene un vector x Rn . En una primera iteracion (primera pasada) se mira si x1 , x2 estan ordenados; si no lo
estan se intercambian. Despues se mira x2 y x3 ; si no estan ordenados
se intercambian. Despues se mira x3 y x4 ; si no estan ordenados se intercambian. Finalmente, si xn1 y xn no estan ordenados, se intercambian.
Por convencion, xi indica el i-esimo elemento de x despues de la u
ltima
modificaci
on. Despues de esta primera pasada el mayor elemento queda
en la u
ltima posicion.
En una segunda pasada se hace un proceso semejante, pero la u
ltima
pareja que se compara es xn2 , xn1 . Al final de esta segunda pasada
los dos u
ltimos elementos estan bien ordenados (en sus posiciones definitivas).
En una tercera pasada se repite el proceso, pero la u
ltima pareja
que se compara es xn3 , xn2 . Al final de esta tercera pasada los tres
u
ltimos elementos estan bien ordenados.
Si en una pasada no hay intercambios, el vector esta ordenado.
Considere
x = (6, 1, 14, 0, 1, 2)
10.3. METODO
BURBUJA
10.
196
10.3. METODO
BURBUJA
Ejercicios
Los ejercicios de este captulo no estan enfocados directamente a los
temas tratados en el; m
as bien, corresponden a varios temas y aparecen
aqu por tratarse del u
ltimo captulo sobre C.
10.1 Haga un programa que escriba en un archivo todas las combinaciones de enteros entre 1 y n.
10.2 Elabore un programa que escriba en un archivo todas las permutaciones de los enteros entre 1 y n.
10.3 Dado un entero n > 0 y 2n enteros u1 v1 , u2 v2 , ..., un vn ,
escriba todas la n-uplas (i1 , i2 , ..., in ) tales que uk ik vk para
todo k.
10.4 Utilice el ejercicio anterior para resolver por la fuerza bruta (estudio de todas las posibilidades) el problema del morral con cotas
inferiores y superiores. Sean n un entero positivo; C, p1 , p2 , ...,
pn , b1 , b2 , ..., bn n
umeros positivos; u1 v1 , u2 v2 , ..., un vn
enteros positivos. Encontrar enteros x1 , x2 , ..., xn para resolver el
siguiente problema de maximizaci
on con restricciones:
max b1 x1 + b2 x2 + + bn xn
p 1 x 1 + p 2 x 2 + + pn x n C
ui xi vi , i = 1, 2, ..., n.
197
10.
198
11
Soluci
on de sistemas
lineales
Uno de los problemas numericos m
as frecuentes, o tal vez el m
as frecuente, consiste en resolver un sistema de ecuaciones de la forma
Ax = b
(11.1)
11.1
Notaci
on
11.
DE SISTEMAS LINEALES
SOLUCION
usar
a la notaci
on de Matlab y Scilab.
parte de un vector: x(5 : 7) = (x5 , x6 , x7 ),
fila i-esima: Ai = A(i, :),
columna j-esima: Aj = A(:, j),
parte de la fila i-esima: A(i, 1 : 4) = [ ai1 ai2 ai3 ai4 ]
parte de la columna j-esima: A(2 : 4, j) = [ a2j a3j a4j ]T
submatriz: A(3 : 6, 2 : 5) .
Supongamos que se tiene una funcion, llamada prodEsc, que calcula el
producto escalar entre dos vectores (del mismo tama
no), o entre dos filas
de una matriz, o entre dos columnas, o entre una fila y una columna.
Supongamos que se tiene una funcion, llamada xMasAlfaY, que a
un vector le suma veces otro vector. Los valores del primer vector
desaparecen y quedan los correspondientes al resultado
xMasAlfaY(u, 3.5, v)
u u + 3.5v
11.2
M
etodos ingenuos
b1 a12 a13
a11 b1 a13
det b2 a22 a23
det a21 b2 a23
b3 a32 a33
a31 b3 a33
x1 =
, x2 =
,
det(A)
det(A)
200
11.2. METODOS
INGENUOS
a11 a12 b1
det a21 a22 b2
a31 a32 b3
x3 =
det(A)
Supongamos ahora que cada determinante se calcula por medio de cofactores. Este calculo se puede hacer utilizando cualquier fila o cualquier
columna; por ejemplo, si A es 3 3, utilizando la primera fila,
a22 a23
a21 a23
a21 a22
det(A) = a11 det
a12 det
+ a13 det
.
a32 a33
a31 a33
a31 a32
En general, sea Mij la matriz (n 1) (n 1) obtenida al suprimir de
A la fila i y la columna j. Si se calcula det(A) utilizando la primera fila,
det(A) = a11 det(M11 ) a12 det(M12 ) + + (1)(1+n) a1n det(M1n ).
Sea n el n
umero de multiplicaciones necesarias para calcular, por cofactores, el determinante de una matriz de orden n. La formula anterior
nos indica que
n > nn1 .
Como a su vez n1 > (n 1)n2 y n2 > (n 2)n3 , ..., entonces
n > n(n 1)(n 2) 2 = n(n 1)(n 2) 2,
n > n! .
11.
11.3
DE SISTEMAS LINEALES
SOLUCION
Sistema diagonal
El caso m
as sencillo de (11.1) corresponde a una matriz diagonal. Para
matrices triangulares, en particular para las diagonales, el determinante
es el producto de los n elementos diagonales. Entonces una matriz triangular es invertible si y solamente si todos los elementos diagonales son
diferentes de cero.
La solucion de un sistema diagonal se obtiene mediante
xi =
bi
, i = 1, ..., n.
aii
(11.2)
11.4
De la cuarta ecuaci
on, se deduce que x4 = 5.6/2.8 = 2. A partir de
la tercera ecuaci
on
45x3 = 203 (79x4 )
203 (79x4 )
x3 =
45
Reemplazando x4 por su valor, se obtiene x3 = 1. A partir de la
segunda ecuaci
on
0.25x2 = 11 (2.5x3 + 4.25x4 )
11 (2.5x3 + 4.25x4 )
x3 =
0.25
202
x3 =
4
Reemplazando x2 , x3 y x4 por sus valores, se obtiene x1 = 1.
En general, para resolver un sistema triangular, primero se calcula
xn = bn /ann . Con este valor se puede calcular xn1 , y as sucesivamente.
Conocidos los valores xi+1 , xi+2 , ..., xn , la ecuaci
on i-esima es
aii xi + ai,i+1 xi+1 + ai,i+2 xi+2 + ... + ain xn = bi ,
aii xi + prodEsc(A(i, i + 1 : n), x(i + 1 : n)) = bi ,
bi prodEsc(A(i, i + 1 : n), x(i + 1 : n))
xi =
aii
Como se supone que A es regular (invertible o no singular), los elementos diagonales son no nulos y no se presentan problemas al efectuar la
divisi
on.
El esquema del algoritmo es el siguiente:
xn = bn /ann
para i = n 1, ..., 1
xi = (bi prodEsc(A(i, i + 1 : n), x(i + 1 : n)))/aii
fin-para
Si los subndices de A y de x van desde 0 hasta n1, entonces el esquema
del algoritmo queda as:
xn1 = bn1 /an1,n1
para i = n 2, ..., 0
xi = (bi prodEsc(A(i, i + 1 : n 1), x(i + 1 : n 1)))/aii
fin-para
11.4.1
N
umero de operaciones
11.
DE SISTEMAS LINEALES
SOLUCION
Multiplicaciones
y divisiones
calculo de xn
calculo de xn1
calculo de xn2
n2
n1
...
calculo de x2
calculo de x1
Total
n1
n2 /2 n/2
n2 /2 + n/2
N
umero total de operaciones de punto flotante: n2 .
11.4.2
Implementaci
on en C
11.
DE SISTEMAS LINEALES
SOLUCION
11.5
i1
X
aij xj
j=1
aii
(11.3)
11.6
M
etodo de Gauss
(11.4)
equivalente al primero, tal que A sea triangular superior. Que los sistemas sean equivalentes quiere decir que la solucion de Ax = b es exactamente la misma solucion de A x = b . La segunda parte es simplemente
la solucion del sistema triangular superior.
Para una matriz, con ndices entre 1 y n, el esquema de triangularizaci
on se puede escribir as:
206
11.6. METODO
DE GAUSS
para k = 1, ..., n 1
buscar ceros en la columna k, por debajo de la diagonal.
fin-para k
Afinando un poco m
as:
para k = 1, ..., n 1
para i = k + 1, ..., n
buscar ceros en la posicion de aik .
fin-para i
fin-para k
Ejemplo 11.2. Consideremos el siguiente sistema de ecuaciones:
4x1 + 3x2 2x3 + x4 =
+ x3 + x4 = 8
4
3
2
5
3 2
2
1
3
1
0
1
x1
1
x2
5
2 x3
x4
1
4
8
=
7
8
Es usual trabajar u
nicamente con los n
umeros, olvidando temporalmente
los xi . M
as a
un, se acostumbra trabajar con una matriz ampliada,
resultado de pegar a la derecha de A el vector b.
4
3
2
5
3 2
2
1
3
1
0
1
1
5
2
1
4
8
7
8
Inicialmente hay que buscar ceros en la primera columna. Para buscar cero en la posicion (2,1), fila 2 y columna 1, se hace la siguiente
operacion:
fila2nueva fila2vieja (3/4)fila1
207
11.
DE SISTEMAS LINEALES
SOLUCION
Para hacer m
as sencilla la escritura la expresi
on anterior se escribir
a
simplemente:
fila2 fila2 (3/4)fila1
4
3
-2
1
4
0
-0.25
2.5
4.25
-11
-2
3
1
2
-7
-5
0
1
1
-8
0
-5
3
-0.25
4.5
0
-2
2.5
0
1
4
-11
-5
-8
1
4.25
2.5
1
4
0
0
0
3
-0.25
4.5
3.75
-2
2.5
0
-1.5
1
4.25
2.5
2.25
4
-11
-5
-3
Ahora hay que buscar ceros en la segunda columna. Para buscar cero
en la posicion (3,2) se hace la siguiente operacion:
fila3 fila3 (4.5/(0.25))fila2
4
0
0
0
3
-0.25
0
3.75
-2
2.5
45
-1.5
1
4.25
79
2.25
4
-11
-203
-3
4
0
0
0
3
-0.25
0
0
-2
2.5
45
36
208
1
4.25
79
66
4
-11
-203
-168
11.6. METODO
DE GAUSS
4
0
0
0
3
-0.25
0
0
-2
2.5
45
0
1
4.25
79
2.8
-11
-203
-5.6
bi = bi lik bk
11.
DE SISTEMAS LINEALES
SOLUCION
para k = 1, ..., n 1
para i = k + 1, ..., n
lik = aik /akk , aik = 0
A(i, k + 1 : n) = A(i, k + 1 : n)likA(k, k + 1 : n)
bi = bi likbk
fin-para i
fin-para k
para k = 1, ..., n 1
para i = k + 1, ..., n
si |akk | ent
buscar m, k + 1 m n, tal que |amk | >
si no fue posible ent salir
intercambiar(A(k, k : n), A(m, k : n))
intercambiar(bk , bm )
fin-si
lik = aik /akk , aik = 0
A(i, k + 1 : n) = A(i, k + 1 : n)likA(k, k + 1 : n)
bi = bi likbk
fin-para i
fin-para k
si |ann | ent salir
11.6. METODO
DE GAUSS
para k = 1, ..., n
para i = k + 1, ..., n
si |akk | ent
buscar m, k + 1 m n, tal que |amk | >
si no fue posible ent salir
intercambiar(A(k, k : n), A(m, k : n))
intercambiar(bk , bm )
fin-si
lik = aik /akk , aik = 0
A(i, k + 1 : n) = A(i, k + 1 : n)likA(k, k + 1 : n)
bi = bi likbk
fin-para i
fin-para k
El anterior algoritmo se adapta facilmente al caso de los subndices,
variando entre 0 y n 1.
para k = 0, ..., n 1
para i = k + 1, ..., n 1
si |akk | ent
buscar m, k + 1 m n 1, tal que |amk | >
si no fue posible ent salir
intercambiar(A(k, k : n 1), A(m, k : n 1))
intercambiar(bk , bm )
fin-si
lik = aik /akk , aik = 0
A(i, k + 1 : n 1) = A(i, k + 1 : n 1)likA(k, k + 1 : n 1)
bi = bi likbk
fin-para i
fin-para k
11.6.1
N
umero de operaciones
11.
DE SISTEMAS LINEALES
SOLUCION
n
n
n
(n 1)n
Multiplicaciones
y divisiones
n+1
n+1
n+1
(n 1)(n + 1)
en la columna 1
en la columna 2
en la columna 3
(n 1)n
(n 2)(n 1)
(n 3)(n 2)
Multiplicaciones
y divisiones
(n 1)(n + 1)
(n 2)n
(n 3)(n 1)
2(3)
1(2)
2(4)
1(3)
en la columna n 2
en la columna n 1
i2 =
i=1
m(m + 1)(2m + 1)
N
umero de sumas y restas:
n1
X
i=1
i(i + 1) =
n1
X
(i2 + i) =
i=1
212
n3 n
n3
3
3
3
11.6. METODO
DE GAUSS
N
umero de multiplicaciones y divisiones:
n1
X
i(i + 2) =
n1
X
(i2 + 2i) =
i=1
i=1
n3
n3 n2 5n
+
3
2
6
3
N
umero de operaciones:
n3 n n3 n2 5n
2n3 n2 7n
2n3
+
+
=
+
3
3
3
2
6
3
2
6
3
Proceso completo
El n
umero de operaciones para las dos partes, triangularizacion y solucion
del sistema triangular, es
2n3 3n2 7n
2n3
+
3
2
6
3
Para valores grandes de n el n
umero de operaciones de la solucion del
sistema triangular es despreciable con respecto al n
umero de operaciones
de la triangularizacion.
11.6.2
Implementaci
on en C
La implementaci
on hace uso de la funcion xMasAlfaY, definida en el
captulo 10, que adiciona a un vector un m
ultiplo de otro vector:
u u + 3.5 v
Su prototipo es:
void xMasAlfaY(double *x, double alfa, double *y, int n);
La siguiente implementaci
on en C es casi la traduccion a C del algoritmo
presentado. Hay algunas variables adicionales para no tener que efectuar
varias veces la misma operacion, por ejemplo, n + 1.
int gauss1( double *a, double *b, double *x, int n,
double eps)
{
// Metodo de Gauss SIN PIVOTEO parcial
// para resolver A x = b
213
11.
DE SISTEMAS LINEALES
SOLUCION
214
11.7. FACTORIZACION
LU
return 1;
}
11.7
Factorizaci
on LU
4
0
U =
0
0
3
-0.25
0
0
-2
2.5
45
0
1
4.25
79
2.8
L=
..
.
0
0
0
..
.
l21
l31
..
.
0
1
l32
0
0
1
0.75
L=
-0.5
-1.25
0
1
-18
-15
0
0
1
0.8
0
0
0
1
11.
DE SISTEMAS LINEALES
SOLUCION
entes.
Ax = b,
LU x = b,
Ly = b,
donde
U x = y.
En resumen:
Resolver Ly = b para obtener y.
Resolver U x = y para obtener x.
Ejemplo 11.3. Resolver
4x1 + 3x2 2x3 + x4 =
Al resolver
0.75
-0.5
-1.25
se obtiene y =
4
0
0
0
+ x3 + x4 =
0
1
-18
-15
0
0
1
0.8
8 24 451 11.2
3
-0.25
0
0
0
y1
y2
0
0 y3
y4
1
8
30
=
15
2
. Al resolver
x1
1
x2
4.25
x3
79
x4
2.8
-2
2.5
45
0
T
1 2 3 4
T
8.0
24.0
=
451.0
11.2
11.8. METODO
DE GAUSS CON PIVOTEO PARCIAL
La factorizaci
on A = LU es un subproducto gratuito del metodo
de Gauss; gratuito en tiempo y en requerimientos de memoria. No se
requiere tiempo adicional puesto que el calculo de los lik se hace dentro
del metodo de Gauss. Tampoco se requiere memoria adicional puesto
que los valores lik se pueden ir almacenando en A en el sitio de aik que
justamente vale cero.
En el algoritmo hay u
nicamente un peque
no cambio:
..
.
lik = aik /akk
aik = lik
A(i, k + 1 : n 1) = A(i, k + 1 : n 1)likA(k, k + 1 : n 1)
bi = bi likbk
..
.
En la matriz final A estara la
u11
l21
L = l31
..
.
ln1
informaci
on indispensable de L y de U .
..
..
.
.
ln2 ln3 unn
4
3
-2
1
0.75
-0.25
2.5
4.25
-0.5
-18
45
79
-1.25
-15
0.8
2.8
11.8
de L y de U es:
M
etodo de Gauss con pivoteo parcial
En el metodo de Gauss cl
asico, u
nicamente se intercambian filas cuando
el pivote, akk , es nulo o casi nulo. Como el pivote (el elemento akk en la
iteraci
on k) va a ser divisor para el calculo de lik, y como el error de
redondeo o de truncamiento se hace mayor cuando el divisor es cercano
a cero, entonces es muy conveniente buscar que el pivote sea grande en
217
11.
DE SISTEMAS LINEALES
SOLUCION
valor absoluto. Es decir, hay que evitar los pivotes que sin ser nulos son
cercanos a cero.
En el metodo de Gauss con pivoteo parcial se busca el elemento
dominante, o sea, el de mayor valor absoluto en la columna k de la
diagonal hacia abajo, es decir, entre los valores |akk |, |ak+1,k |, |ak+2,k |,
..., |akn |, y se intercambian la fila k y la fila del valor dominante. Esto
mejora notablemente, en muchos casos, la precisi
on de la solucion final
obtenida.
Se dice que el pivoteo es total si en la iteraci
on k se busca el mayor
valor de {|aij | : k i, j n}. En este caso es necesario intercambiar dos
filas y dos columnas. As se consigue mejorar un poco la precisi
on con
respecto al metodo de pivoteo parcial, pero a un costo nada despreciable.
En el metodo de pivoteo parcial se busca el mayor valor entre n k + 1
valores. En el pivoteo total se busca entre (n k + 1)2 valores. Si se
busca, de manera secuencial, el m
aximo entre p elementos, entonces
hay que hacer, adem
as de operaciones de asignaci
on, por lo menos p
1 comparaciones. Estas operaciones no son de punto flotante y son
m
as r
apidas que ellas, pero para n grande, el tiempo utilizado no es
despreciable. En el metodo de pivoteo parcial hay aproximadamente
n2 /2 comparaciones, en el pivoteo total aproximadamente n3 /6. En
resumen, con el pivoteo total se gana un poco de precisi
on, pero se gasta
bastante m
as tiempo. El balance aconseja preferir el pivoteo parcial.
Ejemplo 11.4. Resolver por el metodo de Gauss con pivoteo parcial el
siguiente sistema de ecuaciones.
4x1 + 3x2 2x3 + x4 =
-2
-5
+ x3 + x4 = 8
3
2
3
0
-2
1
1
1
1
5
2
1
4
-8
-7
-8
11.8. METODO
DE GAUSS CON PIVOTEO PARCIAL
-5
0
3
2
-2
3
4
3
1
1
1
-2
1
5
2
1
-8
-8
-7
4
-5
0
1
1
-8
0
2
1.6
5.6
-12.8
0
3
0.6
1.6
-3.8
0
3
-1.2
1.8
-2.4
El valor dominante de A(2 : 4, 2) es 3
Entonces se intercambian las filas 2 y
-5
0
1
0
3
0.6
0
2
1.6
0
3
-1.2
-5
0
0
1
-8
1.6
-3.8
5.6
-12.8
1.8
-2.4
0
1
1
-8
3
0.6
1.6
-3.8
0
1.2
4.5333
-10.2667
0
-1.8
0.2
1.4
-5
0
1
1
0
3
0.6
1.6
0
0
-1.8
0.2
0
0
1.2
4.5333
-8
-3.8
1.4
-10.2667
-5
0
1
1
-8
0
3
0.6
1.6
-3.8
0
0
-1.8
0.2
1.4
0
0
0
4.6667
-9.3333
219
11.
DE SISTEMAS LINEALES
SOLUCION
x2 +
0.6867
x3 = .8338
0.7290
1.0000
1.3310
0.8100
1.0000
1.2100
0.9000
1.0000
1.1000
0.6867
0.8338
1.0000
0.9000
-0.2345
-0.5432
0.6867
-0.1081
-0.2538
0.7290
0.8100
0.0000
-0.1111
0.0000
0.0000
0.9000
-0.2345
0.0244
0.6867
-0.1081
0.0078
0.7290
0.0000
0.0000
11.8. METODO
DE GAUSS CON PIVOTEO PARCIAL
kx2 x k.
Si kx1 x k < kx2 x k, entonces x1 es, entre x1 y x2 , la mejor aproximacion de x . Cuando no se conoce x , entonces se utiliza la norma del
vector residuo o resto, r = Ax b. Si x es la solucion exacta, entonces
la norma de su resto vale cero. Entonces hay que comparar
kAx1 bk ,
kAx2 bk.
kx x k = 0.0202 .
0.7290
0.8100
0.9000
0.6867
1.0000
1.0000
1.0000
0.8338
1.3310
1.2100
1.1000
1.0000
Intercambio de las filas
1.3310
1.0000
0.7290
1 y 3.
1.3310
0.0000
0.0000
2 y 3.
1.2100
1.0000
0.8100
1.1000
1.0000
0.9000
1.0000
0.8338
0.6867
1.3310
1.2100
1.1000
1.0000
0.0000
0.0909
0.1736
0.0825
0.0000
0.1473
0.2975
0.1390
1.2100
0.1473
0.0909
1.1000
0.2975
0.1736
1.3310
1.2100
0.0000
0.1473
0.0000
0.0000
1.0000
0.1390
0.0825
1.1000
0.2975
-0.0100
1.0000
0.1390
-0.0033
221
11.
DE SISTEMAS LINEALES
SOLUCION
kx x k = 0.0053 .
Se observa que para este ejemplo la norma del residuo es del mismo orden de magnitud que la norma del residuo correspondiente a la solucion
obtenida sin pivoteo, aunque algo mayor. La comparacion directa con
la solucion exacta favorece notablemente al metodo de pivoteo parcial:
0.0053 y 0.0202, relaci
on de 1 a 4 aproximadamente. Adem
as, visualmente se observa la mejor calidad de la solucion obtenida con pivoteo.
A continuaci
on aparece una versi
on de la funcion que implementa el
metodo de Gauss con pivoteo parcial.
int gausspp( double *a, double *b, int n, double eps)
{
// Metodo de Gauss CON PIVOTEO parcial
// para resolver A x = b.
// Intercambio real de las filas.
// A almacenada en un arreglo unidimensional,
// Aij esta en a[i*n+j].
// Devuelve 1
//
0
//
-1
si se resolvio el sistema.
si la matriz es singular o casi.
si n es inadecuado
b.
LU =PA
11.9. FACTORIZACION
// triangularizacion
for( k = 0; k < n_1; k++){
kk = k*n1;
aamk = maxAbsXPos( &a[kk], n, n-k, m0);
if( aamk <= eps ) return 0;
if( m0 != 0 ){
m = k+m0;
intercXY( &a[kk], &a[m*n+k], n-k);
t = b[k]; b[k] = b[m]; b[m] = t;
}
for( i = k+1; i < n; i++){
// anular Aik
ik = i*n + k;
lik = a[ik]/a[kk];
xMasAlfaY( &a[ik+1], -lik, &a[kk+1], n_1-k);
b[i] -= lik*b[k];
a[ik] = 0.0;
}
}
if( fabs(a[n*n-1]) <= eps) return 0;
solTrSup(a, b, n, eps);
return 1;
}
11.9
Factorizaci
on LU =PA
11.
DE SISTEMAS LINEALES
SOLUCION
0
1
0
0
P =
0
0
1
0
la matriz
0
0
1
0
0
1
.
0
0
De la misma forma que en la factorizacion LU , los valores lik se almacenan en el sitio donde se anula el valor aik . El vector p inicialmente
es (1, 2, 3, ..., n). A medida que se intercambian las filas de la matriz, se
intercambian las componentes de p.
Ejemplo 11.5. Obtener la factorizacion LU
4
3
-2
3
2
1
A=
-2
3
1
-5
0
1
= P A, donde
1
5
.
2
1
-5
0
1
1
3
2
1
5
.
p = (4, 2, 3, 1),
-2
3
1
2
4
3 -2
1
224
LU =PA
11.9. FACTORIZACION
-5
-0.6
0.4
-0.8
1
1.6
0.6
-1.2
1
5.6
.
1.6
1.8
-5
0
1
1
0.4
3
0.6
1.6
.
p = (4, 3, 2, 1),
-0.6
2
1.6
5.6
-0.8
3 -1.2
1.8
-5
0
1
1
0.4
3
0.6
1.6
.
-0.6
0.6667
1.2
4.5333
-0.8
1
-1.8
0.2
-5
0
1
0.4
3
0.6
p = (4, 3, 1, 2),
-0.8
1
-1.8
-0.6
0.6667
1.2
3 y 4.
1.6
.
0.2
4.5333
-5
0
1
1
0.4
3
0.6
1.6
.
-0.8
1
-1.8
0.2
-0.6
0.6667 -0.6667
4.6667
En esta u
ltima matriz y en el arreglo p esta toda la informaci
on necesaria
para obtener L, U , P . Entonces:
1
0
0
0
0.4
1
0
0
.
L=
-0.8
1
1
0
-0.6
0.6667 -0.6667
1
225
11.
DE SISTEMAS LINEALES
SOLUCION
-5
0
U =
0
0
0
0
P =
1
0
0
3
0
0
1.6
.
0.2
4.6667
1
0.6
-1.8
0
0
0
0
1
1
0
.
0
0
0
1
0
0
-8
-7
z = Pb =
4
-8
-8
-3.8
Ly = z , entonces y =
1.4
-9.3333
1
0
U x = y , entonces x =
-1
-2
226
METODO
DE CHOLESKY
11.10.
11.10
M
etodo de Cholesky
11.10.1
x Rn , x 6= 0.
(11.5)
xT Ax =
x1 x2 . . .
x1 x2 . . .
n
n X
X
x1
a11 a12 . . . a1n
a21 a22 . . . a2n x2
xn
...
xn
an1 an2 . . . ann
xn
aij xi xj .
i=1 j=i
Si A es simetrica,
xT Ax =
n
X
i=1
aii x2i + 2
n1
X
n
X
aij xi xj .
i=1 j=i+1
11.
DE SISTEMAS LINEALES
SOLUCION
1 2
2 5
A =
1 2
2 4
A =
1 2
2 3
1 2
3 4
11.10.
METODO
DE CHOLESKY
11.10.2
Factorizaci
on de Cholesky
11.
DE SISTEMAS LINEALES
SOLUCION
La matriz identidad se puede escribir como I = I T I, siendo I triangular superior invertible. Luego existe la factorizacion de Cholesky para
la matriz identidad.
Si existe la factorizacion de Cholesky de una matriz, al ser U y U T
invertibles, entonces A debe ser invertible. Luego la matriz nula no tiene
factorizaci
on de Cholesky.
Sea
A=
1 2
2 5
Entonces
u11 0
u12 u22
u11 u12
0 u22
1 2
2 5
u211 = 1
u11 u12 = 2,
u212
+ u222 = 5
Se deduce que
u11 = 1
u12 = 2,
u22 = 1,
1 2
U =
.
0 1
Entonces existe la factorizacion de Cholesky de A.
Cuando se calcul
o u11 se hubiera podido tomar u11 = 1 y se hubiera
podido obtener otra matriz U . Se puede demostrar que si se escogen
los elementos diagonales uii positivos, entonces la factorizacion, cuando
existe, es u
nica.
Sea
A=
1 2
2 4
230
11.10.
METODO
DE CHOLESKY
Entonces
u11 0
u12 u22
u11 u12
0 u22
1 2
2 4
u211 = 1
u11 u12 = 2,
u212
+ u222 = 4
Se deduce que
u11 = 1
u12 = 2,
u22 = 0,
1 2
U =
.
0 0
Entonces, aunque existe U tal que A = U T U , sin embargo no existe la
factorizaci
on de Cholesky de A ya que U no es invertible.
Sea
A=
1 2
2 3
Entonces
u11 0
u12 u22
u11 u12
0 u22
1 2
2 3
u211 = 1
u11 u12 = 2,
u212
+ u222 = 3
Se deduce que
u11 = 1
u12 = 2,
u222 = 1.
Entonces no existe la factorizaci
on de Cholesky de A.
231
DE SISTEMAS LINEALES
SOLUCION
11.
En el caso
u11
..
.
u1k
..
.
u1j
..
.
u1n
general,
ukk
ukj ujj
ukn ujn
..
..
ujj ujn
..
.
unn
unn
Luego
u11 =
a11 .
(11.6)
a1j
,
j = 2, ..., n.
(11.7)
u11
Al hacer el producto de la fila 2 de U T por la columna 2 de U , se puede
calcular u22 . Al hacer el producto de la fila 2 de U T por la columna j de
U , se puede calcular u2j . Se observa que el calculo de los elementos de
U se hace fila por fila. Supongamos ahora que se conocen los elementos
de las filas 1, 2, ..., k 1 de U y se desea calcular los elementos de la
fila k de U . El producto de la fila k de U T por la columna k de U da:
u1j =
k
X
u2ik = akk
i=1
k1
X
i=1
Luego
ukk
v
u
u
= ta
kk
k1
X
u2ik ,
i=1
232
k = 2, ..., n.
(11.8)
11.10.
METODO
DE CHOLESKY
i=1
Luego
ukj =
akj
k1
X
uik uij
i=1
ukk
k = 2, ..., n, j = k + 1, ..., n.
(11.9)
16 12
8 16
12
18 6
9
.
A =
8 6
5 10
16
9 10
46
u11 = 16 = 4
12
= 3
4
8
=2
u13 =
4
16
u14 =
= 4
4
p
u22 = 18 (3)2 = 3
u12 =
6 (3)(2)
=0
3
9 (3)(4)
u24 =
= 1
3
p
u33 = 5 (22 + 02 ) = 1
u23 =
u34 =
10 ( 2(4) + 0(1) )
= 2
1
233
11.
u44 =
Entonces,
DE SISTEMAS LINEALES
SOLUCION
p
46 ( (4)2 + (1)2 + (2)2 ) = 5 .
4 3 2 4
0
3 0 1
.
=
0
0 1 2
0
0 0
5
La factorizaci
on de Cholesky no existe cuando en la formula 11.8 la
cantidad dentro del radical es negativa o nula. Utilizando el producto
escalar, las formulas 11.8 y 11.9 se pueden reescribir as:
t = akk prodEsc( U (1 : k 1, k) , U (1 : k 1, k) ),
t,
ukk =
akj prodEsc( U (1 : k 1, k) , U (1 : k 1, j) )
ukj =
ukk
Para ahorrar espacio de memoria, los valores ukk y ukj se pueden almacenar sobre los antiguos valores de akk y akj . O sea, al empezar
el algoritmo se tiene la matriz A. Al finalizar, en la parte triangular
superior del espacio ocupado por A estara U .
t = akk prodEsc( A(1 : k 1, k) , A(1 : k 1, k) ),(11.10)
akk =
t,
(11.11)
akj prodEsc( A(1 : k 1, k) , A(1 : k 1, j) )
akj =
(11.12)
akk
El siguiente es el esquema del algoritmo para la factorizaci
on de Cholesky.
Si acaba normalmente, la matriz A es definida positiva. Si en alg
un momento t , entonces A no es definida positiva.
datos: A,
para k = 1, ..., n
calculo de t seg
un (11.10)
si t
ent salir
akk = t
para j = k + 1, ..., n
calculo de akj seg
un (11.12)
fin-para j
fin-para k
234
11.10.
METODO
DE CHOLESKY
La siguiente es la implementaci
on en C, casi la traduccion literal,
del algoritmo anterior. Obviamente los subndices de A varan entre 0 y
n 1.
int factChol(double *a, int n, double eps)
{
// Factorizacion de Cholesky de la matriz simetrica A
// almacenada por filas en el arreglo a.
// A = Ut U, U es triangular sup., invertible.
// Devuelve 0 si A no es definida positiva.
//
1 si A es definida positiva
//
en este caso U estara en
//
la parte triangular superior de A.
// Solamente se trabaja con la parte superior de A.
int j, k, n1, kk, kj;
double t;
n1 = n+1;
for( k = 0; k < n; k++){
kk = k*n1;
t = a[kk] - prodXY( &a[k], n, &a[k], n, k);
if( t <= eps ) return 0;
a[kk] = sqrt(t);
for( j = k+1; j < n; j++){
kj = kk + j-k;
a[kj] = (a[kj]-prodXY(&a[k], n, &a[j], n, k))/
a[kk];
}
}
return 1;
}
11.10.3
N
umero de operaciones de la factorizaci
on
DE SISTEMAS LINEALES
SOLUCION
11.
Sumas y restas
calculo
calculo
calculo
calculo
calculo
calculo
...
calculo
de
de
de
de
de
de
u11
u12
u1n
u22
u23
u2n
0
0
0
1
1
1
de unn
Multiplicaciones,
divisiones y races
1
1
1
2
2
2
n1
Sumas y restas
Multiplicaciones,
divisiones y races
n(1)
(n 1)2
(n 2)3
calculo
calculo
calculo
...
calculo
de U1
de U2
de U3
n(0)
(n 1)1
(n 2)2
de Un
1(n 1)
1(n)
N
umero de sumas y restas:
n1
X
i=1
(n i)i =
n3 n
n3
.
6
6
N
umero de multiplicaciones, divisiones y races:
n
X
i=1
(n + 1 i)i =
n3
n3 n2 n
+
+
.
6
2
3
6
N
umero total de operaciones:
n3 n2 n
n3
+
+
.
3
2
6
3
236
11.10.
11.10.4
METODO
DE CHOLESKY
Soluci
on del sistema
U T y = b,
(11.13)
resolver
U x = y.
(11.14)
Resolver cada uno de los dos sistemas es muy facil. El primero es triangular inferior, el segundo triangular superior. El n
umero total de
operaciones para resolver el sistema esta dado por la factorizacion m
as
la solucion de dos sistemas triangulares.
N
umero de operaciones
n3
n3
+ 2 n2
3
3
76
x1
16 12
8
12
18 6 x2 = 66 .
x3
46
8 6
8
La factorizaci
on de Cholesky es posible (A es definida positiva):
4 3
3
U= 0
0
0
237
2
0 .
2
11.
DE SISTEMAS LINEALES
SOLUCION
Al resolver U T y = b se obtiene
y = (19, 3, 4).
Finalmente, al resolver U x = y se obtiene
x = (3, 1, 2).
Para la implementaci
on en C ya estan todos los elementos, solamente
basta ensamblarlos y tener en cuenta que no es necesario construir U T .
En la solucion del sistema triangular inferior U T y = b, es necesario
trabajar con partes de las filas de U T , o sea, con partes de las columnas
de U .
int solChol(double *a, double *b, int n, double eps)
{
// Solucion por el metodo de Cholesky
// del sistema A x = b.
// A debe ser simetrica.
//
//
//
//
//
238
11.11.
METODO
DE GAUSS-SEIDEL
esta en
u[i*n+j].
// La solucion quedara en
b.
int i, n1;
n1 = n+1;
for( i = 0; i < n; i++){
b[i] = (b[i] - prodXY( &u[i], n, b, 1, i))/u[i*n1];
}
}
11.11
M
etodo de Gauss-Seidel
11.
DE SISTEMAS LINEALES
SOLUCION
En cada iteraci
on del metodo de Gauss-Seidel, hay n subiteraciones.
En la primera subiteraci
on se modifica u
nicamente x1 . Las demas coordenadas x2 , x3 , ..., xn no se modifican. El calculo de x1 se hace de tal
manera que se satisfaga la primera ecuaci
on.
x11 =
x1i
En la segunda subiteraci
on se modifica u
nicamente x2 . Las demas coordenadas x1 , x3 , ..., xn no se modifican. El calculo de x2 se hace de tal
manera que se satisfaga la segunda ecuaci
on.
x22 =
x2i
xnn =
xni
x1
10 2 1 0
1 20 2 3 x2
2 1 30 0 x3
x4
1 2
3 20
240
26
15
=
53
47
11.11.
METODO
DE GAUSS-SEIDEL
x11 =
x1
x22
x2
x33
x3
x44
x4
1.1750
1.0114
1.0114
1.0114
1.9725
1.9725
2.0025
2.0025
2.0466
2.0466
2.0466
1.9991
3.0025
3.0025
3.0025
3.0025
1.0114
0.9997
0.9997
0.9997
2.0025
2.0025
2.0002
2.0002
1.9991
1.9991
1.9991
1.9998
3.0000
3.0000
3.0000
3.0000
0.9997
1.0000
1.0000
1.0000
2.0002
2.0002
2.0000
2.0000
1.9998
1.9998
1.9998
2.0000
3.0000
3.0000
3.0000
3.0000
1.0000
1.0000
1.0000
1.0000
2.0000
2.0000
2.0000
2.0000
2.0000
2.0000
2.0000
2.0000
241
11.
DE SISTEMAS LINEALES
SOLUCION
Teoricamente, el metodo de Gauss-Seidel puede ser un proceso infinito. En la practica el proceso se acaba cuando de xk a xk+n los cambios
son muy peque
nos. Esto quiere decir que el x actual es casi la solucion
x .
Como el metodo no siempre converge, entonces otra detenci
on del
proceso, no deseada pero posible, esta determinada cuando el n
umero
de iteraciones realizadas es igual a un n
umero m
aximo de iteraciones
previsto.
El siguiente ejemplo no es convergente, ni siquiera empezando de una
aproximacion inicial muy cercana a la solucion. La solucion exacta es
x = (1, 1, 1).
Ejemplo 11.16. Resolver
11
x1
1
2 10
11 1 2 x2 = 12
8
x3
1
5 2
partiendo de x0 = (1.0001, 1.0001, 1.0001).
1.0012
1.0012
1.0012
0.6863
0.6863
0.6863
83.5031
83.5031
83.5031
1.0001
1.0134
1.0134
1.0134
2.5189
2.5189
2.5189
926.4428
926.4428
1.0001
1.0001
0.9660
0.9660
0.9660
9.9541
9.9541
9.9541
2353.8586
Algunos criterios garantizan la convergencia del metodo de GaussSeidel. Por ser condiciones suficientes para la convergencia son criterios
demasiado fuertes, es decir, la matriz A puede no cumplir estos requisitos
y sin embargo el metodo puede ser convergente. En la practica, con
frecuencia, es muy dispendioso poder aplicar estos criterios.
Una matriz cuadrada es de diagonal estrictamente dominante
por filas si en cada fila el valor absoluto del elemento diagonal es mayor
242
METODO
DE GAUSS-SEIDEL
11.11.
n
X
j=1,j6=i
|aij | , i.
Dejando de lado los superndices, las formulas del metodo de GaussSeidel se pueden reescribir para facilitar el algoritmo y para mostrar que
kxk x k y kxk xk+n k estan relacionadas.
bi
xi
xi
xi
n
X
aij xj
j=1,j6=i
,
aii
n
X
aij xj + aii xi
bi
j=1
aii
bi Ai x
.
xi +
aii
Sean
ri = bi Ai x,
ri
i =
aii
El valor ri es simplemente el error, residuo o resto que se comete en la
i-esima ecuaci
on al utilizar el x actual. Si ri = 0, entonces la ecuaci
on
i-esima se satisface perfectamente. El valor i es la modificaci
on que
sufre xi en una iteraci
on.
Sean r = (r1 , r2 , ..., rn ), = (1 , 2 , ..., n ). Entonces xk+n = xk + .
Adem
as xk es solucion si y solamente si r = 0, o sea, si y solamente = 0.
243
11.
DE SISTEMAS LINEALES
SOLUCION
kk
max |aii |
La siguiente es la implementaci
on en C, casi la traduccion literal, del
algoritmo anterior.
int gaussSei(double *a, double *b, double *x, int n,
double eps, int maxit)
{
// Metodo de Gauss-Seidel para resolver A x = b
//
//
//
//
Devuelve:
1 : si se obtuvo aproximadamente la solucion.
0 : si hay un elemento diagonal nulo.
2 : si hubo demasiadas iteraciones, mas de maxit.
244
11.12.
int i, n1, k;
double nrmD, di;
n1 = n+1;
for(i=0;i<n;i++)if(fabs(a[i*n1])<=1.e-40)return 0;
11.12
Soluci
on por mnimos cuadrados
kAx bk = 0,
kAx bk2 = 0,
kAx bk22 = 0.
Es Posible que lo deseado no se cumpla, entonces se quiere que el incumplimiento (el error) sea lo m
as peque
no posible. Se desea minimizar
esa cantidad,
min kAx bk22 .
(11.15)
245
11.
DE SISTEMAS LINEALES
SOLUCION
11.12.1
Derivadas parciales
xi
Evaluada en un punto especfico x
, se denota
(
x)
xi
Por ejemplo, si (x1 , x2 , x3 , x4 ) = (4x31 + 6x4 )9 + 5x1 x2 + 8x4 ,
x1
x2
x3
x4
11.12.
11.12.2
Ecuaciones normales
= 2 ((Ax)1 b1 )a11 + ((Ax)2 b2 )a21 + ((Ax)3 b3 )a31
+((Ax)4 b4 a41 ,
= 2
= 2
4
X
i=1
4
X
i=1
= 2
4
X
i=1
De manera semejante
f
x2
f
x3
= 2 AT (Ax b)
= 2 AT (Ax b)
247
11.
DE SISTEMAS LINEALES
SOLUCION
y quitando el 2 se tiene
0,
0,
0
Es decir,
AT (Ax b) = 0,
AT A x = AT b .
(11.16)
3.1
2
1
0
8.9
x1
1 2
3
x2 =
3.1
2
2
1
x3
0.1
5
4 2
248
11.12.
4.0
x1
34
20 15
20
25 12 x2 = 20.5
x3
23.4
15 12
14
La solucion por mnimos cuadrados es:
x = (2.0252, 1.0132, 2.9728) .
El error, Ax b, es:
0.0628
0.0196
0.0039 .
0.0275
3
2
1
3
9
x1
1 2
0
x2 =
3
2
2 6
x3
0
5
4
6
3
x1
34 20 48
20 25 15 x2 = 21
27
x3
48 15 81
Al tratar de resolver este sistema de ecuaciones por el metodo de Cholesky;
no se puede obtener la factorizacion de Cholesky, luego AT A no es
definida positiva, es decir, las columnas de A son linealmente dependientes. Si se aplica el metodo de Gauss, se obtiene que AT A es singular
y se concluye que las columnas de A son linealmente dependientes.
Ejemplo 11.19. Resolver por mnimos cuadrados:
2
1
3
1 2 x1
0
=
2
6
2 x2
5
4
6
249
11.
DE SISTEMAS LINEALES
SOLUCION
0
0
.
0
0
250
11.12.
Ejercicios
11.1 Resuelva el sistema Ax = b,
5 1
0
4
A=
0
0
0
0
donde
4
2
1
1 2
, b = 8 .
0
2
4
6
0
3
4 12 10
6
45
30 , b = 9 .
A = 12
10
30
41
31
36
c = 126 .
122
18
4 12 10
45
30 , b = 63 .
A = 12
60
10
45
25
42
4 15 10
45
15 , b = 96 .
A = 12
105
10 75/2
25
11.6 Resuelva por el metodo de Cholesky el sistema Ax = b, donde
6
4 12 10
45
30 , b = 9 .
A = 12
31
10
30
41
251
11.
DE SISTEMAS LINEALES
SOLUCION
8
4
2
4 2
2
5
6 3
, b = 10 .
A=
14
4
6
8 4
6
2 3 4
3
4 2 2
4
5 1 , b = 4 .
A = 2
2
1 2
5
9
5 1 1
1 , b = 20 .
A= 2 4
48
1 2 10
6
4 12 10
45
30 , b = 9 .
A = 12
31
10
30
41
11.11 Resuelva por el metodo de Gauss-Seidel el
1 4 5
A = 6 2 7 , b =
8 9 3
sistema Ax = b, donde
10
15 .
20
10
1 2 3
15
4 5 6
A=
7 8 9 , b = 20 .
25
10 12 15
10
1 2 3
15
4 5 6
A=
7 8 9 , b = 20 .
25
10 11 12
252
11.12.
8
4 2
2
0 0
0 0
12
2
5 1
2 0
0 0
8
2 1
5
4 6
0 0
, b = 12 .
0
2
4
6
5
2
0
A=
23
0
0
6
5 11
4 3
18
0
0
0 2 4 12 2
6
0
0
0
0 3
2 14
11.21 Se dice que una matriz simetrica es una matriz banda de ancho
2m1 si aij = 0 cuando |ji| m. Demuestre que si A es definida
253
11.
DE SISTEMAS LINEALES
SOLUCION
4 2
2
5 1
2
5
4
6
6
5 2
.
11
4
3
12
2
14
Haga un programa para almacenar de A u
nicamente la banda superior, hacer la factorizacion de Cholesky y resolver el sistema
Ax = b.
(i1 , j1 , v1 )
(i2 , j2 , v2 )
..
.
(ik , jk , vk )
..
.
donde aik ,jk = vk . Haga un programa para almacenar de A u
nicamente
los elementos no nulos y resolver por el metodo de Gauss-Seidel el
sistema Ax = b.
254
12
Soluci
on de ecuaciones
Uno de los problemas m
as corrientes en matem
aticas consiste en resolver
una ecuaci
on, es decir, encontrar un valor x R que satisfaga
f (x) = 0,
donde f es una funcion de variable y valor real, o sea,
f : R R.
Este x se llama solucion de la ecuaci
on. A veces tambien se dice que
x es una raz. Algunos ejemplos sencillos de ecuaciones son:
x5 3x4 + 10x 8 = 0,
ex x3 + 8 = 0,
x2 + x
x = 0.
cos(x 1) + 2
12.
DE ECUACIONES
SOLUCION
El proceso anterior es te
oricamente infinito, y obtendra la solucion despues de haber hecho un n
umero infinito de calculos. En la practica el
proceso se detiene cuando se obtenga una aproximacion suficientemente
buena de x . Esto querra decir que el proceso se detendra cuando
|xk x | ,
para un dado. El anterior criterio supone el conocimiento de x , que es
justamente lo buscado. Entonces se utiliza el criterio, este si aplicable,
|f (xk )| .
En la mayora de los casos, cuanto m
as cerca este x0 de x , m
as rapidamente
se obtendr
a una buena aproximacion de x .
Otros metodos parten de un intervalo inicial [a0 , b0 ], en el cual se
sabe que existe una raz x . A partir de el, se construye otro intervalo
[a1 , b1 ], contenido en el anterior, en el que tambien esta x y que es de
menor tama
no. De manera an
aloga se construye [a2 , b2 ]. Se espera que
256
12.1. METODO
DE NEWTON
[a0 , b0 ],
[ak , bk ], k = 1, 2, ...,
lim (bk ak ) = 0.
12.1
M
etodo de Newton
(x0 , f (x0 ))
(x1 , f (x1 ))
x2
Figura 12.1
x1
x0
Metodo de Newton.
257
DE ECUACIONES
SOLUCION
12.
f (xk )
f (xk )
(12.1)
xk
3.000000
2.758242
2.640786
2.611626
2.609930
2.609924
2.609924
f (xk )
2.200000E+01
5.589425E+00
9.381331E-01
4.892142E-02
1.590178E-04
1.698318E-09
-2.838008E-15
f (xk )
91.000000
47.587479
32.171792
28.848275
28.660840
28.660228
28.660227
Las races reales del polinomio x5 3x4 +10x8 son: 2.6099, 1.3566,
1. Tomando otros valores iniciales el metodo converge a estas races. Si
se toma x0 = 2.1, se esperara que el metodo vaya hacia una de las races
cercanas, 2.6099 o 1.3566 . Sin embargo, hay convergencia hacia 1.
k
0
1
2
3
4
5
xk
2.100000
0.942788
0.993484
0.999891
1.000000
1.000000
f (xk )
-4.503290e+00
-1.974259e-01
-1.988663e-02
-3.272854e-04
-9.509814e-08
-7.993606e-15
f (xk )
-3.891500
3.894306
3.103997
3.001745
3.000001
3.000000
12.1. METODO
DE NEWTON
Sencillez.
Generalmente converge.
En la mayora de los casos, cuando converge, lo hace rapidamente.
Tambien tiene algunas desventajas:
Puede no converger.
Presenta problemas cuando f (xk ) 0.
Requiere poder evaluar, en cada iteraci
on, el valor f (x).
La implementaci
on del metodo de Newton debe tener en cuenta varios aspectos. Como no es un metodo totalmente seguro, debe estar
previsto un n
umero m
aximo de iteraciones, llamado por ejemplo maxit.
Para una precisi
on f , la detencion deseada para el proceso iterativo se
tiene cuando |f (xk )| f . Otra detencion posible se da cuando dos
valores de x son casi iguales, es decir, cuando |xk xk1 | x . Se
acostumbra a utilizar el cambio relativo, o sea, |xk xk1 |/|xk | x .
Para evitar las divisiones por cero, se usa |xk xk1 |/(1 + |xk |) x .
Finalmente, siempre hay que evitar las divisiones por cero o por valores
casi nulos. Entonces, otra posible parada, no deseada, corresponde a
|f (xk )| 0 . El algoritmo para el metodo de Newton puede tener el
siguiente esquema:
datos: x0, maxit, f , x , 0
xk = x0
fx = f (xk), fpx = f (xk)
para k=1,...,maxit
si |fpx| 0 ent salir
= fx/fpx
xk = xk-
fx = f (xk), fpx = f (xk)
si |fx| f ent salir
si ||/(1+|xk|) x ent salir
fin-para k
Para la implementaci
on en C, es necesario determinar como se eval
ua
f y f . Fundamentalmente hay dos posibilidades:
259
12.
DE ECUACIONES
SOLUCION
12.1. METODO
DE NEWTON
DE ECUACIONES
SOLUCION
12.
12.1.1
Orden de convergencia
Definici
on 12.1. Sea {xk } una sucesion de n
umeros reales con lmite
L. Se dice que la convergencia tiene orden de convergencia p, si p es
el mayor valor tal que el siguiente lmite existe y es finito.
lim
|xk+1 L|
=<
|xk L|p
||xk+1 L||
||xk L||p
lim
|xk+1 x |
|xk x |2
|f (x )|
2|f (x )|
(12.2)
(12.3)
La demostraci
on de este teorema esta en varios libros; por ejemplo,
en [Atk78] o en [Sch91]. El primer resultado dice que la sucesion converge
a x . El segundo dice que la convergencia es cuadratica o de orden
superior. La frase x0 esta suficientemente cerca de x , entonces...
262
12.2. METODO
DE LA SECANTE
12.2
xk
2.1000000000000001
0.9427881279712185
0.9934841559110774
0.9998909365826297
0.9999999683006239
0.9999999999999973
|ek |
1.100000e+00
5.721187e-02
6.515844e-03
1.090634e-04
3.169938e-08
2.664535e-15
|ek |/|ek1 |2
4.728254e-02
1.990666e+00
2.568844e+00
2.664971e+00
2.651673e+00
M
etodo de la secante
f (xk ) f (xk1 )
,
xk xk1
entonces se obtiene
xk+1 = xk
(12.4)
12.
DE ECUACIONES
SOLUCION
y = f (x)
(x0 , f (x0 ))
(x1 , f (x1 ))
b
x2 x1
Figura 12.2
x0
Metodo de la secante.
xk
3.000000
3.010000
2.761091
2.678210
2.625482
2.611773
2.609979
2.609925
2.609924
2.609924
f (xk )
2.200000e+01
2.292085e+01
5.725624e+00
2.226281e+00
4.593602e-01
5.317368e-02
1.552812e-03
5.512240e-06
5.747927e-10
-2.838008e-15
1+ 5
1.618
2
Como el metodo de la secante es semejante al metodo de Newton,
entonces tienen aproximadamente las mismas ventajas y las mismas
desventajas, salvo dos aspectos:
264
12.2. METODO
DE LA SECANTE
12.
//
//
//
//
//
//
//
DE ECUACIONES
SOLUCION
int k;
double delta, x1, x2, f0, f1, f2, den;
x1 =
f0 =
f1 =
for(
x0 + 0.01;
f(x0);
f(x1);
k=1; k<= maxit; k++){
den = f1 - f0;
if( fabs(den) <= eps0 ){
indic = 0;
return x1;
}
delta = f1*(x1-x0)/den;
x2 = x1 - delta;
f2 = f(x2);
if( fabs(f2) <= epsF ){
indic = 1;
return x2;
}
if( fabs(delta)/( 1.0+fabs(x2) ) <= epsX ){
indic = 2;
return x2;
}
x0 = x1; x1 = x2; f0 = f1; f1 = f2;
}
indic = 3;
return x2;
}
//--------------------------------------------------------double f(double x)
266
12.3. METODO
DE LA BISECCION
{
// Calculo de f(x)
// f(x) = x^5 - 3x^4 + 10x - 8.
return x*x*x*x*x - 3.0*x*x*x*x + 10.0*x - 8.0;
}
12.3
M
etodo de la bisecci
on
Finalmente
1
1
(bk2 ak2 ).
bk a k =
2
2
Obviamente Ek 0 y
k
1
bk a k =
(b0 a0 ).
2
Ek
1
1
= .
Ek1
2
2
267
12.
DE ECUACIONES
SOLUCION
Esto quiere decir que la sucesion de cotas del error tiene convergencia
lineal (orden 1) y tasa de convergencia 1/2.
En el metodo de la biseccion se puede saber por anticipado el n
umero
de iteraciones necesarias para obtener un tama
no deseado,
bk ak ,
k
1
(b0 a0 ) ,
2
k
,
2
b0 a 0
b0 a 0
2k
,
b0 a 0
,
k log 2 log
a0
log b0
log 2
Por ejemplo, si el tama
no del intervalo inicial es 3, si = 1.0E 6,
entonces en k = 22 ( 21.52) iteraciones se obtiene un intervalo suficientemente peque
no.
12.4
M
etodo de Regula Falsi
Igualmente se conoce con el nombre de falsa posicion. Es una modificacion del metodo de la biseccion. Tambien empieza con un intervalo
[a0 , b0 ] donde f es continua y tal que f (a0 ) y f (b0 ) tienen signo diferente.
En el metodo de biseccion, en cada iteraci
on, u
nicamente se tiene
en cuenta el signo de f (ak ) y de f (bk ), pero no sus valores: no se esta
utilizando toda la informaci
on disponible. Adem
as es de esperar que
si f (ak ) esta m
as cerca de 0 que f (bk ), entonces puede ser interesante
considerar, no el punto medio, sino un punto m
as cercano a ak . De
manera an
aloga, si f (bk ) esta m
as cerca de 0 que f (ak ), entonces puede
ser interesante considerar, no el punto medio, sino un punto m
as cercano
a bk .
En el metodo de Regula Falsi se considera el punto donde la recta
que pasa por (ak , f (ak )), (bk , f (bk )) corta el eje x. Como f (ak ) y f (bk )
tienen signo diferente, entonces el punto de corte ck queda entre ak y bk .
268
12.4. METODO
DE REGULA FALSI
y = f (x)
(bk , f (bk ))
b
ak c k
bk
b
Figura 12.3
Regula Falsi.
La ecuaci
on de la recta es:
y f (ak ) =
f (bk ) f (ak )
(x ak )
bk a k
f (ak )(bk ak )
f (bk ) f (ak )
(12.5)
12.
DE ECUACIONES
SOLUCION
f (ak )f (ck ) < 0; en este caso hay una raz en el intervalo [ak , ck ] =
[ak+1 , bk+1 ];
f (ak )f (ck ) > 0; en este caso hay una raz en el intervalo [ck , bk ] =
[ak+1 , bk+1 ].
Ejemplo 12.3. Aplicar el metodo de Regula Falsi a la ecuaci
on x5
4
3x + 10x 8 = 0, partiendo de [2, 5].
k
0
1
2
3
4
5
10
20
30
335
ak
2.000000
2.009259
2.018616
2.028067
2.037610
2.047239
2.096539
2.198548
2.298673
2.609924
bk
5
5
5
5
5
5
5
5
5
5
f (ak )
-4.000000
-4.054857
-4.108820
-4.161744
-4.213478
-4.263862
-4.489666
-4.739498
-4.594020
-0.000001
f (bk )
1292
1292
1292
1292
1292
1292
1292
1292
1292
1292
ck
2.009259
2.018616
2.028067
2.037610
2.047239
2.056952
2.106594
2.208787
2.308244
2.609924
f (ck )
-4.054857
-4.108820
-4.161744
-4.213478
-4.263862
-4.312734
-4.528370
-4.744664
-4.554769
-0.000001
12.5
Modificaci
on del m
etodo de Regula Falsi
DEL METODO
12.5. MODIFICACION
DE REGULA FALSI
k
1
bk a k
(b0 a0 ),
2
a
2.0000
2.0093
2.0662
2.4104
2.5825
2.6033
2.6092
2.6099
2.6099
2.6099
b
5.0000
3.5000
2.7546
2.7546
2.7546
2.6686
2.6360
2.6226
2.6162
2.6131
f(a)
-4.00e+0
-4.05e+0
-4.36e+0
-3.80e+0
-7.44e-1
-1.87e-1
-2.00e-2
-9.73e-4
-2.33e-5
-2.81e-7
f(b)
1.29e+3
1.02e+2
5.42e+0
5.42e+0
5.42e+0
1.88e+0
7.84e-1
3.72e-1
1.83e-1
9.10e-2
c
2.0093
2.0662
2.3731
2.5523
2.6033
2.6092
2.6099
2.6099
2.6099
2.6099
f(c)
-4.0e+0
-4.4e+0
-4.2e+0
-1.5e+0
-1.9e-1
-2.0e-2
-9.7e-4
-2.3e-5
-2.8e-7
-1.7e-9
m
f(m)
3.5000 1.0e+2
2.7546 5.4e+0
2.4104 -3.8e+0
2.5825 -7.4e-1
2.6686 1.9e+0
2.6360 7.8e-1
2.6226 3.7e-1
2.6162 1.8e-1
2.6131 9.1e-2
La modificaci
on es mucho mejor que el metodo de Regula Falsi.
Adem
as, el n
umero de iteraciones de la modificaci
on debe ser menor
o igual que el n
umero de iteraciones del metodo de bisecci
on. Pero para
comparar equitativamente el metodo de biseccion y la modificaci
on de
Regula Falsi, es necesario tener en cuenta el n
umero de evaluaciones de
f (x).
En el metodo de biseccion, en k iteraciones, el n
umero de evaluaciones de f esta dado por:
nbisec = 2 + kbisec
En la modificaci
on de Regula Falsi,
nmodif = 2 + 2 kmodif
271
12.
12.6
DE ECUACIONES
SOLUCION
M
etodo de punto fijo
(12.6)
(12.7)
x=
6
Aplicando el metodo de punto fijo a partir de x0 = 1 se tiene:
x0
x1
x2
x3
x4
x5
x6
x7
x8
=
=
=
=
=
=
=
=
=
-1
-0.833333
-0.852623
-0.851190
-0.851303
-0.851294
-0.851295
-0.851295
-0.851295
x
272
12.6. METODO
DE PUNTO FIJO
=
=
=
=
=
=
=
=
-0.8510
-0.8488
-0.8294
-0.6599
1.1415
-11.6832
-142.0691
-2.0190e+4
En este caso se observa que, aun partiendo de una muy buena aproximaci
on de la solucion, no hay convergencia.
Antes de ver un resultado sobre convergencia del metodo de punto
fijo, observemos su interpretaci
on gr
afica. La solucion de g(x) = x esta
determinada por el punto de corte, si lo hay, entre las gr
aficas y = g(x)
y y = x.
y=x
y = g(x)
x
Figura 12.4 Punto fijo.
12.
DE ECUACIONES
SOLUCION
curva y = g(x). El punto obtenido tiene coordenadas (x0 , g(x0 )), o sea,
(x0 , x1 ). Para obtener x2 = g(x1 ) es necesario inicialmente resituar x1
sobre el eje x, para lo cual basta con buscar horizontalmente la recta
y = x para obtener el punto (x1 , x1 ). A partir de este punto se puede
obtener x2 buscando verticalmente la curva y = g(x). Se tiene el punto
(x1 , g(x1 )), o sea, (x1 , x2 ). Con desplazamiento horizontal se obtiene
(x2 , x2 ). En resumen, se repite varias veces el siguiente procedimiento:
a partir de (xk , xk ) buscar verticalmente en la curva y = g(x) el punto
(xk , xk+1 ), y a partir del punto obtenido buscar horizontalmente en la
recta y = x el punto (xk+1 , xk+1 ). Si el proceso converge, los puntos
obtenidos tienden hacia el punto (x , g(x )) = (x , x ).
Las figuras 12.5.a, 12.5.b, 12.5.c y 12.5.d muestran gr
aficamente la
utilizaci
on del metodo; en los dos primeros casos hay convergencia; en
los otros dos no hay, aun si la aproximacion inicial es bastante buena.
y=x
y = g(x)
x0 x1 x2 x3 x
Figura 12.5.a Metodo de punto fijo.
274
12.6. METODO
DE PUNTO FIJO
y=x
y = g(x)
x0
x2 x x3
Figura 12.5.b
x1
y=x
y = g(x)
x x0 x2
Figura 12.5.c
x3
x4
275
12.
DE ECUACIONES
SOLUCION
y=x
y = g(x)
x3
x1 x x0 x2
Figura 12.5.d
x4
Entonces existe un u
nico x en [a, b] soluci
on de x = g(x) y la iteraci
on
de punto fijo (12.7) converge a x para todo x0 [a, b].
Teorema 12.3. Sea x soluci
on de x = g(x), g continuamente diferenciable en un intervalo abierto I tal que x I, |g (x )| < 1. Entonces
la iteraci
on de punto fijo (12.7) converge a x para todo x0 suficientemente cerca de x .
El caso ideal (la convergencia es m
as rapida) se tiene cuando g (x ) 0.
12.6. METODO
DE PUNTO FIJO
x =
2
x0
x1
x2
x3
x4
x5
x6
=
=
=
=
=
=
=
3
2
1.75000000000000
1.73214285714286
1.73205081001473
1.73205080756888
1.73205080756888
g ( 3) = 0,
g (1) = 1,
13
,
g (4) =
32
3
g (x) =
x3
277
12.
DE ECUACIONES
SOLUCION
Entonces g (x) > 0 para todo x positivo. Luego g (x) es creciente para
x > 0. Como g (1) = 1, entonces 1 < g (1 + ). De nuevo por
ser g (x) creciente, entonces 1 < g (x) 13/32 para todo x I. En
resumen, |g (x)| < 1 cuando x I.
Entre 3 y 4 el valor
Entre 1+ y 3 el valor de g (x) es negativo.
de g (x) es positivo.
3] ycrece en [ 3, 4]. En Luego g decrece
en [1+,
12.6.1
M
etodo de punto fijo y m
etodo de Newton
ecuaci
on f (x) = 0. Esta
se puede reescribir
0 = cf (x),
x = x + cf (x) = g(x).
(12.8)
1
f (x )
f (xk )
.
f (x )
(12.9)
12.7. METODO
DE NEWTON EN RN
12.7
M
etodo de Newton en Rn
2x1 + 3x2 x3 5 = 0
(12.10)
(x1 + x2 + x3 ) 10x3 + 1 = 0.
Este sistema no se puede escribir en la forma matricial Ax = b; entonces
no se puede resolver por los metodos usuales para sistemas de ecuaciones
lineales. Lo que se hace, como en el metodo de Newton en R, es utilizar
aproximaciones de primer orden (llamadas tambien aproximaciones lineales). Esto es simplemente la generalizaci
on de la aproximacion por
una recta.
Un sistema de n ecuaciones con n incognitas se puede escribir de la
forma
F1 (x1 , x2 , ..., xn ) = 0
F2 (x1 , x2 , ..., xn ) = 0
..
.
Fn (x1 , x2 , ..., xn ) = 0,
donde cada Fi es una funcion de n variables con valor real, o sea, Fi :
Rn R. Denotemos x = (x1 , x2 , ..., xn ) y
F1 (x)
F2 (x)
F (x) =
.
..
.
Fn (x)
(12.11)
12.
12.7.1
DE ECUACIONES
SOLUCION
Matriz jacobiana
por F (
x), es una matriz de tama
no n n, en la que en la i-esima fila
estan las n derivadas parciales de Fi ,
JF (x) = F (x) =
F1
(x)
x1
F1
(x)
x2
F2
(x)
x1
F2
(x)
x2
..
.
..
Fn
(x)
x1
Fn
(x)
x2
F1
(x)
xn
F2
(x)
xn
Fn
(x)
xn
2x1 + x2
x1
1
F (x) =
2
3x3
3x2
F (2, 3, 4) = 2
12.7.2
12 9 .
6 4
F
ormula de Newton en Rn
f (xk )
,
f (xk )
f (xk )
.
f (xk )
12.7. METODO
DE NEWTON EN RN
(12.12)
Su interpretaci
on, muy natural, aparece a continuaci
on. Sea x , un
vector de n componentes, solucion del sistema (12.11). Dependiendo de
la conveniencia se podra escribir
x1
x
2
x = (x1 , x2 , ..., xn )
o
x = . .
..
xn
xk+1 = xk + dk .
Premultiplicando por F (xk )
En esta u
ltima expresi
on se conoce (o se puede calcular) la matriz F (xk ).
Tambien se conoce el vector F (xk ). O sea, simplemente se tiene un
sistema de ecuaciones lineales. La solucion de este sistema es el vector
dk . Entonces las formulas para el metodo de Newton son:
resolver F (xk ) dk = F (xk ),
x
k+1
281
= x +d .
(12.13)
12.
DE ECUACIONES
SOLUCION
(x1 + x2 + x3 )2 10x3 + 1 = 0
1 2
1
1
F (x0 ) = 37 , F (x0 ) = 2 12 9
6 6 4
30
2.5753
1
d1
1 2
1
resolver 2 12 9 d02 = 37 , d0 = 0.5890
2.7534
30
d03
6 6 4
4.5753
2.5753
2
x1 = 3 + 0.5890 = 2.4110
1.2466
2.7534
4
6.7397 4.5753
1.0000
8.1494
F (x1 ) = 4.8656 , F (x1 ) = 2.0000 3.7397 7.2329
6.8219 6.8219 3.1781
0.1689
4.4433
8.1494
d1
6.7397 4.5753 1.0000
2.0000 3.7397 7.2329 d12 = 4.8656 , d1 = 4.6537
0.5048
0.1689
d13
6.8219 6.8219 3.1781
0.1321
4.4433
4.5753
2
4.6537 = 2.2428
x = 2.4110 +
1.7514
0.5048
1.2466
A continuaci
on se presentan los resultados de F (xk ), F (xk ), dk , xk+1 .
k=2
0.7833
0.6513
2.5069 0.1321 1.0000
0.9350
7.0481 , 2.0000 5.2542 6.7283 , 0.8376 , 1.4052
1.1644
0.5870
8.2524 8.2524 1.7476
0.5116
k=3
0.9658
0.1824
2.9718 0.7833 1.0000
0.1213
1.4751 , 2.0000 3.4931 4.2156 , 0.3454 , 1.0598
1.0141
0.1502
6.7057 6.7057 3.2943
0.5981
282
12.7. METODO
DE NEWTON EN RN
k=4
0.9993
0.0335
2.9913 0.9658 1.0000
0.0297
0.1557 , 2.0000 3.0424 3.1793 , 0.0587 , 1.0011
1.0002
0.0139
6.0793 6.0793 3.9207
0.0981
k=5
1.0000
0.0007
2.9997 0.9993 1.0000
0.0008
0.0025 , 2.0000 3.0006 3.0033 , 0.0011 , 1.0000
1.0000
0.0002
6.0012 6.0012 3.9988
0.0015
1
0
, luego x 1 .
F (x ) 0
1
0
Ejercicios
Trate de resolver las ecuaciones propuestas, utilice metodos diferentes, compare sus ventajas y desventajas. Emplee varios puntos iniciales. Busque, si es posible, otras races.
12.1 x3 + 2x2 + 3x + 4 = 0.
12.2 x3 + 2x2 3x 4 = 0.
12.3 x4 4x3 + 6x2 4x + 1 = 0.
12.4 x4 4x3 + 6x2 4x 1 = 0.
12.5 x4 4x3 + 6x2 4x + 2 = 0.
12.6
3x 6
x2
cos(x) + 2 x2 + 1
+ x3 8 = 0.
x2 + x + 10
ex + x 2
12.7
1000000 i
(1 + i)12
= 945560.
(1 + i)12 1
283
12.
DE ECUACIONES
SOLUCION
12.9 x1 + x2 + 2x1 x2 31 = 0,
284
13
Interpolaci
on y
aproximaci
on
En muchas situaciones de la vida real se tiene una tabla de valores
correspondientes a dos magnitudes relacionadas; por ejemplo,
A
no
1930
1940
1950
1960
1970
1980
1985
1990
1995
Poblacion
3425
5243
10538
19123
38765
82468
91963
103646
123425
De manera m
as general, se tiene una tabla de valores
x0
x1
x2
..
.
f (x0 )
f (x1 )
f (x2 )
..
.
xn
f (xn )
285
13.
Y APROXIMACION
INTERPOLACION
y se desea obtener una funcion f, sencilla y facil de calcular, aproximacion de f , o en otros casos, dado un x
, se desea obtener f(
x) valor
aproximado de f (
x).
y
b
b
b
b
b
x
Figura 13.1
Los valores f (xi ) pueden corresponder a:
Datos o medidas obtenidos experimentalmente.
Valores de una funcion f que se conoce pero tiene una expresi
on
analtica muy complicada o de evaluacion difcil o lenta.
Una funcion de la que no se conoce una expresi
on analtica, pero se
puede conocer f (x) como solucion de una ecuaci
on funcional (por
ejemplo, una ecuaci
on diferencial) o como resultado de un proceso
numerico.
Cuando se desea que la funcion f pase exactamente por los puntos
conocidos,
f(xi ) = f (xi ) i,
b
b
Figura 13.2
286
13.1. INTERPOLACION
b
b
Figura 13.3
13.1
Interpolaci
on
13.
Y APROXIMACION
INTERPOLACION
.. = ..
..
. .
.
1 (xn ) 2 (xn )
n (xn )
an
yn
a = y.
(13.1)
1
a1
1 1 1
1
2 4 a2 = 2
5
a3
1
3 9
Entonces
4
a = 3 , f(x) = 4 3x + 2x2 ,
2
Ejemplo 13.2. Dados los puntos mismos (1, 1), (2, 2), (3, 5) y la
base formada por las funciones 1 (x) = 1, 2 (x) = ex , 3 (x) = e2x ,
encontrar la funcion de interpolacion.
Al plantear a = y, se tiene
a1
1
1 0.3679
0.1353
1 7.3891 54.5982 a2 = 2
a3
5
1 20.0855 403.4288
288
DE LAGRANGE
13.2. INTERPOLACION
Entonces
1.2921
a = 0.8123 , f(x) = 1.2921 0.8123ex + 0.0496e2x ,
0.0496
13.2
Interpolaci
on de Lagrange
En la interpolaci
on de Lagrange la funcion f que pasa por los puntos
es un polinomio, pero el polinomio se calcula sin resolver explcitamente
un sistema de ecuaciones. M
as precisamente, dados n + 1 puntos
(x0 , y0 ), (x1 , y1 ), (x2 , y2 ), . . . , (xn , yn ),
donde yi = f (xi ) = fi , se desea encontrar un polinomio p Pn (el conjunto de polinomios de grado menor o igual a n), que pase exactamente
por esos puntos, es decir,
p(xi ) = yi , i = 0, 1, 2, ..., n.
(13.2)
13.2.1
13.
Y APROXIMACION
INTERPOLACION
13.2.2
Polinomios de Lagrange
Lk (x) =
n
Y
i=0,i6=k
n
Y
i=0,i6=k
(x xi )
(xk xi )
(13.3)
La construcci
on de los polinomios de Lagrange, para los datos del u
ltimo
ejemplo x0 = 1, x1 = 2, x2 = 3, da:
L0 (x) =
L1 (x) =
L2 (x) =
(x 2)(x 3)
x2 5x + 6
=
,
(1 2)(1 3)
12
x2 2x 3
(x 1)(x 3)
=
,
(2 1)(2 3)
3
(x 1)(x 2)
x2 x 2
=
.
(3 1)(3 2)
4
DE LAGRANGE
13.2. INTERPOLACION
n
X
yk Lk (x).
(13.5)
k=0
Por construcci
on p es un polinomio en Pn . Reemplazando, facilmente
se verifica 13.2.
Para el ejemplo,
p(x) = 1L0 (x) 2L1 (x) + 5L2 (x) = 2x2 3x 4.
Ejemplo 13.3. Encontrar el polinomio, de grado menor o igual a 3, que
pasa por los puntos
(1, 1), (1, 5), (2, 2), (3, 5).
L0 (x) =
L1 (x) =
L2 (x) =
L3 (x) =
p(x) =
x3 6x2 + 11x 6
(x 1)(x 2)(x 3)
=
,
(1 1)(1 2)(1 3)
24
x3 4x2 + x + 6
,
4
x3 3x2 x + 3
,
3
x3 2x2 x + 2
,
8
2x2 3x 4.
13.2.3
13.
Y APROXIMACION
INTERPOLACION
(xi )
E(t) = 0,
(t)
(t)
G(t) = E(t)
E(t) = 0.
(t)
G(xi ) = E(xi )
(n+1) (x)
E(t),
(t)
(n + 1)!
G(n+1) (x) = f (n+1) (x)
E(t),
(t)
(n + 1)!
G(n+1) () = f (n+1) ()
E(t) = 0.
(t)
292
Entonces
E(t) =
13.3
(t) (n+1)
f
().
(n + 1)!
Por construcci
on, c es un polinomio en Pn . Adem
as,
c(xi ) = pn (xi ) pn1 (xi ) = 0, i = 0, 1, 2, ..., n 1.
La formula anterior dice que c tiene n races diferentes x0 , x1 , ..., xn1 ,
entonces
c(x) = n (x x0 )(x x1 )(x x2 ) (x xn1 ).
f (xn ) = p(xn ) = pn1 (xn ) + c(xn ),
f (xn ) = pn1 (xn ) + n (xn x0 )(xn x1 )(xn x2 ) (xn xn1 ).
De la u
ltima igualdad se puede despejar n . Este valor se define como
la diferencia dividida de orden n de f en los puntos x0 , x1 , x2 , ..., xn .
Se denota
n = f [x0 , x1 , ..., xn ] :=
13.
Y APROXIMACION
INTERPOLACION
(13.8)
Para x = x1 ,
x x0
f [x0 , x1 ] =
f [x0 , x1 ] =
f [x0 , x1 ] =
p1 (x1 ) po (x1 )
,
x1 x0
f (x1 ) f (x0 )
,
x1 x0
f [x1 ] f [x0 ]
.
x1 x0
294
(13.9)
f [xi+1 ] f [xi ]
xi+1 xi
(13.10)
Deducci
on de f [x0 , x1 , x2 ] :
p2 (x) = p1 (x) + f [x0 , x1 , x2 ](x x0 )(x x1 ),
p2 (x) p1 (x)
f [x0 , x1 , x2 ] =
,
(x x0 )(x x1 )
x = x2 ,
p2 (x2 ) p1 (x2 )
f [x0 , x1 , x2 ] =
,
(x2 x0 )(x2 x1 )
= ...
f0 (x2 x1 ) f1 (x2 x0 ) + f2 (x1 x0 )
f [x0 , x1 , x2 ] =
f2 f 1
f1 fo
x2 x1 x1 x0
=
,
x2 x0
= ...
f0 (x2 x1 ) f1 (x2 x0 ) + f2 (x1 x0 )
=
Luego
f [x0 , x1 , x2 ] =
Generalizando,
f [xi , xi+1 , xi+2 ] =
f [x1 , x2 ] f [x0 , x1 ]
x2 x0
xi+2 xi
(13.11)
La generalizaci
on para diferencias divididas de orden j es:
f [xi , xi+1 , ..., xi+j ] =
xi+j xi
(13.12)
(13.13)
13.
Y APROXIMACION
INTERPOLACION
Entonces
D0 f [xi ] := f (xi ),
D0 f [xi+1 ] D0 f [xi ]
,
Df [xi ] = D1 f [xi ] =
xi+1 xi
D1 f [xi+1 ] D1 f [xi ]
,
D2 f [xi ] =
xi+2 xi
Dj f [xi ] =
13.3.1
xi+j xi
(13.14)
(13.15)
(13.16)
(13.17)
fi
f0
x1
f1
x2
f2
x3
f3
f [xi , xi+1 ]
f [x0 , x1 ]
f [x0 , x1 , x2 ]
f [x1 , x2 ]
f [x0 , x1 , x2 , x3 ]
f [x1 , x2 , x3 ]
f [x2 , x3 ]
f [x1 , x2 , x3 , x4 ]
f [x2 , x3 , x4 ]
f [x3 , x4 ]
x4
f4
fi
0.0000
.5
0.7071
1.0000
1.4142
D2 f [xi ]
Df [xi ]
D3 f [xi ]
1.4142
0.5858
0.4142
0.3179
3
1.7321
0.2679
0.8284
0.1144
0.0482
0.3570
0.0265
0.0077
0.0250
2.0000
13.
Y APROXIMACION
INTERPOLACION
para i = 0, ..., n
D0 f [xi ] = f (xi )
fin-para i
para j = 1, ..., m
para i = 0, ..., n j
calcular Dj f [xi ] seg
un (13.17)
fin-para i
fin-para j
Si los datos f (xi ) corresponden a un polinomio, esto se puede deducir
mediante las siguientes observaciones:
Si para alg
un m todos los valores f [xk , xk+1 , ..., xk+m ] son iguales
(o aproximadamente iguales), entonces f es (aproximadamente)
un polinomio de grado m.
Si para alg
un r todos los valores f [xk , xk+1 , ..., xk+r ] son nulos
(o aproximadamente nulos), entonces f es (aproximadamente) un
polinomio de grado r 1.
13.3.2
C
alculo del valor interpolado
i1
m
Y
X
Di f [xk ]
(x xk+j ) .
(13.19)
pm (x) =
j=0
i=0
p0 (x) = fk
p1 (x) = p0 (x) + D1 f [xk ](x xk )
p2 (x) = p1 (x) + D2 f [xk ](x xk )(x xk+1 )
p3 (x) = p2 (x) + D3 f [xk ](x xk )(x xk+1 )(x xk+2 )
p4 (x) = p3 (x) + D4 f [xk ](x xk )(x xk+1 )(x xk+2 )(x xk+3 )
..
.
298
= 1,
= 0 (x xk ),
= 1 (x xk+1 ),
= 2 (x xk+2 ),
= 3 (x xk+3 ),
p0 (x) = fk
p1 (x) = p0 (x) + D1 f [xk ] 1
p2 (x) = p1 (x) + D2 f [xk ] 2
p3 (x) = p2 (x) + D3 f [xk ] 3
p4 (x) = p3 (x) + D4 f [xk ] 4
Unicamente
queda por precisar la escogencia del punto inicial o de referencia xk . Si se desea evaluar pm (
x), cu
al debe ser xk ? Recordemos
que se supone que los puntos x0 , x1 , x2 , ..., xn estan ordenados y que
m, orden del polinomio de interpolacion, es menor o igual que n. Obviamente, aunque no es absolutamente indispensable, tambien se supone
que x
/ {x0 , x1 , ..., xn }.
Ejemplo 13.5. Considere los datos del ejemplo anterior para calcular por interpolaci
on cuadratica y por interpolacion c
ubica una aproximacion de f (1.69).
El primer paso consiste en determinar el xk . Para ello u
nicamente se
tienen en cuenta los valores xi .
xi
0
.5
1
2
3
4
Para el caso de la interpolacion cuadratica, una simple inspecci
on
visual determina que hay dos posibilidades para xk . La primera es xk =
299
13.
Y APROXIMACION
INTERPOLACION
|
x vk | = min{|
x vi | : x
[xi , xi+m ]}.
i
(13.20)
(13.21)
(13.22)
(13.23)
xi
0
.5
1
2
3
4
ui
1.25
2.00
|
x ui |
0.44
0.31
vi
1.1667
2.0000
|
x vi |
0.5233
0.3100
Para la interpolaci
on c
ubica hay tres posibilidades para xk : 0 , 0.5 y
1.
300
xi
ui
0
.5
1
2
3
4
1.00
1.75
2.50
|
x ui |
vi
0.69
0.06
0.81
0.875
1.625
2.500
|
x vi |
0.815
0.065
0.810
p0 (x) = 0.7071,
p1 (x) = 0.7071+0.5858(1.19)
p1 (x) = 1.404202
2 = 1.19(1.691) = 0.8211,
p2 (x) = 1.4042020.1144(0.8211)
p2 (x) = 1.310268
3 = 0.8211(1.692) =0.254541, p3 (x) = 1.310268+0.0265(0.254541)
p3 (x) = 1.303523.
13.
13.4
Y APROXIMACION
INTERPOLACION
Diferencias finitas
Cuando los puntos (x0 , f (x0 )), (x1 , f (x1 )), (x2 , f (x2 )), ..., (xn , f (xn )),
estan igualmente espaciados en x, es decir, existe un h > 0 tal que
xi = x0 + ih, i = 1, ..., n
entonces se pueden utilizar las diferencias finitas, definidas por
0 fi = fi
(13.24)
fi = fi+1 fi
k+1
(13.25)
k
fi = (fi ) = fi+1 fi
(13.26)
fi+k
k
X
k
=
j fi .
j
(13.28)
j=0
13.4.1
xi
x0
fi
f0
x1
f1
2 fi
fi
f0
2 f0
f1
x2
2 f
f2
f2
x3
2 f
f3
3 fi
3 f0
3 f1
f3
x4
f4
La elaboracion de la tabla es muy sencilla. Las dos primeras columnas corresponden a los datos. A partir de la tercera columna, para
calcular cada elemento se hace la resta de dos elementos consecutivos de
la columna anterior. Por ejemplo, f3 = f4 f3 . Observese que este
valor se coloca en medio de la fila de f3 y de la fila de f4 . Por ejemplo,
2 f1 = f2 f1 . De manera semejante, 3 f0 = 2 f1 2 f0 .
Ejemplo 13.6. Construir la tabla de diferencias finitas, hasta el orden
3, a partir de los seis puntos siguientes: (0, 0), (0.5, 0.7071), (1, 1),
(1.5, 1.2247), (2, 1.4142), (2.5, 1.5811).
xi
0
fi
0.0000
fi
2 fi
3 fi
0.7071
.5
0.7071
0.2929
1.0000
0.2247
1.5
1.2247
1.4142
0.1895
0.1669
2.5
0.4142
0.0682
0.0352
0.3460
0.0330
0.0126
0.0226
1.5811
13.
Y APROXIMACION
INTERPOLACION
para i = 0, ..., n
0 fi = f (xi )
fin-para i
para j = 1, ..., m
para i = 0, ..., n j
j fi = j1 fi+1 j1 fi
fin-para i
fin-para j
13.4.2
C
alculo del valor interpolado
m
i1
if Y
X
pm (x) =
(x xk+j ) .
i! hi
i=0
j=0
Q
El valor i! se puede escribir i1
as, sea s = (x xk )/h,
j=0 (j + 1). Adem
es decir, x = xk + sh. Entonces, x xk+j = xk + sh xk jh = (s j)h.
i1
m
i
Y
X
fk
(s j)h
pm (x) =
i! hi
j=0
i=0
m
i1
if Y
X
=
(s j)
i!
i=0
m
X
j=0
i fk
i=0
i1
Y
j=0
sj
j+1
Esta u
ltima expresi
on sirve para cualquiervalor
real a y cualquier entero
a
= 1. Entonces,
no negativo b, con la convencion de que
0
i1
Y
sj
j+1
j=0
s
se puede denotar simplemente por
y as
i
m
X
s
i
fk
pm (x) =
.
(13.30)
i
i=0
s
guarda propiedades semejantes a las del coeficiente
Este coeficiente
i
binomial, en particular
s
s
si+1
.
=
i
i
i1
Esto permite su calculo de manera
s
=
0
s
=
1
s
=
2
s
=
3
s
=
4
..
.
recurrente
1,
s
s
0
s s1
2
1
s s2
3
2
s s3
4
3
305
13.
Y APROXIMACION
INTERPOLACION
x xk
.
h
= 1,
= 0 s,
= 1 (s 1)/2,
= 2 (s 2)/3,
= 3 (s 3)/4,
p0 (x) = fk
p1 (x) = p0 (x) + 1 fk 1
p2 (x) = p1 (x) + 2 fk 2
p3 (x) = p2 (x) + 3 fk 3
p4 (x) = p3 (x) + 4 fk 4
p0 (x) = f2 = 1
p1 (x) = 1 + .2247(1.92) = 1.431424
p2 (x) = 1.431424 .0352(.8832)
p2 (x) = 1.400335
3 = 2 (1.92 2)/3 = .023552, p3 (x) = 1.400335 + .0126(.023552)
p3 (x) = 1.400039
13.5
Aproximaci
on por mnimos cuadrados
..
.
..
.
.
.
an
1 (xm ) 2 (xm ) n (xm )
ym
307
13.
Y APROXIMACION
INTERPOLACION
(13.31)
(13.32)
2
n
m
X
X
min
aj j (xi ) yi .
i=1
es decir,
min
j=1
m
X
i=1
f(xi ) yi
2
0.55
1 0
0
0.65
a1
1 1
1
0.85
a3
1 2
4
1.35
1 3
9
308
a1
4.1250
5
7.5
16.25
7.5
16.25
39.375 a2 = 7.4875
a3
17.8313
16.25 39.375 103.0625
La solucion es:
0.56
a = 0.04 ,
0.10
f(x1 )
f(x2 )
f(x3 )
f(x4 )
f(x5 )
= a =
0.56
0.62
0.725
0.88
1.34
y=
0.55
0.65
0.725
0.85
1.35
Ejercicios
13.1 Halle, resolviendo el sistema de ecuaciones, el polinomio de interpolaci
on que pasa por los puntos
(1, 5),
(2, 4),
(4, 4).
13.2 Halle, por medio de los polinomios de Lagrange, el polinomio de
interpolaci
on que pasa por los puntos del ejercicio anterior.
13.3 Halle el polinomio de interpolacion que pasa por los puntos
(1, 5),
(1, 5),
(2, 2),
(4, 40).
309
13.
Y APROXIMACION
INTERPOLACION
311
13.
Y APROXIMACION
INTERPOLACION
312
14
Integraci
on y diferenciaci
on
14.1
Integraci
on num
erica
Esta tecnica sirve para calcular el valor numerico de una integral definida,
es decir, parar obtener el valor
I=
f (x)dx.
a
y = f (x)
b
Figura 14.1
14.
Y DIFERENCIACION
INTEGRACION
0.5
ex dx.
0.1
14.2
F
ormula del trapecio
ba
,
n
xn
f (x)dx =
x0
xm
f (x)dx +
x0
x0 x1 x2
a
xm
x2m
xm
f (x)dx + +
x2m
Figura 14.2
314
xnm
xn
f (x)dx.
xnm
xn
b
14.2. FORMULA
DEL TRAPECIO
xm
x0
f (x)dx
xm
pm (x)dx.
x0
p1 (x) = y0
Entonces
x1
p1 (x)dx =
x0
(y0 + x
0
y1 y0
)dx
h
h2 y1 y0
,
= y0 h +
2
h
y1
y0
+
),
= h(
2
2
Z x1
y0 + y1
f (x)dx h
2
x0
(14.1)
De la formula (14.1) o de la gr
afica se deduce naturalmente el nombre
de formula del trapecio.
315
14.
Y DIFERENCIACION
INTEGRACION
y0
y1
x0
x1
Figura 14.3
Ejemplo 14.1.
Z 0.2
0
1
1
ex dx 0.2( e0 + e0.2 ) = 0.22214028 .
2
2
.
Z xn
yn
yn1
+
).
f (x)dx h(
2
2
xn1
xn
y1
y1
y2
yn1
yn
y0
+
+
+
+
+
),
2
2
2
2
2
2
Zx0xn
yn
y0
+ y1 + y2 + + yn2 + yn1 +
),
f (x)dx h(
2
2
x0
Z xn
n1
X
yn
y0
yi +
+
).
f (x)dx h(
2
2
x0
Z
f (x)dx h(
(14.2)
i=1
Ejemplo 14.2.
Z 0.8
1
1
ex dx 0.2( e0 + e0.2 + e0.4 + e0.6 + e0.8 ) = 1.22962334 .
2
2
0
316
14.2. FORMULA
DEL TRAPECIO
14.2.1
f (x)g(x)dx = f (c)
a
g(x)dx
a
para alg
un c en [a, b].
Teniendo en cuenta que (x x0 )(x x1 ) 0 en el intervalo [x0 , x1 ] y
aplicando el teorema del valor medio para integrales, existe z [x0 , x1 ]
tal que
Z
f (z) x1
(x x0 )(x x1 )dx , z [x0 , x1 ].
eloc =
2
x0
Mediante el cambio de variable t = x x0 , dt = dx,
Z
f (z) h
eloc =
t(t h)dt , z [x0 , x1 ],
2
0
f (z) h3
=
( ) , z [x0 , x1 ],
2
6
(z)
f
eloc = h3
, z [x0 , x1 ].
12
317
(14.3)
14.
Y DIFERENCIACION
INTEGRACION
La formula anterior, como muchas de las formulas de error, sirve principalmente para obtener cotas del error cometido.
h3
M,
12
|eloc |
(14.4)
xn
x0
n
X
i=1
f (x)dx h(
(
yn
y0
+ y1 + y2 + + yn2 + yn1 +
)
2
2
f (zi ) h3
) , zi [xi1 , xi ]
12
n
h3 X
f (zi ) , zi [xi1 , xi ]
12
i=1
Sean
M1 = min{f (x) : x [a, b]} ,
318
14.3. FORMULA
DE SIMPSON
Entonces
M1 f (zi ) M2 , i
n
X
f (zi ) nM2 ,
nM1
i=1
n
1 X
f (zi ) M2 .
M1
n
i=1
2 ,
C[a,b]
1 X
f () =
f (zi ) .
n
i=1
Entonces
eglob =
h3
nf () ,
12
[a, b].
14.3
(b a)f ()
, [a, b].
12
(14.5)
F
ormula de Simpson
x0
El polinomio de interpolaci
on p2 (x) se construye a partir de los puntos
(x0 , y0 ), (x1 , y1 ), (x2 , y2 ). Para facilitar la deduccion de la formula,
supongamos que p2 es el polinomio de interpolacion que pasa por los
puntos (0, y0 ), (h, y1 ), (2h, y2 ). Entonces
(x 0)(x 2h)
(x 0)(x h)
(x h)(x 2h)
+ y1
+ y2
,
(0 h)(0 2h)
(h 0)(h 2h)
(2h 0)(2h h)
1
= 2 y0 (x h)(x 2h) 2y1 x(x 2h) + y2 x(x h) ,
2h
1
= 2 x2 (y0 2y1 + y2 ) + hx(3y0 + 4y1 y2 ) + 2h2 y0 ,
2h
p2 (x) = y0
319
Y DIFERENCIACION
INTEGRACION
14.
Z
Z
2h
1 8h3
4h2
(y
2y
+
y
)
+
h
(3y0 + 4y1 y2 )
0
1
2
2h2 3
2
+ 2h2 (2h)y0 ,
p2 (x)dx =
0
2h
0
4
1
1
p2 (x)dx = h( y0 + y1 + y2 ).
3
3
3
Entonces
Z
x2
x0
f (x)dx
h
(y0 + 4y1 + y2 )
3
(14.6)
xn
x0
f (x)dx
h
(y0 + 4y1 + 2y2 + 4y3 + + 4yn1 + yn )
3
f (x)dx
X
X
h
y2j + yn )
y2j1 + 2
( y0 + 4
3
xn
x0
k1
j=1
j=1
(14.7)
Ejemplo 14.3.
Z
0.8
0
ex dx
0.2 0
(e + 4(e0.2 + e0.6 ) + 2 e0.4 + e0.8 ) = 1.22555177 .
3
14.3.1
h
h
h
h
f (x) dx
f (x) dx
p2 (x) dx,
h
h
f (h) + 4f (0) + f (h) .
3
320
14.3. FORMULA
DE SIMPSON
Rh
Sea F tal que F (x) = f (x), entonces h f (x) dx = F (h) F (h). Al
derivar con respecto a h se tiene f (h) + f (h).
1
f (h) + 4f (0) + f (h)
3
f (h) + f (h) ,
h
3
2h2 (4)
f (h) , [1, 1].
3
Sea
g4 (h) = f (4) (h).
e (h) =
2h2
g4 (h).
3
e (t) dt + e (0),
Z
2 h 2
e (h) =
t g4 (t) dt.
3 0
e (h) =
321
14.
Y DIFERENCIACION
INTEGRACION
e (h) = h g4 (4 ).
9
4 [0, h],
Sea
g3 (h) = g4 (4 ) = f (4) (3 h) ,
1 3 1,
entonces
2
e (h) = h3 g3 (h).
9
De manera semejante,
e (t) dt + e (0),
0
Z
2 h 3
t g3 (t) dt,
e (h) =
9 0
Z h
2
e (h) = g3 (3 )
t3 dt ,
9
0
1 4
e (h) = h g3 (3 ).
18
e (h) =
3 [0, h],
Sea
g2 (h) = g3 (3 ) = f (4) (2 h) ,
1
e (h) = h4 g2 (h).
18
322
1 2 1,
14.3. FORMULA
DE SIMPSON
e (t) dt + e(0),
0
Z h
1
t4 g2 (t) dt,
e(h) =
18 0
Z h
1
e(h) = g2 (2 )
t4 dt , 2 [0, h],
18
0
1
e(h) = h5 g2 (2 ),
90
h5 (4)
e(h) = f (1 h) , 1 1 1,
90
h5 (4)
e(h) = f (z) , h z h.
90
e(h) =
f (4) (z)
, z [x0 , x2 ].
90
(14.8)
b
a
k1
k
h
X
X
f (x) dx
y2j + yn ) ,
y2j1 + 2
( y0 + 4
3
k
X
j=1
j=1
h5
f (4) (zj )
,
90
zj [x2j2 , x2j ],
h5 X (4)
=
f (zj )
90
j=1
M1 f (4) (zj ) M2 , j
k
X
f (4) (zj ) kM2 ,
kM1
M1
j=1
k
X
1
k
j=1
j=1
f (4) (zj ) M2 ,
323
14.
Y DIFERENCIACION
INTEGRACION
k
X
j=1
k
X
f (4) (zj ) =
n (4)
f (),
2
f (4) (zj ) =
b a (4)
f ().
2h
j=1
k
X
j=1
Entonces
eglob = h4
(b a)f (4) ()
, [a, b].
180
(14.9)
x3
f (x)dx =
x0
3
h
(3y0 + 9y1 + 9y2 + 3y3 ) h5 f (4) (z) ,
8
80
z [x0 , x3 ],
14.4. OTRAS FORMULAS
DE NEWTON-COTES
14.4
Otras f
ormulas de Newton-Cotes
Las formulas de Newton-Cotes se pueden clasificar en abiertas y cerradas. Las formulas del trapecio y de Simpson son casos particulares de
las formulas cerradas. En ellas se aproxima la integral en el intervalo
[x0 , xm ] usando el polinomio de interpolacion, de grado menor o igual a
m, construido a partir de los puntos (x0 , y0 ), (x1 , y1 ), ..., (xm1 , ym1 ),
(xm , ym ), igualmente espaciados en x.
Z
xm
x0
f (x)dx
xm
pm (x)dx.
x0
m
1
2
3
4
error
h
(y0 + y1 )
2
h
(y0 + 4y1 + y2 )
3
3h
(y0 + 3y1 + 3y2 + y3 )
8
2h
(7y0 + 32y1 + 12y2 + 32y3 + 7y4 )
45
f (z) 3
h
12
f (4) (z) 5
h
90
3 f (4) (z) 5
h
80
8 f (6) (z) 7
h
945
14.4.1
F
ormulas de Newton-Cotes abiertas
xm+2
x0
f (x)dx
xm+2
pm (x)dx,
x0
14.
Y DIFERENCIACION
INTEGRACION
paciados en x.
m
error
f (z) 3
h
3
3 f (z) 3
3h
(y1 + y2 )
+
h
2
4
4h
14 f (4) (z) 5
(2y1 y2 + 2y3 )
+
h
3
45
5h
95 f (4) (z) 5
(11y1 + y2 + y3 + 11y4 ) +
h
24
144
2h y1
1
2
3
0.8
0
ex dx
4 0.2
(2 e0.2 e0.4 + 2 e0.6 ) = 1.22539158 .
3
14.5
Cuadratura de Gauss
En las diferentes formulas de Newton-Cotes, los valores xi deben estar igualmente espaciados. Esto se presenta con frecuencia cuando se
dispone de una tabla de valores (xi , f (xi )). En la cuadratura de Gauss
se calcula la integral en un intervalo fijo [1, 1] mediante valores precisos pero no igualmente espaciados. Es decir, no se debe disponer de
una tabla de valores, sino que debe ser posible evaluar la funcion en
valores especficos.
326
(14.10)
i=1
Los valores wi se llaman los pesos o ponderaciones y los xi son las abscisas. Si se desea integrar en otro intervalo,
Z b
() d
a
2
( a) 1 ,
ba
Z
Z
Z
b
a
ba
() d =
2
() d
a
b
a
=
Z
(
1
n
baX
ba
(t + 1) + a ,
2
ba
dt
2
ba
(t + 1) + a) dt,
2
wi (
i=1
n
baX
d =
ba
(xi + 1) + a),
2
(14.11)
wi (i ),
(14.12)
ba
i =
(xi + 1) + a.
2
(14.13)
() d
i=1
i=1
1
1
xk dx =
si k es impar,
2
k+1
327
si k es par.
14.
Y DIFERENCIACION
INTEGRACION
1 dx = 2,
1
Z 1
x dx = 0.
x1 = 0.
(14.14)
wi = wn+1i .
Para n = 2,
w1 + w2 =
w 1 x1 + w 2 x2 =
w1 x21 + w2 x22 =
w1 x31 + w2 x32 =
1 dx = 2,
1
Z 1
1
Z 1
1
1
x dx = 0,
x2 dx =
x3 dx = 0.
Entonces
2w1 = 2,
2
2w1 x21 =
.
3
328
2
,
3
Finalmente,
r
1
,
w1 = 1,x1 =
3
r
1
w2 = 1,x2 =
.
3
Para n = 3,
w1 + w2 + w3 = 2,
w1 x1 + w2 x2 + w3 x3 = 0,
2
w1 x21 + w2 x22 + w3 x23 = ,
3
w1 x31 + w2 x32 + w3 x33 = 0,
2
w1 x41 + w2 x42 + w3 x43 = ,
5
w1 x51 + w2 x52 + w3 x53 = 0.
Por suposiciones de simetra,
x1 < 0 = x2 < x3 ,
x1 = x3 ,
w1 = w3 .
Entonces
2w1 + w2 = 2,
2
,
2w1 x21 =
3
2
.
2w1 x41 =
5
Finalmente,
r
5
3
w1 = ,x1 =
,
9
5
8
w2 = ,x2 = 0,
9
r
3
5
w3 = ,x3 =
.
9
5
329
14.
Y DIFERENCIACION
INTEGRACION
wi
xi
2
1
0.555555555555555
0.888888888888889
0.347854845137454
0.652145154862546
0
0.577350269189626
0.774596669241483
0
0.861136311594053
0.339981043584856
Tablas m
as completas se pueden encontrar en [Fro70] o en [AbS74].
Ejemplo 14.5. Calcular una aproximacion de
Z 0.8
ex dx
0.2
0.8
0.2
0.8 0.2 5 1 8 2 5 3
e dx
e + e + e
2
9
9
9
1.00413814737559
x
22n+1 (n!)4
f (2n) () ,
(2n + 1)((2n)!)3
1 < < 1 .
(14.15)
a < < b.
(14.16)
eSimpson =
eGauss3
Se observa que mientras que la formula de Simpson es exacta para polinomios de grado menor o igual a 3, la formula de Gauss es exacta hasta
para polinomios de grado 5. Sea 0 < h < 1. No s
olo h7 < h5 , sino que
el coeficiente 1/15750 es mucho menor que 1/90.
En el ejemplo anterior, h = 0.3, y tanto f (4) como f (6) varan en el
intervalo [1.22, 2.23 ].
eSimpson = 2.7 105 f (4) (z) ,
eGauss3 = 1.39 108 f (6) () .
14.5.1
Polinomios de Legendre
Las formulas de cuadratura vistas son las formulas de Gauss-Legendre. En ellas estan involucrados los polinomios ortogonales de Legendre. Tambien hay cuadratura de Gauss-Laguerre, de Gauss-Hermite y
de Gauss-Chebyshev, relacionadas con los polinomios de Laguerre, de
Hermite y de Chebyshev.
Hay varias maneras de definir los polinomios de Legendre; una de ellas
es:
P0 (x) = 1,
Pn (x) =
(14.17)
1
2n n!
d
(x2 1)n .
dxn
331
(14.18)
14.
Y DIFERENCIACION
INTEGRACION
Por ejemplo,
P0 (x) = 1,
P1 (x) = x,
1
P2 (x) = (3x2 1),
2
1
P3 (x) = (5x3 x),
2
1
P4 (x) = (35x4 30x2 + 3).
8
Tambien existe una expresi
on recursiva:
P0 (x) = 1,
(14.19)
P1 (x) = x,
2n + 1
n
Pn+1 (x) =
x Pn (x)
Pn1 (x) .
n+1
n+1
(14.20)
(14.21)
1
1
Pm (x)Pn (x) dx = 0 ,
1
Z 1
1
(Pn (x))2 dx =
m 6= n,
2n + 1
(14.23)
(14.24)
Las abscisas de las formulas de cuadratura de Gauss-Legendre son exactamente las races de Pn (x). Adem
as,
Z 1
Pn (x)
1
wi =
dx,
(14.25)
Pn (xi ) 1 x xi
1
2
wi =
(14.26)
(Pn (xi ))2 1 x2i
14.6
Derivaci
on num
erica
NUMERICA
14.6. DERIVACION
(y1 y0 )
(x x0 ) ,
h
(x) = (x x0 )(x x1 ) ,
p1 (x) =
(y1 y0 )
(x) = 2x 2x0 h
Entonces
(y1 y0 )
(y1 y0 ) h
+ (2x0 2x0 h)F (x0 ) =
f ((x0 )),
h
h
2
(y
y
)
h
(y
y
)
1
0
1
0
+ (2x1 2x0 h)F (x1 ) =
+ f ((x1 )).
f (x1 ) =
h
h
2
f (x0 ) =
En general,
(yi+1 yi )
h
f (), [xi , xi+1 ]
h
2
(y
y
)
h
i
i1
f (xi ) =
+ f (), [xi1 , xi ]
h
2
f (xi ) =
(14.27)
(14.28)
El primer termino despues del signo igual corresponde al valor aproximado. El segundo termino es el error. Se acostumbra decir que el error
es del orden de h. Esto se escribe
(yi+1 yi )
+ O(h),
h
(yi yi1 )
f (xi ) =
+ O(h).
h
f (xi ) =
333
14.
Y DIFERENCIACION
INTEGRACION
p2 (x1 ) =
2h
p2 (x) = y0 + sf0 +
y2 y0 h2
f () , [x0 , x2 ].
2h
6
De manera general,
yi+1 yi1 h2
f () , [xi1 , xi+1 ],
2h
6
yi+1 yi1
+ O(h2 ).
f (xi ) =
2h
f (xi ) =
(14.29)
En [YoG72], pagina 357, hay una tabla con varias formulas para diferenciaci
on numerica. Para la segunda derivada, una formula muy empleada
es:
yi+1 2yi + yi1 h2 (4)
f () , [xi1 , xi+1 ],
h2
12
yi+1 2yi + yi1
f (xi ) =
+ O(h2 ).
h2
f (xi ) =
(14.30)
NUMERICA
14.6. DERIVACION
2.0494 2
= 0.2470
0.2
2 1.9494
= 0.2532
f (4)
0.2
2.0494 1.9494
f (4)
= 0.2501
2 0.2
2.0494 2 2 + 1.9494
f (4)
= 0.0313 .
0.22
f (4)
Ejercicios
14.1 Calcule
ex dx
0.2
ex dx
335
14.
Y DIFERENCIACION
INTEGRACION
0.05
0.45
f (x)dx.
0.05
14.7 Considere los mismos puntos del ejercicio anterior. Calcule una
aproximacion de f (0.25), f (0.225), f (0.30).
14.8 Combine integracion numerica y solucion de ecuaciones para resolver
Z x
2
et dt = 0.1.
0
336
15
Ecuaciones diferenciales
Este captulo se refiere u
nicamente a ecuaciones diferenciales ordinarias. Generalmente una ecuaci
on diferencial ordinaria de primer orden
con condiciones iniciales, EDO1CI, se escribe de la forma
y = f (x, y) para a x b,
y(x0 ) = y0 .
(15.1)
Frecuentemente la condici
on inicial esta dada sobre el extremo izquierdo
del intervalo, o sea, a = x0 . Un ejemplo de EDO1CI es:
xy
+ 3x2 , x [2, 4],
1 + x2 + y 2
y(2) = 5.
y =
Temas importantsimos como existencia de la solucion, unicidad o estabilidad, no seran tratados en este texto. El lector debera remitirse a un
libro de ecuaciones diferenciales. Aqu se supondr
a que las funciones satisfacen todas las condiciones necesarias (continuidad, diferenciabilidad,
condici
on de Lipschitz... ) para que la solucion exista, sea u
nica...
Como en todos los otros casos de metodos numericos, la primera
opci
on para resolver una EDO1CI es buscar la solucion analtica. Si
esto no se logra, entonces se busca la solucion numerica que consiste en
encontrar valores aproximados y1 , y2 , ..., yn tales que
yi y(xi ), i = 1, ..., n, donde a = x0 < x1 < x2 < ... < xn = b.
337
15.
ECUACIONES DIFERENCIALES
ba
.
n
15.1
M
etodo de Euler
y(x0 + h) y(x0 )
.
h
(15.2)
Gr
aficamente esto significa que y(xi + h) = y(xi+1 ) se aproxima por el
valor obtenido a partir de la recta tangente a la curva en el punto (xi , yi ).
338
15.1. METODO
DE EULER
(x1 , y1 )
y(x0 + h)
y0 = y(x0 )
b
x0 + h
x0
(15.3)
yn = y(xn ) + O(h).
(15.4)
339
15.
ECUACIONES DIFERENCIALES
y = 2x2 4x + y
y(1) = 0.7182818
y1 = y0 + hf (x0 , y0 )
= 0.7182818 + 0.25f (1, 0.7182818)
= 0.7182818 + 0.25(0.7182818 + 2 12 4 1)
= 0.3978523
y2 = y1 + hf (x1 , y1 )
= 0.3978523 + 0.25f (1.25, 0.3978523)
= 0.3978523 + 0.25(0.3978523 + 2 1.252 4 1.25)
= 0.0285654
y3 = ...
xi
1.00
1.25
1.50
1.75
2.00
2.25
2.50
2.75
3.00
y(xi )
0.7182818
0.3978523
0.0285654
-0.3392933
-0.6428666
-0.8035833
-0.7232291
-0.2790364
0.6824545
340
y(xi )
0.7182818
0.3653430
-0.0183109
-0.3703973
-0.6109439
-0.6372642
-0.3175060
0.5176319
2.0855369
15.2. METODO
DE HEUN
2
1
b
b
b
0
b
b
b
b
b
15.2
M
etodo de Heun
y(x0 + h)
y0 = y(x0 )
(x1 , y1 )
x0 + h
x0
15.
ECUACIONES DIFERENCIALES
y(x + h) y(x) + h
y (x) + y (x + h)
2
y(x + h) y(x) + h
o sea,
y(x + h) y(x) + h
(15.5)
y = 2x2 4x + y
y(1) = 0.7182818
15.2. METODO
DE HEUN
K1 = hf (x0 , y0 )
= 0.25f (1, 0.7182818)
= 0.320430
K2 = hf (x0 + h, y0 + K1 )
= 0.25f (1.25, 0.397852)
= 0.369287
y1 = y0 + (K1 + K2 )/2
= 0.3734236
K1 = hf (x1 , y1 )
= 0.25f (1.25, 0.3734236)
= 0.375394
K2 = hf (x1 + h, y1 + K1 )
= 0.25f (1.500000, 0.001971)
= 0.375493
y2 = y1 + (K1 + K2 )/2
= 0.0020198
K1 = ...
xi
1.00
1.25
1.50
1.75
2.00
2.25
2.50
2.75
3.00
y(xi )
0.7182818
0.3734236
-0.0020198
-0.3463378
-0.5804641
-0.6030946
-0.2844337
0.5418193
2.0887372
343
y(xi )
0.7182818
0.3653430
-0.0183109
-0.3703973
-0.6109439
-0.6372642
-0.3175060
0.5176319
2.0855369
15.
ECUACIONES DIFERENCIALES
2
1
b
b
b
0
b
b
b
b
15.3
M
etodo del punto medio
15.3. METODO
DEL PUNTO MEDIO
y(x0 + h)
y0 = y(x0 )
(x1 , y1 )
x0 + h/2
x0
x0 + h
h
f (x, y)
2
h
f (x, y))
2
(15.6)
yi+1 = yi + K2 .
Ejemplo 15.3. Resolver, por el metodo del punto medio, la ecuaci
on
diferencial
y = 2x2 4x + y
y(1) = 0.7182818
345
15.
ECUACIONES DIFERENCIALES
K1 = hf (x0 , y0 )
= 0.25f (1, 0.7182818)
= 0.320430
y1 = y0 + K2
= 0.3656111
K1 = hf (x1 , y1 )
= 0.25f (1.25, 0.3656111)
= 0.377347
y2 = y1 + K2
= 0.0198420
K1 = ...
xi
1.00
1.25
1.50
1.75
2.00
2.25
2.50
2.75
3.00
y(xi )
0.7182818
0.3656111
-0.0198420
-0.3769851
-0.6275434
-0.6712275
-0.3795415
0.4121500
1.9147859
346
y(xi )
0.7182818
0.3653430
-0.0183109
-0.3703973
-0.6109439
-0.6372642
-0.3175060
0.5176319
2.0855369
15.4. METODO
DE RUNGE-KUTTA
2
b
1
b
b
b
0
b
b
b
15.4
M
etodo de Runge-Kutta
El metodo de Runge-Kutta o, m
as bien, los metodos de Runge-Kutta
se aplican a una EDO1CI como en (15.1) utilizando puntos igualmente
espaciados. La forma general del metodo RK de orden n es la siguiente:
K1 = hf (xi , yi )
K2 = hf (xi + 2 h, yi + 21 K1 )
K3 = hf (xi + 3 h, yi + 31 K1 + 32 K2 )
..
.
(15.7)
yi+1 = yi + R1 K1 + R2 K2 + ... + Rn Kn .
15.
ECUACIONES DIFERENCIALES
Metodo de Euler:
K1 = hf (xi , yi )
yi+1 = yi + K1 .
Metodo de Heun:
K1 = hf (xi , yi )
K2 = hf (xi + h, yi + K1 )
1
1
yi+1 = yi + K1 + K2 .
2
2
Metodo del punto medio:
K1 = hf (xi , yi )
1
1
K2 = hf (xi + h, yi + K1 )
2
2
yi+1 = yi + 0K1 + K2 .
(15.8)
K4 = hf (xi + h, yi + K3 )
yi+1 = yi + (K1 + 2K2 + 2K3 + K4 )/6.
Ejemplo 15.4. Resolver, por el metodo RK4 anterior, la ecuaci
on diferencial
y = 2x2 4x + y
y(1) = 0.7182818
348
15.4. METODO
DE RUNGE-KUTTA
K4 = hf (x0 + h, y0 + K3 )
= 0.25f (1.25, 0.361581)
= 0.378355
K4 = hf (x1 + h, y1 + K3 )
= 0.25f (1.5, 0.02117)
= 0.380294
15.
xi
1.00
1.25
1.50
1.75
2.00
2.25
2.50
2.75
3.00
ECUACIONES DIFERENCIALES
y(xi )
0.7182818
0.3653606
-0.0182773
-0.3703514
-0.6108932
-0.6372210
-0.3174905
0.5175891
2.0853898
y(xi )
0.7182818
0.3653430
-0.0183109
-0.3703973
-0.6109439
-0.6372642
-0.3175060
0.5176319
2.0855369
2
1
b
b
b
0
b
b
b
b
15.5
Deducci
on de RK2
DE RK2
15.5. DEDUCCION
g
g
(
u, v) + v (
u, v).
u
v
(15.9)
(15.10)
(15.11)
y (xi ) =
351
15.
ECUACIONES DIFERENCIALES
Entonces
y = fx + f fy
y(xi + h) y + hf +
h2
h2
fx + f fy .
2
2
(15.12)
(15.13)
R2 =
2
R1 = 1 R2 .
(15.14)
(15.15)
(15.16)
15.6
15.
ECUACIONES DIFERENCIALES
C0 = 2 (yA , yB , h, p)
C = (C0 , ...)
h = Ch.
Los diferentes algoritmos difieren en la manera de calcular e, C0 y
C (las funciones 1 , 2 y ). M
as a
un, para el mismo metodo A y el
mismo metodo B hay diferentes algoritmos.
Un metodo muy popular es el de Runge-Kutta-Fehlberg, construido a partir de un metodo de RK de orden 5 (el metodo A) y de un
metodo de RK de orden 6 (el metodo B). Una de sus ventajas esta dada
por el siguiente hecho: los valores K1 , K2 , K3 , K4 y K5 son los mismos
para los dos metodos. Teniendo en cuenta la forma general (15.7) del
metodo RK, basta con dar los valores i y ij . Recuerdese que siempre
K1 = hf (xi , yi ).
354
i
2
3
4
i1
1
4
3
8
12
13
1
4
3
32
1932
2197
439
216
8
27
1
2
i2
9
32
7200
2197
8
2
...
7296
2197
3680
513
3544
2565
845
4104
1859
4104
11
40
25
1408
2197
1
K1 + 0K2 +
K3 +
K4 K5
216
2565
4104
5
6656
28561
9
2
16
K1 + 0K2 +
K3 +
K4 K5 + K6
yB = yi +
135
12825
56430
50
55
(15.17)
yA = yi +
|yA yB |
.
h
(15.18)
1/4
e
C = min{C0 , 4},
,
(15.19)
C = max{C, 0.1}.
Las formulas anteriores buscan que C no sea muy grande ni muy peque
no.
M
as especficamente, C debe estar en el intervalo [0.1, 4].
355
15.
ECUACIONES DIFERENCIALES
En la descripci
on del algoritmo usaremos la siguiente notaci
on de
Matlab y de Scilab. La orden
u = [u; t]
significa que al vector columna u se le agrega al final el valor t y el
resultado se llama de nuevo u.
METODO
RUNGE-KUTTA-FEHLBERG
datos: x0 , y0 , b, h0 , , hmin
x = x0 , y = y0 , h = h0
X = [x0 ], Y = [y0 ]
mientras x < b
h = min{h, b x}
hbien = 0
mientras hbien = 0
calcular ya , yB seg
un (15.17)
e = |yA yB |/h
si e
x = x + h, y = yB
bienh = 1
X = [X; x], Y = [Y ; y]
fin-si
C0 = 0.84(/e)1/4
C = max{C0 , 0.1}, C = min{C, 4}
h = Ch
si h < hmin ent parar
fin-mientras
fin-mientras
La salida no deseada del algoritmo anterior se produce cuando h se
vuelve demasiado peque
no. Esto se produce en problemas muy difciles
cuando, para mantener el posible error dentro de lo establecido, ha sido
necesario disminuir mucho el valor de h, por debajo del lmite deseado.
En una versi
on ligeramente m
as eficiente, inicialmente no se calcula
yA ni yB . Se calcula directamente
1
128
2197
1
2
K1
K3
K4 + K5 + K6 .
e=
360
4275
75240
50
55
356
y(1) = 0.7182818
yB = 0.01830704
e = 0.00006717
h = 0.5 no sirve.
C0 = 0.29341805
C = 0.29341805
h = 0.14670902
yA = 0.51793321
yB = 0.51793329
e = 0.00000057
h = 0.14670902 sirve.
x = 1.14670902
y = 0.51793329
C0 = 0.96535578
C = 0.96535578
h = 0.14162640
yA = 0.30712817
yB = 0.30712821
e = 0.00000029
357
15.
ECUACIONES DIFERENCIALES
h = 0.14162640 sirve.
x = 1.28833543
y = 0.30712821
..
.
x
1.0000000
1.1467090
1.2883354
1.4505624
1.6192491
1.7525988
1.8855347
2.0046653
2.1139603
2.2163666
2.3134884
2.4062996
2.4954587
2.5814440
2.6646196
2.7452730
2.8236369
2.8999043
2.9742376
3.0000000
h
0.1467090
0.1416264
0.1622270
0.1686867
0.1333497
0.1329359
0.1191306
0.1092950
0.1024064
0.0971218
0.0928111
0.0891591
0.0859853
0.0831757
0.0806534
0.0783639
0.0762674
0.0743333
0.0257624
358
y(x)
0.7182818
0.5179333
0.3071282
0.0572501
-0.1946380
-0.3736279
-0.5206051
-0.6137572
-0.6566848
-0.6506243
-0.5948276
-0.4877186
-0.3273334
-0.1114979
0.1620898
0.4958158
0.8921268
1.3535162
1.8825153
2.0855366
y(x)
0.7182818
0.5179333
0.3071282
0.0572501
-0.1946380
-0.3736279
-0.5206051
-0.6137571
-0.6566847
-0.6506241
-0.5948275
-0.4877184
-0.3273332
-0.1114977
0.1620900
0.4958160
0.8921270
1.3535164
1.8825156
2.0855369
15.7. ORDEN DEL METODO
Y ORDEN DEL ERROR
2
b
1
b
b
b
b
b
b
b
b
b
b
b
b
Figura 15.8
15.7
Metodo de Runge-Kutta-Fehlberg.
Orden del m
etodo y orden del error
Para algunos de los metodos hasta ahora vistos, todos son metodos de
RK, se ha hablado del orden del metodo, del orden del error local y del
orden del error global.
El orden del metodo se refiere al n
umero de evaluaciones de la funcion
f en cada iteraci
on. As por ejemplo, el metodo de Euler es un metodo
de orden 1 y el metodo de Heun es un metodo de orden 2.
El orden del error local se refiere al exponente de h en el error te
orico
cometido en cada iteraci
on. Si la formula es
15.
ECUACIONES DIFERENCIALES
Metodo
Formula
Orden del
metodo
Error
local
Euler
(15.2)
O(h2 )
Heun
(15.5)
O(h3 )
Punto medio
(15.6)
O(h3 )
RK4
(15.8)
O(h5 )
RK5
(15.17)
O(h5 )
RK6
(15.17)
O(h6 )
15.7.1
Verificaci
on num
erica del orden del error
(15.20)
15.7. ORDEN DEL METODO
Y ORDEN DEL ERROR
y(1) = 0.7182818,
con h = 0.1, 0.12, 0.14, 0.16, 0.18 y 0.2.
h x0 + h y(x0 + h) y(x0 + h)
0.10 1.10
0.584701 0.584166
0.12 1.12
0.556975 0.556054
0.14 1.14
0.529024 0.527568
0.16 1.16
0.500897 0.498733
0.18 1.18
0.472641 0.469574
0.20 1.20
0.444304 0.440117
e
0.000535
0.000921
0.001456
0.002164
0.003067
0.004187
log(h)
-2.302585
-2.120264
-1.966113
-1.832581
-1.714798
-1.609438
log(e)
-7.532503
-6.989970
-6.532007
-6.135958
-5.787212
-5.475793
En la siguiente gr
afica, log(h) en las abscisas y log(e) en las ordenadas, los puntos estan aproximadamente en una recta.
5
b
b
b
b
7
8
2.5
2.0
1.5
15.
15.8
ECUACIONES DIFERENCIALES
M
etodos multipaso explcitos
p2 (x) = f0
(x 0)(x 2h)
(x 0)(x h)
(x h)(x 2h)
+ f1
+ f2
.
(0 h)(0 2h)
(h 0)(h 2h)
(2h 0)(2h h)
p2 (x) =
1
2
2
.
(f
2f
+
f
)x
+
(3f
+
4f
f
)hx
+
2h
f
0
1
2
0
1
2
0
2h2
x3
x2
x2
3h
f (x, y)dx.
2h
15.8. METODOS
MULTIPASO EXPLICITOS
3h
p2 (x)dx
Z 3h
1
(f0 2f1 + f2 )x2 +
y(x3 ) y(x2 ) +
2
2h 2h
y(x3 ) y(x2 ) +
2h
(15.21)
La anterior igualdad se conoce con el nombre de formula de AdamsBashforth de orden 2 (se utiliza un polinomio de orden 2). Tambien
recibe el nombre de metodo multipaso explcito o metodo multipaso
abierto de orden 2.
Si los valores y0 , y1 y y2 son exactos, o sea, si y0 = y(x0 ), y1 = y(x1 )
y y2 = y(x2 ), entonces los valores fi son exactos, o sea, f (xi , yi ) =
f (xi , y(xi )) y el error esta dado por
y(x3 ) = y(x2 ) +
h
3
(5f0 16f1 + 23f2 ) + y (3) (z)h4 , z [x0 , x3 ].
12
8
(15.22)
h
(5fi2 16fi1 + 23fi ).
12
(15.23)
15.
ECUACIONES DIFERENCIALES
2, la ecuaci
on diferencial
y = 2x2 4x + y
y(1) = 0.7182818
en el intervalo [1, 3], con h = 0.25.
f1 = f (x1 , y1 ) = 1.5096394
f2 = 1.5182773
f3 = f (x3 , y3 ) = 1.2510843
y4 = 0.6267238
..
.
xi
1.00
1.25
1.50
1.75
2.00
2.25
2.50
2.75
3.00
y(xi )
0.7182818
0.3653606
-0.0182773
-0.3760843
-0.6267238
-0.6681548
-0.3706632
0.4320786
1.9534879
364
y(xi )
0.7182818
0.3653430
-0.0183109
-0.3703973
-0.6109439
-0.6372642
-0.3175060
0.5176319
2.0855369
15.8. METODOS
MULTIPASO EXPLICITOS
2
b
1
b
b
b
0
b
b
b
b
1
Figura 15.10
Metodo de Adams-Bashforth 2.
En este caso hubo que evaluar 8 veces la funcion para los dos valores
de RK4 y en seguida 6 evaluaciones para un total de 14 evaluaciones de
la funcion f .
MULTIPASO EXPLICITO: ADAMS-BASHFORTH
n
error
1
2
2 y ()h
yi+1 = yi + hfi
yi+1 = yi +
h
(fi1 + 3fi )
2
5
3
12 y ()h
yi+1 = yi +
h
(5fi2 16fi1 + 23fi )
12
3 (4)
4
8 y ()h
yi+1 = yi +
h
(9fi3 + 37fi2 59fi1 + 55fi )
24
251 (5)
5
720 y ()h
yi+1 = yi +
h
(251fi4 1274fi3 + 2616fi2
720
95 (6)
6
288 y ()h
2774fi1 + 1901fi )
En la anterior tabla se muestran las principales formulas. All n
indica el grado del polinomio de interpolacion usado. En algunos li365
15.
ECUACIONES DIFERENCIALES
15.9
M
etodos multipaso implcitos
x2
x1
x1
2h
f (x, y)dx.
h
y(x2 ) y(x1 ) +
y(x2 ) y(x1 ) +
2h
h
Z 2h
h
p2 (x)dx
1
(f0 2f1 + f2 )x2 +
2h2
2
15.9. METODOS
MULTIPASO IMPLICITOS
7
1
y2 = y1 + 2 (f0 2f1 + f2 ) h3 +
2h
3
3 3
3
(3f0 + 4f1 f2 ) h + 2h f0
2
h
y2 = y1 + (f0 + 8f1 + 5f2 ).
12
(15.24)
La anterior igualdad se conoce con el nombre de formula de AdamsMoulton de orden 2 (se utiliza un polinomio de orden 2). Tambien
recibe el nombre de metodo multipaso implcito o metodo multipaso
cerrado de orden 2.
Si los valores y0 , y1 y y2 son exactos, o sea, si y0 = y(x0 ), y1 = y(x1 )
y y2 = y(x2 ), entonces los valores fi son exactos, o sea, f (xi , yi ) =
f (xi , y(xi )) y el error esta dado por
y(x2 ) = y(x1 ) +
h
1 (3)
(f0 + 8f1 + 5f2 )
y (z)h4 , z [x0 , x2 ].
12
24
(15.25)
Una dificultad m
as grande, y especfica de los metodos implcitos,
esta dada por el siguiente hecho: para calcular yi+1 se utiliza fi+1 , pero
este valor es justamente f (xi+1 , yi+1 ). Como salir de este crculo vi0 , una primera aproximaci
on, por el
cioso? Inicialmente se calcula yi+1
0
0 )
metodo de Euler. Con este valor se puede calcular fi+1
= f (xi+1 , yi+1
1
1
1
y en seguida yi+1 . De nuevo se calcula fi+1 = f (xi+1 , yi+1 ) y en seguida
2 . Este proceso iterativo acaba cuando dos valores consecutivos, y k
yi+1
i+1
k+1
y yi+1
, son muy parecidos. Este metodo recibe tambien el nombre de
metodo predictor-corrector. La formula queda entonces as:
k+1
= yi +
yi+1
h
k
(fi1 + 8fi + 5fi+1
).
12
367
(15.27)
15.
ECUACIONES DIFERENCIALES
max{1, |yik+1 |}
y(1) = 0.7182818
f1 = f (x1 , y1 ) = 1.5096394
f20 = 1.5120493
Empiezan las iteraciones:
y21 = 0.0170487
f21 = 1.5170487
y22 = 0.0175694
f22 = 1.5175694
y23 = 0.0176237 = y2
f2 = 1.5176237.
368
15.9. METODOS
MULTIPASO IMPLICITOS
y30 = 0.3970296
f30 = 1.2720296
y31 = 0.3716132
f31 = 1.2466132
y32 = 0.3689657
f32 = 1.2439657
y33 = 0.3686899
f33 = 1.2436899
y34 = 0.3686612 = y3
..
.
xi
1.00
1.25
1.50
1.75
2.00
2.25
2.50
2.75
3.00
y(xi )
0.7182818
0.3653606
-0.0176237
-0.3686612
-0.6076225
-0.6315876
-0.3084043
0.5316463
2.1065205
369
y(xi )
0.7182818
0.3653430
-0.0183109
-0.3703973
-0.6109439
-0.6372642
-0.3175060
0.5176319
2.0855369
15.
ECUACIONES DIFERENCIALES
2
1
b
b
b
0
b
b
b
b
error
h
(fi + fi+1 )
2
h
= yi + (fi1 + 8fi + 5fi+1 )
12
h
= yi + (fi2 5fi1 + 19fi + 9fi+1 )
24
h
= yi +
(19fi3 + 106fi2 264fi1
720
yi+1 = yi +
yi+1
yi+1
yi+1
+646fi + 251fi+1 )
370
1
y ()h3
12
1 (3)
24
y ()h4
19 (4)
y ()h5
720
27 (5)
y ()h6
1440
15.10.
15.10
y(x0 ) = y 0 .
371
15.
ECUACIONES DIFERENCIALES
(15.28)
K = hf (xi + h, y + K )
y i+1 = y i + (K 1 + 2K 2 + 2K 3 + K 4 )/6.
Ejemplo 15.9. Resolver el siguiente sistema de ecuaciones por RK4:
2y1
+ x 3 y2 , 1 x 2
x
3
y2 = y2
x
y1 (1) = 1
y1 =
y2 (1) = 1
con h = 0.2.
y2 (x) = x3 .
372
15.11.
K 1 = (0.2, 0.6)
K 2 = (0.2136600, 0.3818182)
K 3 = (0.1871036, 0.4413223)
K 4 = (0.2026222, 0.2793388)
y 1 = (1.2006916, 0.5790634)
K 1 = (0.2001062, 0.2895317)
K 2 = (0.2093988, 0.2004450)
K 3 = (0.1912561, 0.2210035)
K 4 = (0.2011961, 0.1534542)
y 2 = (1.4011269, 0.3647495)
..
.
xi
1.0
1.2
1.4
1.6
1.8
2.0
15.11
y1 (xi )
-1.0
-1.2006916
-1.4011269
-1.6014497
-1.8017156
-2.0019491
y2 (xi )
1.0
0.5790634
0.3647495
0.2443822
0.1716477
0.1251354
y1 (xi )
-1.0
-1.2
-1.4
-1.6
-1.8
-2.0
y2 (xi )
1.0
0.5787037
0.3644315
0.2441406
0.1714678
0.125
Una ecuaci
on diferencial ordinaria, de orden m, con condiciones iniciales,
se puede escribir de la siguiente manera:
373
15.
ECUACIONES DIFERENCIALES
x0 x b
y (x0 ) = y0
y (x0 ) = y0
..
.
(m1)
y (m1) (x0 ) = y0
Esta ecuaci
on diferencial se puede convertir en un sistema de ecuaciones
diferenciales de primer orden, mediante el siguiente cambio de variables:
u1 = y
u2 = y
u3 = y
..
.
um = y (m1)
Entonces la ecuaci
on diferencial se convierte en el siguiente sistema:
u1 = u2
u2 = u3
u3 = u4
..
.
um1 = um
um = f (x, u1 , u2 , ..., um )
u1 (x0 ) = y0
u2 (x0 ) = y0
u3 (x0 ) = y0
..
.
(m1)
um (x0 ) = y0
De forma m
as compacta,
u = F (x, u), x0 x b
u(x0 ) = 0 ,
374
15.11.
(m1)
y (1) = 10,
por el metodo RK4, con h = 0.2.
Sean u1 = y, u2 = y .
u1 = u2
4u1 xu2
u2 =
, 1 x 2,
x2
u1 (1) = 3
u2 (1) = 10.
La solucion exacta es y = 4x2 x2 . Al aplicar el metodo RK4 se
obtiene:
K 1 = (2, 0.4)
K 2 = (2.04, 0.7900826)
K 3 = (2.0790083, 0.7678437)
K 4 = (2.1535687, 1.0270306)
u1 = (5.0652642, 10.7571472)
..
.
xi
1.0
1.2
1.4
1.6
1.8
2.0
u
1 (xi )
3.0
5.0652642
7.3293797
9.8488422
12.65069
15.749173
u
2 (xi )
10.0
10.757147
11.928367
13.287616
14.742141
16.249097
375
y(xi )
3.0
5.0655556
7.3297959
9.849375
12.651358
15.75
15.
15.12
ECUACIONES DIFERENCIALES
Una ecuaci
on diferencial de segundo orden con condiciones de frontera
se puede escribir de la forma
y = f (x, y, y ), a x b,
y(a) = ya
(15.29)
y(b) = yb .
Esta ecuaci
on diferencial se puede convertir en un sistema de dos ecuaciones diferenciales, pero para obtener su solucion numerica se presenta
un inconveniente: se debera conocer el valor ya = y (a). Esta dificultad
se supera mediante el m
etodo del disparo (shooting).
Como no se conoce ya , se le asigna un valor aproximado inicial.
Puede ser
yb ya
ya
.
ba
Con este valor inicial se busca la solucion numerica, hasta obtener
y(b) = y(b, ya ).
Este valor debera ser el valor conocido yb . Si no coinciden, es necesario
modificar la suposicion de ya hasta obtener el resultado deseado. Si
y(b, ya ) < yb , entonces se debe aumentar la pendiente inicial del disparo.
De manera an
aloga, si y(b, ya ) > yb , se debe disminuir la pendiente
inicial del disparo. Lo anterior se puede presentar como la solucion de
una ecuaci
on:
(ya ) = yb y(b, ya ) = 0.
Esta ecuaci
on se puede resolver, entre otros metodos, por el de la secante
o el de biseccion.
376
15.12.
y(a) = ya
P(v)
y (a) = v,
(v) = yb yn = yb y(b, v).
(15.30)
METODO
DEL DISPARO
datos: f , a, b, ya , yb , , maxit, 0
r = max{1, |yb |}
v0 = (yb ya )/(b a)
y = solucion numerica de P(v0 )
0 = yb yn
si |0 | r ent parar
v1 = v0 + 0 /(b a)
y = solucion numerica de P(v1 )
1 = yb yn
si |1 | r ent parar
para k = 1, ...,maxit
= 1 0
si || 0 ent parar
v2 = v1 1 (v1 v0 )/
y = solucion numerica de P(v2 )
2 = yb yn
si |2 | r ent parar
v 0 = v 1 , v 1 = v 2 , 0 = 1 , 1 = 2
fin-para
OJO: no hubo convergencia.
377
15.
ECUACIONES DIFERENCIALES
y(0.7) = 0.9854497,
con h = 0.1 y utilizando RK4 para la solucion del sistema de ecuaciones
diferenciales asociado.
La primera aproximacion de y (a) es
v0 = (0.9854497 0.3894183)/(0.7 0.2) = 1.19206278
Al resolver numericamente el problema P(1.19206278) se obtiene:
y5 = 0.94935663.
El disparo resulto muy bajo.
0 = 0.03609310
v1 = 1.19206278 + 0.03609310/(0.7 0.5) = 1.26424897
Al resolver numericamente el problema P(1.26424897) se obtiene:
y5 = 0.95337713
1 = 0.03207260
Primera iteraci
on del metodo de la secante:
v2 = 1.84009748
Al resolver numericamente el problema P(1.84009748) se obtiene:
y5 = 0.98544973
Este disparo fue preciso (no siempre se obtiene la solucion con una sola
iteraci
on de la secante). El u
ltimo vector y es la solucion. La solucion
exacta es y = sen(2x).
378
15.13.
xi
0.2
0.3
0.4
0.5
0.6
0.7
15.13
y(xi )
0.3894183
0.5647741
0.7174439
0.8415217
0.9320614
0.9854497
y(xi )
0.3894183
0.5646425
0.7173561
0.8414710
0.9320391
0.9854497
Una ecuaci
on diferencial lineal de segundo orden con condiciones de
frontera se puede escribir de la forma
p(x)y + q(x)y + r(x)y = s(x), a x b,
y(a) = ya
(15.31)
y(b) = yb .
Obviamente esta ecuaci
on se puede resolver por el metodo del disparo,
pero, dada la linealidad, se puede resolver usando aproximaciones numericas
(diferencias finitas) para y y y .
El intervalo [a, b] se divide en n 2 subintervalos de tama
no h =
(b a)/n. Los puntos xi estan igualmente espaciados (xi = a + ih). Se
utilizan las siguientes aproximaciones y la siguiente notaci
on:
yi1 2yi + yi+1
h2
yi1 + yi+1
yi
2h
pi := p(xi )
yi
qi := q(xi )
ri := r(xi )
si := s(xi ).
Entonces:
pi
15.
ECUACIONES DIFERENCIALES
d1 u1
l1 d2 u2
l2 d3 u3
y1
y2
y3
1
2
3
=
, (15.32)
un2
yn2
n2
ln3 dn2
ln2 dn1
yn1
n1
donde
di = 4pi + 2h2 ri ,
i = 1, ..., n 1,
li = 2pi+1 hqi+1 ,
i = 1, ..., n 2,
ui = 2pi + hqi ,
i = 1, ..., n 2,
i = 2, ..., n 2,
y(0.7) = 0.9854497,
con n = 5, es decir, h = 0.1.
380
15.13.
u1 = 2p1 + hq1
y(xi )
0.3894183
0.5628333
0.7158127
0.8404825
0.9315998
0.9854497
y(xi )
0.3894183
0.5646425
0.7173561
0.8414710
0.9320391
0.9854497
Ejercicios
Escoja varias ecuaciones diferenciales (o sistemas de ecuaciones
diferenciales) de las que conozca la solucion exacta. Fije el intervalo de trabajo. Determine que metodos puede utilizar. Aplique
varios de ellos. Compare los resultados. Cambie el tama
no del
paso. Compare de nuevo.
Un procedimiento adecuado para obtener las ecuaciones diferenciales consiste en partir de la solucion (una funcion cualquiera) y
construir la ecuaci
on diferencial.
381
15.
ECUACIONES DIFERENCIALES
y
x
y(1) = 0.
Su solucion es y = ex
ex
x
15.2
y1 = 2y1 + y2 + 3
y2 = 4y1 y2 + 9
y1 (0) = 3
y2 (0) = 5.
y (1) = 1.
15.13.
15.5
y y = e2x sen2 (x)
y(0) = 1
y() = e .
Su solucion es y = ex + sen(x).
15.6
y + ex y + y = 2ex + 1 + ex cos(x)
y(0) = 1
y() = e .
Su solucion es y = ex + sen(x).
383
15.
ECUACIONES DIFERENCIALES
384
BIBLIOGRAFIA
[AbS74] Abramowitz Milton. y Stegun Irene A. (eds.), Handbook of
Mathematical Functions, Dover, New York, 1974.
[Atk98] Atkinson Kendall E., An Introduction to Numerical Analysis,
Wiley, New York, 1978.
[BaN94] Barton John J. y Nackman Lee R., Scientific and Engineering
C++, Addison-Wesley, Reading, 1994.
[Ber01] Berryhill John R., C++ Scientific Programming, Wiley, Nueva
York, 2001.
[Bra00] Braquelaire Jean-Pierre, Methodologie de la programmation en
C, Dunod, Pars, 2000.
[Bro00] Bronson Gary J., C++ para ingeniera y ciencias, Int. Thomson, Mexico, 2000.
[BuF85] Burden Richard L. y Faires J. Douglas, Numerical Analysis,
3a. ed., Prindle-Weber-Schmidt, Boston, 1985.
[Buz93] Buzzi-Ferraris Guido, Scientific C++, Building Numerical Libraries the Object-Oriented Way, Addison-Wesley, Wokingham,
Inglaterra, 1993.
[ChC99] Chapra Steven C. y Canale Raymond P., Metodos Numericos
para Ingenieros, 3 ed., McGraw-Hill, Mexico, 1999.
[Cap94] Capper Derek M., Introducing C++ for Scientists, Engineers
and Mathematicians, Springer-Verlag, Londres, 1994.
385
BIBLIOGRAFIA
BIBLIOGRAFIA
Manual de referencia,
387
BIBLIOGRAFIA
388
Ap
endice A
Estilo en C
Para que la lectura de un programa en C sea m
as facil para el mismo
programador o para otros lectores, es conveniente tener ciertas reglas
sobre la manera de escribir, de hacer sangras, de separar las funciones,
etc. Esta reglas no son absolutamente fijas y cada programador establece
su propio estilo. Hay unos estilos que son m
as claros y dicientes que
otros. Algunos son ventajosos en ciertos aspectos y desventajosos en
otros. Otros son diferentes pero comparables. Algunas reglas son m
as
universales y populares que otras.
Las siguientes normas sirven de modelo o referencia y fueron utilizadas en la elaboracion de los ejemplos en C de este libro.
A.1
Generalidades
APENDICE
A. ESTILO EN C
...
// fin de factorial
}
El corchete de inicio de un bloque dentro de una estructura de
control debe ir en la misma lnea de la condici
on.
En la lnea de corchete correspondiente al final de un bloque en una
estructura de control no debe haber nada m
as, salvo un comentario
indicando que tipo de estructura finaliza o cu
al variable de control
se us
o, cuando la estructura de control tiene muchas lneas. Por
ejemplo:
...
for( i = ... ){
...
while( ... ){
...
...
for( j = ... ){
...
}
...
...
} // fin while
...
...
} // fin i
No escribir m
as all
a de la columna 72 (excepcionalmente, hasta la
80).
Las estructuras de control anidadas dentro de otras deben incrementar la sangra. Cada vez que hay incremento en la sangra,
esta debe estar dada siempre por un n
umero fijo de columnas a lo
largo de todo el programa. Este valor fijo puede ser 2, 3 o 4. Es
preferible hacerlo con espacios y no con el tabulador.
390
A.1. GENERALIDADES
Libros importantsimos de C++ como [Str02] (libro obligado de referencia), aconsejan justamente lo contrario, es decir, sugieren declarar las variables en el momento
que se van a necesitar, por ejemplo, for( int i = 0; i < n; i++)...
391
APENDICE
A. ESTILO EN C
Los nombres de las variables, deben ser indicativos de su significado. Cuando hay varias palabras, estas se separan con el signo _
o por medio de una may
uscula al empezar la nueva palabra. Por
ejemplo, para el peso especfico:
pe
peso_esp
pesoEsp
no es muy diciente
puede ser
puede ser
A.2. EJEMPLO
A.2
Ejemplo
APENDICE
A. ESTILO EN C
...
...
...
if(...){
...
...
...
}
...
}
}
}
}
//================================================
void funcion1( ... )
{
// comentarios
// mas comentarios
int m, n;
float u; // indica ...
...
...
}
//-----------------------------------------------double funcion2( ... )
{
// comentarios
// mas comentarios
int i, j;
double x; // x indica ...
double zz; // indica ...
394
...
...
}
A.3
Estructuras de control
if( ... ) {
...
...
...
}
else {
...
...
...
}
if( ... ) ... ;
else ... ;
if( ... ) ... ;
else {
...
...
...
}
if( ... ){
...
...
...
}
else ... ;
if( ... ){
...
...
395
APENDICE
A. ESTILO EN C
...
}
...
for( ... ) {
...
...
...
}
for( ... ) ...;
while( ... ) {
...
...
...
}
while( ... ) ... ;
do {
...
...
...
} while ( ... );
switch( i ) {
case 1:
...
...
...
break;
case 4:
...
396
...
...
break;
case 8: case 9:
...
...
...
break;
default:
...
...
...
}
397
INDICE ANALITICO
||, 45
&, 31, 78, 79, 109
&&, 45
\0, 98
(double), 36
(float), 37
(int), 37
*, 22, 78, 109
**, 116
*=, 27
+, 22
++, 22, 24
+=, 27
-, 22, 23
--, 22, 25
-=, 27
/, 22
/=, 27
<, 45
<<, 8
<=, 45
=, 21
==, 45
>, 45
>=, 45
>>, 33
?, 171, 173
%, 22, 23
%c, 31
%d, 31
%e, 31
%f, 31
%i, 31
%lf, 31
%p, 31, 110
%s, 31, 99
%u, 31
\n, 7
a, 145
abreviaciones, 27
acos, 29
Adams-Bashforth
formula de, 363
Adams-Moulton
formula de, 367
adicion, 22
algoritmo
de Euclides, 54
alloc.h, 85
ambito
global, 82
local, 82
ANSI C, 70
aproximacion, 285
aproximacion por mnimos cuadrados, 306
apuntador, 78
apuntadores, 109
a apuntadores, 116
a estructuras, 177, 180
398
INDICE ANALITICO
a funciones, 165
dobles, 116
dobles y matrices, 135
y arreglos bidimensionales, 116
y arreglos unidimensionales, 111
archivo
de texto, 145
texto, 145
argc, 172, 173
argumento, 68
argumentos de main, 171
argv, 172, 173
arreglos, 87
a partir de 1, 139
aleatorios, 129
bidimensionales, 87, 94
y apuntadores, 116
como par
ametros, 94, 97
como par
ametros, 88
de estructuras, 177, 180
multidimensionales, 94
unidimensionales, 87
y apuntadores, 111
y matrices, 117
ASCII, 5
asignaci
on din
amica de memoria,
131
para estructuras, 177, 180
asin, 29
asm, 17
asociatividad, 25
de derecha a izquierda, 25
de izquierda a derecha, 25
atan, 29
auto, 17
base, 287, 307
biblioteca estandar, 85
bloque, 43
bloque de sentencias, 43
Borland, 70
break, 17, 58
bucle, 48
burbuja, metodo, 194
%c, 31
cadena de formato, 31
cadenas, 98
cambio de signo, 23
caracteres, 19
case, 17, 57
catch, 17
ceil, 29
char, 17, 19, 20, 31, 158
cin, 33
class, 17
codigo, 5
comentario, 15
compilador, 5
complejo, 175
complejos, 176
complex.h, 85
condiciones de frontera
ecuaciones diferenciales con, 376
ecuaciones diferenciales lineales
con, 379
conio.h, 70
const, 17, 159
continue, 17, 60
control del paso, 353
convergencia
cuadratica, 262
lineal, 262
conversiones de tipo en expresiones
mixtas, 35
cos, 29
coseno, 53
cosh, 29
399
INDICE ANALITICO
cout, 8, 33
ecuaciones
ctype.h, 85
diferenciales ordinarias, 337
cuadratura
ecuaciones diferenciales
de Gauss, 326
con condiciones de frontera, 376
de Gauss-Legendre, vease cuadraturade orden superior, 373
de Gauss
lineales con condiciones de froncuerpo de una funcion, 69
tera, 379
sistemas de, 371
%d, 31
ecuaciones normales, 247
decremento, 25
else, 17, 41
default, 17
encadenamiento, 6
#define, 164
endl, 8
delete, 17, 132
enlace, 6
densidad, 254
entrada de datos, 30
derivaci
on
enum, 17
numerica, 332
EOF, 35, 148
derivadas parciales, 246
errno.h, 85
desviacion estandar, 148
error, 331
determinante, 229
de compilaci
on, 5
diagonal estrictamente dominante
de ejecuci
on, 6
por filas, 242
global, 317, 318, 320, 323, 339
diferencias
orden del, 359
divididas de Newton, 293
local, 317, 320, 339
finitas, 302
metodo de Euler, 360
diferencias finitas, 379
metodo de Heun, 360
diferente, 45
metodo del punto medio, 360
distancia entre dos vectores, 183
metodo RK4, 360
divisi
on, 22
metodo RK5, 360
entre enteros, 23
metodo RK6, 360
sintetica, 134
orden del, 359
do, 17
metodo de Euler, 339
do while, 54, 58, 60
orden del, 359
doble precisi
on, 19
escritura
double, 17, 19, 20, 31, 36, 158
de un vector, 89, 91, 117, 120
double( ), 37
en un archivo, 150152
(double), 36
de una matriz, 94, 97, 117, 120
en un archivo, 152, 154
%e, 31
ecuaci
on cuadratica, 43
en archivos, 143
400
INDICE ANALITICO
esquema de H
orner, 134
estructura
devuelta por una funcion, 177,
180
estructuras, 175
como par
ametros, 177, 180
estructuras de control, 41
Euler
metodo de, 338, 348
orden del metodo de, 360
exit, 61
exp, 29
extern, 17, 173
INDICE ANALITICO
INDICE ANALITICO
de columnas, 32
de operaciones, 203, 211, 235
n
umeros
enteros, 19
reales, 19
o, 45
operaciones elementales con vectores,
183
operador
de asignaci
on, 21
unario, 24
operadores
l
ogicos, 45
relacionales, 45
operadores aritmeticos, 22
operator, 17
orden
del error, 359
verificacion numerica, 360
del error global, 359
del error local, 359
del metodo, 359
de Euler, 360
de Heun, 360
del punto medio, 360
RK4, 360
RK5, 360
RK6, 360
orden de convergencia, 262, 264
ordenamiento, 194
overflow, 75
%p, 31, 110
palabra clave, 16
par
ametro, 68
por defecto, 81
por referencia, 7678, 88
por valor, 76, 77
403
INDICE ANALITICO
pausa, 70
pivote, 217
pivoteo
parcial, 217
total, 218
polinomios
de Legendre, 331
polinomios de Lagrange, 290
pow, 29
precedencia de los operadores
aritmeticos, 25
precisi
on
doble, 19
sencilla, 19
printf, 7
prioridad de los operadores aritmeticos, 25
private, 17
producto
de complejos, 177, 180
de matrices, 94, 97, 117, 120
123, 125, 128, 129
escalar, 126, 128, 183
programa
ejecutable, 6
fuente, 5
promedio, 89, 91, 113, 115, 148
protected, 17
prototipo, 68
public, 17
punteros, vease apuntadores
punto flotante, 19
punto medio
metodo del, 344, 348
orden del metodo de, 360
r, 145
r+, 145
RAND_MAX, 130
404
rand(), 130
Raphson, vease metodo de NewtonRaphson
register, 17
residuo entero, 23
return, 17
RK, vease metodo de Runge-Kutta
RK4, vease metodo RK4
RKF, vease Runge-Kutta-Fehlberg
Runge-Kutta
metodo de, 347
Runge-Kutta-Fehlberg
metodo de, 354, 356
%s, 31, 99
salida de resultados, 30
scanf, 30, 34
Scilab, 200
Seidel, vease metodo de Gauss-Seidel
serie de Taylor, 51, 53
seudosolucion, 248
short, 17
short int, 36, 158
signed, 17
sin, 29
sinh, 29
sistema
diagonal, 202
triangular inferior, 206
triangular superior, 202
sistemas
de ecuaciones diferenciales, 371
sizeof, 17, 132, 157, 158
sobrecarga de funciones, 83
solucion
de ecuaciones, 255
de sistemas lineales, 199
de un sistema
diagonal, 202
INDICE ANALITICO
devuelto, 69
dominante, 70
propio, 228
variables
globales, 82
locales, 82
vectores
almacenados con salto, 184, 190
virtual, 17
void, 7, 17
volatile, 17
w, 145
while, 17, 51, 58, 60
y, 45
tabla
de diferencias divididas, 296
de diferencias finitas, 302
tan, 29
tanh, 29
tasa de convergencia, 262
template, 17
this, 17
throw, 17
time.h, 85
tipos de datos, 19
triangularizacion, 206, 209, 211
try, 17
typedef, 17, 159
%u, 31
union, 17
unsigned, 17, 20
unsigned int, 21
valor
405