Sie sind auf Seite 1von 428

UNIVERSIDAD

~~ NACIONAL
DE COLOMBIA
Sede Bogot

coleccin textos
HCTOR MANUEL MORA ESCOBAR

es Matemtico e Ingeniero Civil de la Universidad

Nacional de Colombia. En la Universit de Nancy en '

Francia obtuvo el DEA, Diplme d'tudes Approfondies, y

el Doctorat de 3eme Cycle en Matemticas Aplicadas.

Desde 1975 es docente de la Universidad Nacional de

Colombia, actualmente se desempea como Profesor

Titular del Departamento de Matemticas. Ha publicado

varios libros y artculos sobre optimizacin, mtodos

numricos y prospectiva. Es miembro de las siguientes

sociedades: Sociedad Colombiana de Matemticas, Society

for Industrial and Applied Mathematics, Societ de

Mathmatiques Appliques et Industrielles, Mathematical

Progamming Society y Sociedad Colombiana de

Investigacin de Operaciones.
Introduccin a e
y a mtodos numricos
Hctor Manuel Mora Escobar
Profesor del Departamento de Matemticas
Facultad de Ciencias, Universidad Nacional de Colombia

Introduccin a e
y a mtodos numricos

Universidad Nacional de Colombia


FACULTAD DE CIENCIAS
BOGOT
Universidad Nacional de Colombia
Facultad de Ciencias
Departamento de Matemticas y Estadstica

Hctor Manuel Mora Escobar

Primera edicin, 2004


Bogot, Colombia, 2004

UNIBIBLOS
Director general
Ramn Fayad Naffah

Coordinaci6n editorial
Dora Ins Perilla Castillo

Revisi6n editorial
Osear Torres

Preparaci6n editorial e impresi6n


Universidad Nacional de Colombia, Unibiblos
dirunibiblo_bog@unal.edu.co

Cartula
Camilo Umaa

ISBN 958-701-363-8
ISBN 958-701-138-4
(obra completa)

Catalogacin en la publicacin Universidad Nacional de Colombia


Mora Escobar, Hctor Manuel, 1953-

Introduccin a C y a mtodos numricos 1 Hctor Manuel Mora Escobar -


Bogot: Universidad Nacional de Colombia. Facultad de Ciencias, 2004
408 p.

ISBN: 958-701-363-8
1.Anlisis numrico 2.C (Lenguaje de programacin para computadores)
3. Matemticas aplicadas
CDD-21 519.41 M827in 1 2004
A Hlfme, Nicols y Sylvie
A Hlfme, Nicols y Sylvie
A Hlfme, Nicols y Sylvie
,
Indice general

Prlogo IX

1. Introduccin 1

2. Generalidades 5
2.1. El primer programa 6
2.2. Editar, compilar, ejecutar 9
2.2.1. g++ . . . . . 10
2.2.2. bcc32 . . . . 10
2.2.3. Thrbo 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 asignacin 21
2.7. Operadores aritmticos. 22
2.8. Prioridad de los operadores aritmticos . 24
2.9. Abreviaciones usuales 26
2.10. Funciones matemticas 27
2.11. Entrada de datos y salida de resultados 30
2.12. Conversiones de tipo en expresiones mixtas 35
2.13. Moldes . . . . . . . . . . . ..... . 36

III
NDICE GENERAL

3. Estructuras de control 41
3.1. if . . . . . . . . . . 41
3.2. Operadores relacionales y lgicos 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 exi t 61

4. Funciones 67
4.1. Generalidades 67
4.2. Funciones recurrentes 75
4.3. Parmetros por valor y por referencia 76
4.4. Parmetros por defecto ...... . 81
4.5. Variables locales y variables globales 82
4.6. Sobrecarga de funciones 83
4.7. Biblioteca estndar 85

5. Arreglos 87
5.1. Arreglos unidimensionales 87
5.2. Arreglos multidimensionales 94
5.3. Cadenas . . . . . . . . . 98
5.4. Inicializacin de arreglos 103

6. Apuntadores 109
6.1. Apuntadores y arreglos unidimensionales . 111
6.2. Apuntadores a apuntadores . . . . . . . 116
6.3. Apuntadores y arreglos bidimensionales 116
6.4. Matrices y arreglos unidimensionales 117
6.5. Arreglos aleatorios . . . . . . . . 129
6.6. Asignacin dinmica de memoria 131

IV
NDICE GENERAL

6.7. Matrices y apuntadores dobles 135


6.8. Arreglos a partir de 1. . . . . 139

7. Lectura y escritura en archivos 143


7.1. fopen, fscanf, fclose, fprintf 144
7.2. feof 148
7.3. Algunos ejemplos 150

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. Apuntadores a funciones 165
8.7. Funciones en lnea 169
8.8. Argumentos de la funcin main 171

9. Estructuras 175
9.1. Un ejemplo con complejos 175
9.2. Un ejemplo tpico. . . . . 181

10. Algunas funciones elementales 183


10.1. Cdigo de algunas funciones. 184
10.2. Versiones con saltos 190
10.3. Mtodo burbuja. . . 194

11. Solucin de sistemas lineales 199


11.1. Notacin. . . . . . 199
11.2. Mtodos ingenuos. .200
11.3. Sistema diagonal . .202
11.4. Sistema triangular superior .202
11.4.1. Nmero de operaciones .203
11.4.2. Implementacin en C .204

v
NDICE GENERAL

11.5. Sistema triangular inferior. . . . 206


11.6. Mtodo de Gauss . . . . . . . . . 206
11.6.1. Nmero de operaciones . 211
11.6.2. Implementacin en C . 213
11.7. Factorizacin LU . . . . . . . . 215
11.8. Mtodo de Gauss con pivoteo parcial. . 217
11.9. Factorizacin LU=PA . . . . . . . . . 223
11.10. Mtodo de Cholesky ........ . 227
11.10.1. Matrices definidas positivas . 227
11.10.2. Factorizacin de Cholesky . . 229
11.10.3. Nmero de operaciones de la factorizacin . 235
11.10.4. Solucin del sistema . . . . 237
11.11. Mtodo de Gauss-Seidel . . . . . . 239
11.12. Solucin por mnimos cuadrados. . 245
11.12.1. Derivadas parciales . . 246
11.12.2. Ecuaciones normales . 247

12. Solucin de ecuaciones 255


12.1. Mtodo de Newton .. .257
12.1.1. Orden de convergencia. . 262
12.2. Mtodo de la secante . . . 263
12.3. Mtodo de la biseccin . . . . . . 267
12.4. Mtodo de Regula Falsi . . . . . 268
12.5. Modificacin del mtodo de Regula Falsi . 270
12.6. Mtodo de punto fijo . . . . . . . . . . . . 272
12.6.1. Mtodo de punto fijo y mtodo de Newton . 278
12.7. Mtodo de Newton en lRn . . . . . . 279

12.7.1. Matriz jacobiana . . . . . . . 280


12.7.2. Frmula de Newton en lRn . . 280

13. Interpolacin y aproximacin 285


13.1. Interpolacin . . . . . . . . 287
13.2. Interpolacin de Lagrange . 289

VI
NDICE GENERAL

13.2.1. Algunos resultados previos . 289


13.2.2. Polinomios de Lagrange . . . 290
13.2.3. Existencia, unicidad y error . 291
13.3. Diferencias divididas de Newton. . . 293
13.3.1. Tabla de diferencias divididas . 296
13.3.2. Clculo del valor interpolado . 298
13.4. Diferencias finitas. . . . . . . . . . . . 302
13.4.1. Tabla de diferencias finitas . . 302
13.4.2. Clculo del valor interpolado . 304
13.5. Aproximacin por mnimos cuadrados . 306

14. Integracin y diferenciacin 313


14.1. Integracin numrica. . . . . 313
14.2. Frmula del trapecio . . . . . 314
14.2.1. Errores local y global . 317
14.3. Frmula de Simpson . . . . . . 319
14.3.1. Errores local y global . 320
14.4. Otras frmulas de Newton-Cotes . 325
14.4.1. Frmulas de Newton-Cotes abiertas . 325
14.5. Cuadratura de Gauss. . . . . . . 326
14.5.1. Polinomios de Legendre . 331
14.6. Derivacin numrica . . . 332

15. Ecuaciones diferenciales 337


15.1. Mtodo de Euler . . . . . 338
15.2. Mtodo de Heun . . . . . 341
15.3. Mtodo del punto medio . 344
15.4. Mtodo de Runge-Kutta . . 347
15.5. Deduccin de RK2 . . . . . 350
15.6. Control del paso . . . . . . 353
15.7. Orden del mtodo y orden del error. . 359
15.7.1. Verificacin numrica del orden del error. . 360
15.8. Mtodos multipaso explcitos . . . . . . . . . . . . 362

VII
NDICE GENERAL

15.9. Mtodos multipaso implcitos . . . . . . . . . 366


15.10. Sistemas de ecuaciones diferenciales. . . . . 371
15.11. Ecuaciones diferenciales de orden superior . 373
15.12. Ecuaciones diferenciales con condiciones de frontera . 376
15.13. Ecuaciones lineales con condiciones de frontera. .. . 379

A. Estilo en e 389
A.1. Generalidades . . 389
A.2. Ejemplo . . . . . 393
A.3. Estructuras de control . 395

VIII
NDICE GENERAL

15.9. Mtodos multipaso implcitos . . . . . . . . . 366


15.10. Sistemas de ecuaciones diferenciales. . . . . 371
15.11. Ecuaciones diferenciales de orden superior . 373
15.12. Ecuaciones diferenciales con condiciones de frontera . 376
15.13. Ecuaciones lineales con condiciones de frontera. .. . 379

A. Estilo en e 389
A.1. Generalidades . . 389
A.2. Ejemplo . . . . . 393
A.3. Estructuras de control . 395

VIII
NDICE GENERAL

15.9. Mtodos multipaso implcitos . . . . . . . . . 366


15.10. Sistemas de ecuaciones diferenciales. . . . . 371
15.11. Ecuaciones diferenciales de orden superior . 373
15.12. Ecuaciones diferenciales con condiciones de frontera . 376
15.13. Ecuaciones lineales con condiciones de frontera. .. . 379

A. Estilo en e 389
A.1. Generalidades . . 389
A.2. Ejemplo . . . . . 393
A.3. Estructuras de control . 395

VIII
Prlogo

El propsito de este libro es presentar los conceptos ms importantes


del lenguaje C y varios temas de mtodos numricos. Tambin estn
algunos temas sencillos y muy tiles de C++.
Est dirigido principalmente, pero no de modo exclusivo, para el cur-
so Programacin y Mtodos Numricos que deben tomar los estudiantes
de las carreras de Matemticas y de Estadstica en la Universidad Nacio-
nal. Estos estudiantes ya han visto clculo diferencial y estn cursando,
de manera simultnea, clculo integral y lgebra lineal. Adems se supo-
ne 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 tiem-
po, esto corresponde a cinco horas semanales durante quince semanas
aproximadamente. Obtener un nivel medio de programacin no es difcil
pero requiere de manera indispensable bastante tiempo de prctica fren-
te a un computador.
El captulo 15, sobre solucin numrica de ecuaciones diferenciales
ordinarias, no corresponde al programa del curso, pero est incluido para
no dejar por fuera un tema tan importante. Sin embargo, otro tema
muy til, solucin numrica de las ecuaciones diferenciales parciales, no
est incluido. Tampoco se trata el tema del clculo de valores y vectores
propios.

En la pgina electrnica del autor, se encontrar una fe de erratas del


libro, que se ir completando a medida que los errores sean detectados.
En esta pgina tambin est el cdigo para algunos mtodos y otros
documentos relacionados con el tema. Actualmente la direccin es:
www.matematicas.unal.edu.co/-hmora/

IX
Si hay reorganizacin de las pginas de la Universidad, ser necesario
entrar a la pgina
www.unal.edu.co
dirigirse a Sede de Bogot, Facultad de Ciencias, Departamento de Ma-
temticas y pgina del autor.

Quiero agradecer especialmente a los profesores Fabio Gonzlez, Fer-


nando Bernal, Luis Eduardo Giraldo, Flix Soriano, Humberto Sarria y
Hctor Lpez quienes tuvieron la amabilidad y la paciencia de leer la
versin inicial de este libro. Tambin a los estudiantes del curso Pro-
gramacin y Mtodos Numricos de las carreras de Matemticas y Es-
tadstica, en especial a Claudia Chica y Marcela Ewert. Las sugerencias,
comentarios y correcciones de todos ellos fueron muy tiles. Tambin
doy gracias al profesor Gustavo Rubiano, director de Publicaciones de
la Facultad de Ciencias, quien facilit la publicacin preliminar, en la
coleccin Notas de Clase, de la primera versin de este documento.

El autor estar muy agradecido por los comentarios, sugerencias y


correcciones enviados a:

hmmorae@unal.edu.co
hectormora@yahoo.com

Deseo agradecer a la Universidad Nacional por haberme permitido


destinar parte de mi tiempo de trabajo a esta obra, este tiempo fue una
parte importante del necesario para la realizacin del libro.

El texto fue escrito en Jb.1EX-. Quiero agradecer al profesor Rodrigo


De Castro quien amablemente me ayud a resolver las inquietudes y los
problemas presentados.

Finalmente, y de manera muy especial, agradezco a HlEme, Nicols


y Sylvie. Sin su apoyo, comprensin y paciencia no hubiera sido posible
escribir este libro.

x
1

Introduccin

El lenguaje de programacin ms utilizado para clculos cientficos


es el Fortran, bien sea en sus versiones originales, en Fortran-77 o en
Fortran-90. Inicialmente Fortran fue el nico lenguaje empleado para
clculo cientfico. Posteriormente se utilizaron tambin otros lenguajes,
como Algol, PL-l, Pascal, e, e++ ...
Actualmente se sigue utilizando ampliamente Fortran en laboratorios
de investigacin del ms alto nivel pues, adems de sus buenas cualida-
des, 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 informticos, sobre la obsolescencia del Fortran.
Sin embargo, actualmente una parte importante de programas pa-
ra clculo cientfico se hace en e y e++. Entre sus ventajas, algunas
compartidas tambin por Fortran, se pueden citar:

Disponibilidad: es posible encontrar fcilmente diferentes compila-


dores de e y e++, para microcomputadores, minicomputadores,
estaciones de trabajo y computadores grandes (mainframes).

Portabilidad: los programas pueden moverse fcilmente entre di-


ferentes tipos de computadores; por ejemplo, un programa en e
hecho en un microcomputador debe poder pasar sin problemas a
una estacin de trabajo.

Eficiencia.

1
1. INTRODUCCIN

Bibliotecas: C y C++ permiten crear fcilmente interfaces para


usar las bibliotecas hechas en Fortran.

En el medio estudiantil colombiano, donde fundamentalmente se


usan microcomputadores con plataforma Windows, es mucho ms comn
encontrar compiladores de C y C++ que de Fortran. Esta situacin no
tiene que ver con las bondades o defectos de los lenguajes, pero hace
que, en la prctica, en muchos casos, sea ms fcil pensar en hacer un
programa en C o C++ que en Fortran. Actualmente est creciendo el
uso de Linux, en el cual, casi siempre, todas las distribuciones tienen
compilador de C, C++ y Fortran.
Este libro, de alcance no muy extenso, es una introduccin al lenguaje
C, a algunas de las caractersticas sencillas de C++ y al tema de los
mtodos numricos. No contiene dos temas fundamentales de C++, que
estn relacionados entre s: las clases y la programacin orientada a
objetos.
El libro no pretende ser de referencia, es decir, los temas no se tratan
de manera exhaustiva; solamente estn los detalles y caractersticas ms
importantes o ms usados.
Se invita al lector a profundizar y complementar los temas tratados,
y a continuar con el estudio, aprendizaje y prctica de algunos nuevos,
en particular clases y programacin orientada a objetos, en libros como
[BaN94], [Buz93], [Cap94], [DeD99], [E1S90], [Sch92].
C es considerado como un lenguaje de nivel medio; en cambio Pascal,
Basic o Fortran se consideran de ms alto nivel. Esto no es mejor ni peor,
simplemente quiere decir que C utiliza al mismo tiempo caractersticas
de lenguajes de alto nivel y propiedades cercanas al lenguaje de mqui-
na. En C hay algunas funcionalidades parecidas al lenguaje interno del
computador, pero esto implica que el programador debe ser mucho ms
cuidadoso. Por ejemplo, C no controla si los subndices de un arreglo
(algo semejante a un vector) salen fuera del rango de variacin previsto.
Se puede considerar que C++ es como una ampliacin de C; por
tanto C++ acepta casi todo lo que es vlido en C. A su vez, las rdenes
y caractersticas especficas de C++ no son vlidas en C.
En cuanto a mtodos numricos, slo estn algunos de los temas
ms importantes. Para cada tema o problema hay muchos mtodos. De
nuevo este libro no es, y no podra serlo, exhaustivo. Los mtodos trata-

2
dos presentan un equilibrio entre eficiencia, facilidad de presentacin y
popularidad. Hay muy buenos libros de referencia para mtodos numri-
cos y anlisis numrico. Algunos de ellos son [GoV96], [IsK66], [YoG72],
[DaB74], [BuF85], [LaT87], [StB93], [Atk78].
Tambin hay libros que al mismo tiempo tratan los dos temas: C
(o C++) y mtodos numricos; por ejemplo: [Pre93], [Kem87], [OrG98],
[Fl095], [ReD90].
Los ejemplos de programas de este libro han sido probados en va-
rios 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 nmero de cifras decimales desplegadas en pantalla.
En algunos ejemplos no estn todos los detalles ni instrucciones ne-
cesarias, aparecen nicamente las instrucciones ms relevantes para ilus-
trar el tema en estudio. Usualmente aparecern puntos suspensivos in-
dicando que hacen falta algunas instrucciones; por ejemplo, las instruc-
ciones donde se leen, se definen o se les asigna un valor a las variables.
dos presentan un equilibrio entre eficiencia, facilidad de presentacin y
popularidad. Hay muy buenos libros de referencia para mtodos numri-
cos y anlisis numrico. Algunos de ellos son [GoV96], [IsK66], [YoG72],
[DaB74], [BuF85], [LaT87], [StB93], [Atk78].
Tambin hay libros que al mismo tiempo tratan los dos temas: C
(o C++) y mtodos numricos; por ejemplo: [Pre93], [Kem87], [OrG98],
[Fl095], [ReD90].
Los ejemplos de programas de este libro han sido probados en va-
rios 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 nmero de cifras decimales desplegadas en pantalla.
En algunos ejemplos no estn todos los detalles ni instrucciones ne-
cesarias, aparecen nicamente las instrucciones ms relevantes para ilus-
trar el tema en estudio. Usualmente aparecern puntos suspensivos in-
dicando que hacen falta algunas instrucciones; por ejemplo, las instruc-
ciones donde se leen, se definen o se les asigna un valor a las variables.
2

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 est de acuerdo con la sintaxis de C y que haga lo que
el programador desea. Este archivo se denomina el programa fuente
o el cdigo. Generalmente, tiene la extensin.c o .cpp, es decir, si
el programa se va a llamar progrOl, entonces el programa fuente se
llamar progrOl. e o progrOl. 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. Tambin 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 estn 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), Dev-
C++ (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 rdenes adecuadas para hacer lo que el programador desea. U na vez
construida una primera versin del programa fuente, es necesario utilizar
el compilador. El compilador revisa si el programa fuente est de acuerdo
con las normas de C. Si hay errores, el compilador produce mensajes

5
2. GENERALIDADES

indicando el tipo de error y la lnea donde han sido detectados. Entonces


el programador debe corregir el programa fuente y volver a compilar
(utilizar el compilador). Este proceso se repite hasta eliminar todos los
errores.
Si no hay errores de compilacin, el compilador crea un programa
ejecutable, generalmente con la extensin .exe (en Windows o DOS);
por ejemplo, progrOl. exe. Este programa ejecutable est en lenguaje
de mquina y es el que realmente hace lo que el programador escribi en
el programa fuente.
En el mejor de los casos, el programa no presenta errores durante la
ejecucin y adems efectivamente hace lo que el programador quiere.
Tambin puede suceder que el programa no presenta errores de eje-
cucin, pero no hace lo que el programador quera, es decir, el programa
hace lo que est en el programa fuente, pero no corresponde a lo que de-
seaba el programador. Entonces el programador debe revisar y modificar
el programa fuente y despus compilar de nuevo.
En un tercer caso hay errores durante la ejecucin del programa; por
ejemplo, se presenta el clculo de la raz cuadrada de un nmero negativo
o una divisin por cero o el programa nunca termina (permanece en un
ciclo sin fin). Como en el caso anterior, el programador debe revisar y
modificar el programa fuente y despus compilar de nuevo.
Por el momento hemos pasado por alto el proceso de enlace o en-
cadenamiento ( link). De manera muy esquemtica se puede decir que
mediante este proceso se concatenan en un nico bloque varios mdulos
que han sido compilados por separado.

2.1 El primer programa

Uno de los programas ms sencillos y pequeos puede ser el siguiente:

#include <stdio.h>
int mainO
{
printf(" Este es mi primer programa.\n");
return O;
}

6
2.1. EL PRIMER PROGRAMA

La primera lnea, #include ... ,indica que se va a utilizar una biblio-


teca cuyo archivo de cabecera es stdio . h, es decir, la biblioteca standard
input output. En un archivo de cabecera hay informacin y declaraciones
necesarias para el uso correcto de las funciones de la biblioteca corres-
pondiente.
En un programa en C hay una o varias funciones, pero siempre tiene
que estar la funcin main, es decir, la funcin principal. La palabra int,
que precede a main, indica que la funcin main devuelve un valor entero.
Justamente la funcin main, en este ejemplo, devuelve O por medio de
la instruccin return o. Para la funcin main se usa la siguiente con-
vencin: devuelve O si no hay errores; devuelve 1 u otro valor no nulo si
hubo errores.
Dentro de los parntesis despus de main no hay nada; esto quiere
decir que la funcin main no tiene parmetros o argumentos.
Poco a poco el lector entender el significado del valor devuelto por
una funcin, de los parmetros o argumentos de una funcin. Por el
momento puede suponer que siempre se debe escribir int main () .
El corchete izquierdo, {, indica el comienzo de la funcin main y el
corchete derecho, }, indica el final.
La funcin printf es propia de C y sirve para "escribir" o desplegar
en la pantalla algn resultado. Esta funcin est 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 11 y termina con ". Dentro de la cadena tambin
est \n que sirve para crear una nueva lnea dentro de lo que aparece
en la pantalla. Observe lo que pasa, durante la ejecucin del programa,
al cambiar la lnea por una de las siguientes:
printf(" Este es mi primer programa.");
printf(" Este es mi primer programa.\n\n\n");
printf(" Este es mi primer \n\n programa.\n");
printf(lI\n\n\n\n Este es mi \n primer programa.\n");
Al final de las instrucciones u rdenes de C siempre hay un punto y
coma. Este signo determina donde acaba la instruccin.
Este primer programa tambin se puede escribir con una funcin
especfica de C++.
#include <iostream.h>

7
2. GENERALIDADES

int mainO
{
eout" Este es mi primer programa en C++."endl;
return O;
}

Aqu se utiliza el archivo de cabecera iostream. h, en el cual est la


funcin eout. Observe la diferencia de sintaxis entre printf y eout.
La orden para cambiar de lnea est dada por endl. Tambin se puede
meter, dentro de la cadena, \n y se obtienen los mismos resultados.

eout" Este es mi primer programa.\n";

Para obtener cambios de lnea adicionales se puede utilizar varias veces


endl, por ejemplo:

eout"Este es mi primer programa."endlendl;


eout"Este es mi primer"endl"programa."endl;
eoutendl"Este es mi"endl"primer programa.";

Algunos compiladores muy recientes no aceptan de buen gusto el an-


terior programa en C++; por ejemplo, el g++ (gcc) 3.2 de Linux. Lo
consideran anticuado (deprecaied or aniiquaied). El programa se debera
escribir as:

#inelude <iostream>
using namespaee std;
int mainO
{
eout" Este es mi primer programa en C++."endl;
return O;
}

Observe que aparece simplemente iostream y no iostream. h. La se-


gunda lnea, using ... , sirve para que no sea necesario escribir
std: : eout .. .
sino simplemente
eout ...
Cuando hay varios espacios seguidos, es lo mismo que si hubiera uno
solo. Las lneas en blanco no se tienen en cuenta, simplemente sirven para

8
2.2. EDITAR, COMPILAR, EJECUTAR

la presentacin del programa fuente. El programa del ejemplo tambin


se hubiera podido escribir como sigue, pero su lectura no es fcil.

#include <stdio.h>
int
main() {printf
( 11 Este es mi primer programa. \n")
return
O;}

2.2 Editar, compilar, ejecutar

En esta seccin hay algunas pautas generales para poder efectuar


el proceso de edicin, compilacin y ejecucin de un programa. Estas
pautas pueden variar de computador en computador o de configuracin
en configuracin; adems, sirven para los casos ms sencillos. Poco a
poco, el programador deber aprender a utilizar otras opciones y formas
de compilacin.
Suponga que el programa fuente se llama progO!. cpp. Tambin se
supone que el compilador que se va a usar ha sido instalado correcta-
mente.
Para facilitar la escritura se utilizar la siguiente notacin:
r:>orden
indica que se activa el botn (o parte de un men) llamado orden. Esto
se logra, generalmente, picando con el mouse dicho botn. En algunos
casos se logra el mismo objetivo mediante el desplazamiento con las
flechas y se finaliza oprimiendo la tecla Enter. Por ejemplo, r:>File indica
que se activa el botn File.
La notacin Alt-f indica que se mantiene oprimida la tecla Alt
y despus se pulsa ligeramente la tecla f. Finalmente se suelta la tecla
Alt. De manera anloga se utiliza la misma notacin para la tecla Ctrl o
para la tecla il' que aqu se denotar por May (maysculas); por ejemplo,
Ctrl-F5 o May-F2.

9
2. GENERALIDADES

2.2.1 g++
Este compilador est en la mayora de las distribuciones de Linux, o
posiblemente en todas. Es en realidad el mismo compilador gcc.
Para editar el programa fuente, utilice el editor de su preferencia,
por ejemplo, Emacs, vi, pico. No olvide guardar los cambios hechos.

Se puede compilar mediante la orden


g++ progO!. cpp

En este caso, si no hay errores de compilacin, se produce un archivo


ejecutable llamado siempre a. out.

Para correr el programa se debe dar la orden


./a.out

Si se da la orden
g++ prog01.cpp -o algo

el compilador produce un archivo ejecutable llamado algo. Es ms di-


ciente que el nombre del archivo ejecutable sea semejante al del programa
fuente, por ejemplo,
g++ prog01.cpp -o prog01

As, para correr el programa, se da la orden


./prog01

Si desea que no aparezcan las advertencias que indican que el programa


est escrito en un leguaje anticuado, digite
g++ prog01.cpp -o prog01 -Wno-deprecated

Para obtener informacin sobre g++


man g++

Para salir de la informacin, oprima q.

2.2.2 bcc32

Una manera sencilla de utilizar este compilador es en ambiente DOS,


es decir, estando en Windows es necesario abrir una ventana de DOS o

10
2.2. EDITAR, COMPILAR, EJECUTAR

ventana de sistema.
La edicin del archivo se hace con cualquier editor de texto de Win-
dows (bloc de notas, Wordpad, Emacs para Windows ... ) o de DOS
(edit...).

Una vez editado y guardado el archivo, se compila mediante


bee32 pragOl.epp
La orden anterior produce, si no hay errores, el archivo pragOl. exe.
ste es un archivo ejecutable. Generalmente no es necesario especificar
la extensin . epp, el compilador la presupone, o sea, bastara con
bee32 pragOl

Para correr el programa basta con digitar


pragOl
Como se observa, no es necesario escribir la extensin. exe.

2.2.3 Turbo C++

Este compilador para DOS viene con IDE (ambiente integrado). Sin
embargo tambin se puede utilizar nicamente el compilador de la misma
forma como se usa el compilador bee32. Basta con cambiar bee32 por
tee.
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
te
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, en la parte superior de la ven-
tana, por medio del mouse o por medio de la tecla Alt acompaada
simultneamente de la primera letra de la orden o submen. Por ejem-
plo Alt-F para el sub men File.

Para grabar el archivo o los cambios:


1> File I>Save

11
2. GENERALIDADES

Para algunas de estas secuencias de operaciones hay una tecla que re-
emplaza la secuencia. La secuencia File Save se puede reemplazar por
F2.

Para compilar:
r>Compile r>Compile o Alt-F9
Para correr el programa
r>Run r>Run o Ctrl-F9
La secuencia anterior, cuando el programa (la ltima versin) no ha sido
compilado, en un primer paso lo compila y despus lo corre. Entonces,
en muchos casos, no es necesaria la secuencia Compile Compile.
Despus de correr el programa, el ambiente Thrbo C++, vuelve in-
mediatamente a la pantalla donde est el editor. Si el programa muestra
algunos resultados en pantalla, stos no se ven, pues la pantalla de re- 1\
sultados queda inmediatamente oculta por la pantalla del editor. Para
ver la pantalla de resultados:
Alt-F5
Para volver a la pantalla del editor, oprima cualquier tecla.

Para salir de Thrbo C++


r> File r> Quit o Alt-x

2.2.4 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 nicamente un archivo .cpp, el archivo parte_a. cpp.

La primera vez es necesario crear el proyecto y agregarle archivos.

r>File r>New r>Projects r> Win32 Console Application r>Project Name


prog50 .Create a new workspace r>OK .An empty project r>Finish
r>OK

Hasta aqu, se cre un proyecto con nombre prog50; esto quiere de-
cir que hay una carpeta, con el nombre prog50, con la siguiente ruta
(posiblemente) :

12
2.2. EDITAR, COMPILAR, EJECUTAR

c:\Archivos de Programa\Microsoft Visual Studio\


My Projects\prog50\

Dentro de esa carpeta, Visual C++ cre la carpeta Debug y cuatro


archivos: prog50. dsp, prog50. dsw, prog50. ncb y prog50. opto Ahora
es necesario agregar por lo menos un archivo fuente, un .cpp. Tambin
se pueden agregar otros archivos .cpp y archivos de cabecera .h:
r>Project r>Add To Project r>New r>C++ Source File
r>File name parte_a r>OK
Como se utiliz la opcin de un archivo nuevo, inmediatamente Visual
C++ abre el editor para escribir en el archivo parte_a. cpp

Al finalizar la escritura en el archivo, la secuencia


r> Build r> Compile o Crtl-F7
guarda el archivo parte_a. cpp, lo compila y, si no hay errores, crea el
archivo part e _a . ob j en la carpeta De bug .

La secuencia
r> Build r> Build o F7
hace la ~dicin de enlaces (link) y, si no hay errores, crea el ejecutable
prog50. ebce en la carpeta Debug. Si es necesario, esta secuencia tambin
guarda y compila.

La secuencia
r>Build r>Execute o Ctrl-F5
activa el ejecutable prog50. exe
Las otras veces ya no es necesario crear el proyecto, basta con abrir
el archivo adecuado. La secuencia
r> File r> Recent W orkpaces
permite escoger el proyecto prog50 y hacer las modificaciones necesa-
rias. Para compilar, enlazar y correr se utilizan las mismas secuencias
anteriores.
En Visual C++ y en Dev-C++, varias de estas secuencias se pueden
reemplazar por conos que aparecen en una de las barras superiores; por
ejemplo el cono del disquete para guardar, la carpeta semiabierta para
abrir un documento ...

13
2. GENERALIDADES

2.2.5 Dev-C++

Este compilador para Windows es software libre, viene con IDE. Su


direccin es www.bloodshed.net. Despus de instalado, para un progra-
ma nuevo, se puede utilizar inicialmente la siguiente secuencia:
r>File r>New So urce file
Entonces Dev-C++ abre un archivo predefinido que el programador debe
completar.

#include <iostream.h>
#include <stdlib.h>

int mainO
{

system("PAUSE");
return O;
}

Hay dos lneas "nuevas": se incluye otro archivo de cabecera, el archi-


vo stdli b . 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.

U na vez que el programador ha escrito su programa, la secuencia


r>File r>Save unit o Ctrl-s
permite guardar el archivo. Si es la primera vez, es necesario dar el nom-
bre, para nuestro ejemplo, progOl. Las veces posteriores, la secuencia
anterior simplemente graba los cambios realizados en el archivo.

La secuencia
r>Execute r>Compile and Run o Ctrl-FlO
encadena las tres acciones importantes: guardar, compilar y ejecutar.
Cuando en una ocasin anterior ya se hizo una parte del programa y se
desea modificarlo, se puede utilizar la secuencia
r> File r> Open project or file o Ctrl-o

14
2.3. COMENTARIOS

Con la secuencia anterior se puede escoger el archivo que se desea abrir.


Tambin se puede utilizar
[> File [> Reopen
La orden system("pause") tambin puede ser usada en TUrbo C para
no salir de la pantalla de resultados, as no es necesario utilizar Alt-F5
para regresar a la pantalla de resultados. Con los compiladores bcc32,
Visual C++ y g++, no es necesaria.

2.3 Comentarios
Un comentario en C es una porcin de texto que est en el programa
fuente con el objetivo de hacerlo ms claro, pero no influye en nada en
el programa ejecutable.

#include <stdio.h>
II Comentario de una linea, especifico de C++
1* Comentario en C. *1
1*
Puede ser
de varias
lineas

int maine)
{
printf(" Este es mi primer programa.\n");
return O;
}

Un comentario en C empieza con 1* y acaba con *1. Un comentario


en C++ empieza con II y termina donde acaba la lnea. Un comentario
en C puede abarcar una parte de una lnea, una lnea completa o varias
lneas. Un comentario en C++ no puede abarcar ms de una lnea, pero
puede haber varios comentarios seguidos. Los comentarios pueden estar
despus de una instruccin.

II Primera linea de un comentario en C++

15
2. GENERALIDADES

II Segunda linea de un comentario en C++


II Tercera linea de un comentario en C++
II
printf(" HOLA.\n"); II escribe HOLA
printf(" HOLA.\n"); 1* escribe HOLA *1
Cuando el programador est haciendo el programa tiene muy claro
qu significa cada parte del programa. Sin embargo, al cabo de unas
semanas, en especial si ha estado haciendo otros programas, el signifi-
cado de cada parte del programa empieza a hacerse difuso. Ms an,
el programa fuente debe ser suficientemente claro para que pueda ser
ledo por otras personas. La inclusin de comentarios adecuados permi-
te hacer ms claro un programa y facilita enormemente su correccin
y actualizacin posterior. Los comentarios tienen que ver con varios as-
pectos, por ejemplo: objetivos del programa, datos, resultados, mtodo
empleado, significado de las variables ...

2.4 Identificadores
Los identificadores sirven para el nombre de variables o de funcio-
nes. La longitud mxima de un identificador depende del compilador
utilizado y del lenguaje (C o C++). Generalmente no es inferior a 32;
ms an, puede ser muy grande. Los identificadores slo usan smbolos
alfanumricos, es decir, letras minsculas, letras maysculas, dgitos y
el smbolo de subrayado:

a b c ... x y z A B C... X Y Z O 1 2 345 6 7 8 9 _

El primer carcter no puede ser un dgito. No puede haber espacios


dentro de un identificador. Las minsculas se consideran diferentes de
las maysculas. Un identificador no puede ser una palabra clave. Las
palabras clave estn reservadas para C o C++. Usualmente la lista de
palabras clave es la siguiente:

asm auto break case catch


char class const continue default
delete do double else enum
extern float for friend goto
if inline int long new

16
2.4. IDENTIFICADORES

operator private protected public register


return short signed sizeof static
struct switch template this throw
try typedef union unsigned virtual
void volatile while

De los siguientes identificadores posibles, los cuatro primeros son correc-


tos, los cinco ltimos son inadecuados. El primer identificador es dife-
rente del segundo.

al
Al
peso_especifico_del_mercurio
blj
peso especifico
peso-especifico
la
peso'esp
float

Adems, 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;

coutprintfendl;

En el segundo ejemplo hay conflicto entre la funcin 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


representaR. El tercero, peso_especifico_deLmercurio, es un buen

17
2. GENERALIDADES

ejemplo. Sin embargo es un poco largo. Si un identificador es muy largo,


no hay error; simplemente es ineficiente cuando hay que escribir varias,
o muchas, veces el identificador.
Buscar que sean muy cortos puede llevar a que sean poco o nada
explicativos; por ejemplo, usar

pem

es corto, y tal vez eficiente, pero dice poco con respecto al peso especfico
del mercurio.
Usualmente, cuando es necesario, se emplean las tres o cuatro pri-
meras letras de cada palabra. Para diferenciar visualmente las palabras,
stas se separan por el smbolo de subrayado o se escribe la primera letra
de cada palabra (a partir de la segunda) en maysculas; por ejemplo,
un identificador para el peso especfico del mercurio puede ser

pesoEspHg
peso_esp_hg

Obviamente, si por tradicin las variables tienen nombres muy cortos,


entonces no se justifica utilizar identificadores largos. Por ejemplo, de
manera natural, los identificadores para los coeficientes de una ecuacin
cuadrtica pueden ser

a b e

Adicionalmente, uno o varios comentarios adecuados pueden explicar lo


que hace un programa y el significado de cada identificador.

II Programa para la solucion de la ecuacion cuadratica


II
II a x x + b x + e = O
II

En los comentarios es posible, dependiendo del sistema operativo, utili-


zar letras tildadas, y . Sin embargo, estos caracteres se pueden perder
al pasar de un sistema operativo a otro, por ejemplo, al pasar de DOS a
Windows. Entonces es preferible usar letras sin tildes, no importa
que sea un error de ortografa.

18
2.5. TIPOS DE DATOS

En un programa hay, o debe haber, una correspondencia biunvoca


entre las varibles y los identificadores. Por esta razn, de manera un
poco abusiva, algunas veces se utilizan indistintamente. Por ejemplo, en
lugar de decir la variable peso especfico del mercurio con identificador
pesoEspHg, se utilizar con frecuencia: la variable pesoEspHg .

2.5 Tipos de datos


Los principales tipos de datos son:

char
int
float
double

El primero, char, se usa para los caracteres, no slo los alfanumricos,


tambin para los otros caracteres usuales como + ( = ? [ * , etc. El tipo
int se usa para nmeros enteros. Para los nmeros reales (tienen una
parte entera y una parte fraccionaria no necesariamente nula) se usan
los tipos float y double.
Este ltimo es de mayor tamao y permite almacenar ms infor-
macin, pero a su vez necesita ms espacio para su almacenamiento y
un poco ms de tiempo para las operaciones. En general, para hacer
clculos numricos, si no hay restricciones muy fuertes de disponibilidad
de memoria, es preferible utilizar double para los reales. Generalmente
se conoce el tipo float con el nombre de punto flotante en precisin
sencilla y double con el nombre de punto flotante en doble precisin o
simplemente doble precisin.
Antes de su uso en el programa, generalmente al comienzo de las
funciones, es necesario declarar el tipo de las variables, por ejemplo:

double a, b, e;
int i, denom;
int j;

La siguiente tabla muestra los tamaos usuales en bytes (un byte, u octe-
to, es una unidad de informacin compuesta por 8 bits; un bit, acrnimo
de binary digit, es la unidad ms sencilla de informacin y puede tomar

19
2 GENERALIDADES

los valores O o 1) de los tipos anteriores, y el rango de variacin.


Tipo Tamao Rango
(bytes)
char 2
int 2 -32768 a 32767
float 4 3.4E-38 a 3.4E38
double 8 1.7E-308 a 1.7E308
La tabla anterior puede variar con el computador o con el compilador.
Con algunos compiladores el tipo entero usa cuatro bytes y tiene un
rango de variacin mucho ms amplio
La notacin usada no es la del idioma espaol. Aqu la parte entera se
separa de la fraccionaria con punto y no con coma, como es lo correcto
en espaol; es decir, aqu 1. 7 representa una unidad y siete dcimas.
Consecuentemente no se utiliza punto para separar las unidades de mil
de las centenas, ni se utiliza la comilla para separar los millones. Tambin
se est utilizando una convencin para la notacin cientfica, a saber,

3.45E42 345 X 1042 ,


100
O.345E-38 345 X 10-38.
1000
En la notacin cientfica de e tambin se puede utilizar la e minscula
en lugar de la mayscula; por ejemplo, 3. 45e42.
Para los tipos float y double, en la tabla est escrito nicamente
el rango positivo. Es necesario sobrentender el cero y el rango negativo;
por ejemplo, el tipo float tambin puede ser cero o variar entre -3.4E38
y -3.4E-38.

Mediante los modificadores

unsigned long

se obtienen nuevos tipos. Los ms usuales estn en la siguiente tabla.


Tipo Tamao Rango
(bytes)
unsigned int 2 O a 65535
long int 4 -2147483648 a 2147483647
long double 10 3.4E-4932 a 3.4E4932

20
2.6. OPERADOR DE ASIGNACIN

Los valores de la tabla anterior tambin pueden variar con el tipo de


computador o con el compilador.
El tipo long double debe ser manejado con mucho cuidado, pues
en varios compiladores aparentemente funciona bien la compilacin de
programas con variables long double, pero puede haber errores en los
resultados. Consulte detalladamente la documentacin del compilador
que usa, en lo referente al manejo de long double.

2.6 Operador de asignacin


Es el operador ms utilizado. Mediante su uso se le asigna a una
variable un nuevo valor. La forma general es:

variable = expresin;

Lo anterior indica que la variable, que siempre est a la izquierda del


signo igual, toma el valor dado por la expresin de la derecha. La asig-
nacin no se debe confundir con el significado de una igualdad en una
expresin matemtica. Algunos ejemplos permiten aclarar el uso y sig-
nificado de la asignacin.

int a;
double x, y;
char c;

a = 100;
Y 9.0/4.0;
x = 5.0 + y;
a = a+3;
c = 'A' ;

Antes de la instruccin a = 100 la variable a tena un valor determi-


nado, o tal vez ningn valor especfico. De todas maneras, despus de la
instruccin a = 100 la variable entera a vale cien. Despus de la ins-
truccin y = 9.0/4.0 la variable y vale 2.25. Como la variable y
corresponde a un nmero real, es preferible que la expresin de la dere-
cha sea hecha explcitamente entre nmeros reales; por esto en este caso
es preferible escribir 9. 0/4. O Y no simplemente 9/4. Como se ver ms

21
2. GENERALIDADES

adelante, el valor de 9/4 es el entero 2. Despus de la instruccin x =


5. O + Y , la variable x vale 7.25.
La instruccin a = a + 3 sera un error desde el punto de vista
matemtico, trabajando en el conjunto de los nmeros 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 instruccin, a vale
100. Despus de la instruccin, a vale 103.
En el momento en que se especifica el tipo de una variable, se puede
hacer una asignacin inicial. Por ejemplo, la instruccin

int i 3, j 5;

dice que las variables i, j son enteras y adems a i se le asigna el valor


3 y a j el valor 5 .

2.7 Operadores aritmticos


Los principales operadores aritmticos son:

+ / * % ++

Como era de esperarse + / indican la adicin, la sustraccin y


la divisin. Para la multiplicacin entre dos nmeros se emplea * (el
asterisco). Por ejemplo

int i, j, k;
double x, y;

i 27;
j 4;
k i+j;
coutkendl;
x = 10.0;
Y = 3.0;
coutx/yendl;
coutx*yendl;
couti/jendl;

produce la escritura en pantalla de los resultados

22
2.7. OPERADORES ARITMTICOS

31
3.33333
30
6

Es importante observar que al efectuar la divisin entre dos nmeros


enteros i, j (j i- O), e 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)lli/jIJ
Por ejemplo,

int i, j;

i = 27;
j = -4;
couti/jendl;

produce la escritura en pantalla de -6.


El operador - adems de representar la sustraccin, operacin
binaria, sirve para indicar el cambio de signo. La instruccin

x = -y;

asigna a la variable x el inverso aditivo del valor de y .


El operador % se aplica nicamente a enteros e indica el residuo
entero de la divisin. Por ejemplo,

int i, j, k;
i 25;
j = 7;
k = i%j;
coutkendl;

producir 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 despus 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

23
2. GENERALIDADES

int i 4, j 4, k;

k = i++;
couti" "kendl;
k = ++j;
coutj" "kendl;

el resultado ser la escritura de

5 4
5 5

Tanto para i como para j el valor inicial result incrementado en una


unidad. En la primera asignacin, la variable k tom el valor de i antes
del incremento. En la segunda asignacin, la variable k tom el valor de
j despus del incremento.
En caso de duda, en lugar de utilizar una sola instruccin, se pue-
de realizar exactamente lo mismo mediante dos instrucciones que no
presentan posibilidad de mala interpretacin.
k i ++ ; es equivalente a k = i;
i++;

k ++ j ; es equivalente a j++;
k = j;

tambin es equivalente a ++ j ;
k = j;

El operador es el operador de decremento. Su uso es anlogo al


de ++.

2.8 Prioridad de los operadores aritmticos


Cuando en una expresin hay varios operadores aritmticos, existen
reglas precisas de prioridad, llamada tambin precedencia, que indican
el orden en que el computador debe efectuar las operaciones.

En una expresin aritmtica puede haber parntesis redondos, es


decir ( , ). No estn permitidos, como parntesis, los rectangulares

24
2.8. PRIORIDAD DE LOS OPERADORES ARITMTICOS

[ , ], ni los corchetes { , }. Como se ver posteriormente, los


parntesis rectangulares [ , ] se utilizan para los subndices.

Los parntesis tienen prioridad sobre todos los operadores y deben


cumplir las reglas usuales de los parntesis, por ejemplo: deben ir
por parejas (uno izquierdo y uno derecho); en el orden usual, de
izquierda a derecha, no puede aparecer un parntesis derecho si
no va precedido de su correspondiente parntesis izquierdo; cuan-
do hay parntesis anidados, unos dentro de otros, los parntesis
internos tienen prioridad sobre los parntesis externos.

Cuando en una expresin hay dos operadores iguales, sin parnte-


sis, es necesario conocer la clase de asociatividad, es decir, se re-
quiere saber si se asocia utilizando el orden de izquierda a derecha
o el orden de derecha a izquierda.

Al encontrar la expresin a/b/ e, dado que la divisin es una opera-


cin binaria, habra dos posibilidades. La primera consiste en efectuar
primero el cociente a/b y dividir el resultado por c. La segunda con-
siste en efectuar primero el cociente b/ e y enseguida dividir el valor a
por el resultado. Utilizando parntesis, las dos posibilidades se pueden
expresar as:

(a/b)/c
a/(b/c)

La primera correspondera a asociatividad de izquierda a derecha y la


segunda de derecha a izquierda. Obviamente, cuando una operacin
es asociativa, por ejemplo la adicin, no importa en que orden se haga
la asociacin. Para la divisin, el lenguaje C, como est indicado en
la siguiente tabla, asocia de izquierda a derecha, entonces a/b/ e es lo
mismo que (a/b)/c.
La siguiente tabla muestra la precedencia, de mayor a menor, y la
asociatividad de los operadores aritmticos ms usados.

25
2. GENERALIDADES

Operador Asociatividad Precedencia


++ posincremento izq. a derecha mayor
-- posdecremento izq. a derecha
++ preincremento derecha a izq.
-- predecremento derecha a izq.
- cambio de signo derecha a izq.
multiplicacin izq. a derecha
*
/ divisin izq. a derecha
% resto de la divo entera izq. a derecha
+ adicin izq. a derecha
- sustraccin izq. a derecha
= asignacin derecha a izq. menor

Por medio de parntesis, que tienen prioridad superior a los operadores


aritmticos, los siguientes ejemplos muestran el orden en que se realizan
algunas operaciones.

double a = 1.2, b = 3.1, e = -2.5, d = 5.1, x;

x = a/b/e; // x (a/b)/e;
x = a*b+e/d-e*b; // x ( (a*b) + (c/d) ) - (e*b);
x = al-e; // x a/C-e);

De todas maneras, en caso de duda o para facilitar la lectura, se reco-


mienda el uso adecuado de parntesis o de espacios.

double a 1.2, b 3.1, e -2.5, d 5.1, x;

x = (a/b)/e;
x = a*b + c/d - e*b;
x = a/C-e);

2.9 Abreviaciones usuales


Una de las instrucciones frecuentes en los programas de computador
es la siguiente: se toma el valor de una variable y se le suma una constante
o una variable y el resultado se convierte en el nuevo valor de la variable.
Por ejemplo:

26
2.10. FUNCIONES MATEMTICAS

a = a + 2.0;
b b + c;

En C, las dos asignaciones anteriores se pueden escribir de manera abre-


viada as:

a += 2.0;
b += c;

Al principio, parece un poco raro o difcil del leer, pero finalmente se


adquiere la costumbre. De manera anloga, se puede abreviar cuando
hay multiplicaciones, restas o divisiones. O sea, las instrucciones

a = a*3.0;
i i - 2;
b b/c;

se pueden abreviar por

3.0;
2;
b 1= C;

2.10 Funciones matemticas


C tiene predefinidas en sus bibliotecas varias funciones matemti-
cas cuyo archivo de cabecera es math. h. Por ejemplo, la funcin sqrt
permite obtener la raz cuadrada. Su argumento es tipo double y su
resultado tambin.
El siguiente programa permite calcular las races de una ecuacin
cuadrtica, solamente cuando stas son reales. Ms adelante se ver el
caso general. Adems, hay otro inconveniente: este programa sirve ni-
camente para los valores definidos en el programa. Tambin se ver pos-
teriormente cmo hacer para que el programa reciba otros valores y
trabaje con ellos.

II Calculo de las raices de una ecuacion cuadratica,


II cuando son reales.

27
2. GENERALIDADES

#include <iostream.h>
#include <math.h>

int maine)
{
double a = 7.0, b = 3.1, c = -5.72;
double raiz1, raiz2;

raiz1 = (-b + sqrt(b*b-4.0*a*c) )/(2.0*a)


raiz2 = (-b - sqrt(b*b-4.0*a*c) )/(2.0*a);

cout" Las raices son: 1raiz1" "raiz2endl;


return O
}

El programa anterior producir el siguiente resultado.

Las raices son: 0.709256 -1.15211

Al hacer un programa, la primera preocupaClOn es que funcione. La


segunda es que sea eficiente. En el programa anterior hay varios clculos
repetidos: b*b-4. O*a*c y 2. O*a. Hacer el programa anterior ms
eficiente tendr una ganancia imperceptible, milsimas de segundo o
menos. Pero cuando se hace ms 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>

int mainO
{
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);

28
2.10. FUNCIONES MATEMTICAS

raiz1 (-b + d )/a2;


raiz2 (-b - d )/a2;

cout"\n\n "a" x*x + "b" X + "cendl;


cout"Las raices son: "raiz1" "raiz2endl;
return O;
}

En la siguiente tabla estn las principales funciones matemticas de C.


Para todas, el resultado es tipo double. Todas, salvo pow , tienen un solo
argumento. pow (x, y) evala x Y , ambos argumentos son tipo double y
el resultado tambin lo es.
/
Argumentos Resultado
acos arco coseno double double
asin arco seno double double
atan arco tangente double double
ceil parte entera superior double double
cos coseno double double
cosh coseno hiperblico double double
exp exponencial: eX double double
fabs valor absoluto double double
floor parte entera inferior double double
log logaritmo neperiano double double
log10 logaritmo en base 10 double double
pow xY double, double double
sin seno double double
sinh seno hiperblico double double
sqrt raz cuadrada double double
tan tangente double double
tanh tangente hiperblica double double

Si se utiliza alguna de estas funciones con un argumento fuera de


su conjunto de definicin, se producir un error durante la ejecucin del
programa, este se detendr y producir un pequeo aviso. Por ejemplo, si
se utiliza sqrt para un nmero negativo, el aviso producido, dependiendo
del compilador, puede ser:

sqrt: DOMAIN error

29
2. GENERALIDADES

Es responsabilidad del programador verificar, antes del llamado a la fun-


cin, que se va a utilizar un argumento adecuado. De manera anloga,
cuando hay divisiones, se debe estar seguro de que el divisor no es nulo.
En caso contrario, debe haber un control previo para evitar una termi-
nacin anormal del programa.

2.11 Entrada de datos y salida de resultados

La manera natural de entrar datos al programa, cuando hay pocos,


es por medio del teclado. En e, se hace mediante la funcin seanf. Los
siguientes ejemplos ilustran su uso.

II Calculo de las raiees de una eeuaeion euadratiea,


II cuando son reales.

#inelude <stdio.h>
#inelude <math.h>

int mainO
{
double a, b, e, raiz1, raiz2, d, a2;

printf("\n Raiees de a*x*x + b*x + e O.\n\n");

printf(" a = ");
seanf ("%lf", &a);

printf(" b = ");
seanf("%lf", &b);

printf(" e = ");
seanf("%lf", &e);

printf (" \n %lf x*x + %lf x + %lf O\n\n", a, b, e);

a2 = 2.0*a;
d = sqrt(b*b-4.0*a*e);
raiz1 = (-b + d )/a2;

30
2.11. ENTRADA DE DATOS Y SALIDA DE RESULTADOS

raiz2 = (-b - d )/a2;

printf (" Raiees: %12.4lf %15. 6lf\n", raiz1, raiz2);


return O;
}

Despus de que el programa escribe en la pantalla a = ,sigue la orden


seanf. Entonces el usuario, por medio del teclado, deber digitar el
valor de a. Para finalizar esta orden el usuario deber oprimir la tecla
Return o Enter.
All, lo que est entre comillas es la cadena de formato. Para este ca-
so, %lf es el formato para nmeros tipo double. La siguiente lista mues-
tra otros tipos de formato. Algunos corresponden a conceptos todava
no presentados en este libro. Consulte la documentacin del compilador
que usa, sobre los formatos para nmeros long int y long double.
~~-
%d int
%f float
%lf double
%u unsigned int
%e double, float en notacin cientfica
%i int
%e ehar
%s cadena de caracteres
%p puntero o apuntador

Es importante recalcar que en la lectura mediante seanf, la variable


debe ir precedida de &. Es un error muy comn, especialmente en pro-
gramadores conocedores de otros lenguajes (Pascal, Fortran u otros), no
colocar este signo. No es un error de compilacin, pero el resultado no
ser el deseado en la lectura.
Despus de la lectura de a, de manera anloga, el programa lee los
otros dos valores, el de b y el de e.

En la orden:

printf(lI\n %lf x*x + %lf x + %lf = O\n\n", a, b, e);

la cadena de formato tiene tres veces el formato %lf, correspondientes a


las tres variables que aparecen despus de la cadena. De acuerdo con la

31
2. GENERALIDADES

cadena de formato, el resultado producido ser:

un cambio de lnea,
un espacio,
el valor de a,
x*x +
el valor de b,
x +
el valor de e,
= O
dos cambios de lnea.

Dicho de otra manera, el resultado es semejante a escribir la cadena

n\n x*x + X + O\n\nn

insertando en el lugar adecuado los valores de a, b, e.


En la orden prntf, las variables que van a ser escritas no van pre-
cedidas de signo &, como era el caso para seanf.
Es una buena costumbre escribir los datos, o una parte de ellos, tan
pronto han sido ledos, antes de efectuar los clculos, para verificar que
la lectura se desarroll de manera adecuada.
En los casos anteriores, al utilizar simplemente %lf, el programador
no tiene control sobre el nmero de cifras decimales ni sobre la longitud
del campo (nmero de columnas utilizadas para la escritura del nme-
ro). En la ltima orden de escritura, hay modificadores para el formato.
Por ejemplo, el formato %12. 4lf indica que el valor de razl ocupar 12
columnas, de las cuales las cuatro ltimas son para escribir cuatro cifras
decimales. Por defecto, las salidas siempre estn ajustadas a la derecha,
entonces los espacios sobrantes aparecern a la izquierda en blanco. Si
razl valiera -10.0/3. O, entonces apareceran en pantalla cinco espa-
cios seguidos de -3.3333. Cuando el nmero no cabe en la longitud
de campo prevista, C toma el espacio necesario para la escritura del
nmero.
Los modificadores tambin se pueden utilizar para otros tipos de
formato; por ejemplo:

%15.4f

32
2.11. ENTRADA DE DATOS Y SALIDA DE RESULTADOS

%10.4e
%5d

La lectura de datos no tiene que hacerse necesariamente uno por uno,


como en el programa anterior. La lectura de las tres variables se podra
hacer tambin mediante:

printf(U Entre los coeficientes a b c U);


scanf(U%lf%lf%lf U, &a, &b, &c);

En este caso, durante la ejecucin del programa, despus de que sale en


pantalla el aviso" Entre los coeficientes a b c:", el usuario
debe digitar los tres valores, separados entre s por uno o ms espacios
en blanco, y finalizar oprimiendo la tecla Enter.
En C++, las entradas y salidas se hacen mediante cin y cout. El
programa anterior podra quedar de la siguiente manera:

II Calculo de las raices de una ecuacion cuadratica,


II cuando son reales.

#include <iostream.h>
#include <math.h>

int main()
{
double a, b, c, raiz1, raiz2, d, a2;

coutU\n Raices de a*x*x + b*x + C O. \n\n U ;

coutU a = u;
cina;

coutU b U
,
cinb;

coutU c = u;
cinc;

coutU\n uau x*x + ubu x + ucu O.\n\n U ;

33
2. GENERALIDADES

a2 = 2.0*a;
d = sqrt(b*b-4.0*a*c);
raizl (-b + d )/a2;
raiz2 = (-b - d )/a2;

cout" Las raices son: "raizl" "raiz2endl;


return O;
}

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 precisin.
La utilizacin de modificadores de formato como longitud de campo
y nmero de cifras decimales con las rdenes cin y cout, est fuera del
alcance de este libro.
Tambin 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 a b c ";


cinabc;

e no controla explcitamente las entradas, ni por teclado ni desde ar-


chivo. Por ejemplo, si el programa est esperando leer un nmero y el
usuario se equivoca y en lugar de digitar un cero digita la letra o, enton-
ces el programa hace alguna conversin y contina con el proceso. En
otros lenguajes, cuando esto sucede, el programa se detiene e informa
sobre el error.
e puede controlar si la lectura se efectu de manera adecuada ya
que la funcin scanf devuelve un valor entero que indica el nmero de
campos bien ledos y almacenados. Si no hubo almacenamiento, scanf
devuelve 0, en otros casos de error devuelve EOF (generalmente EOF
es lo mismo que -1). El control entonces se puede hacer con un if,
instruccin que se ver en el siguiente captulo. Una vez que el lector
conozca el manejo del if, puede volver a este prrafo para entender el
esquema siguiente que muestra cmo se podra hacer el control.

int result;

34
2.12. CONVERSIONES DE TIPO EN EXPRESIONES MIXTAS

result = scanf("%lf", &a);


if( result <= O ){

}
else {

A lo largo de este libro se supondr que la entrada de datos se hace con


valores adecuados y por tanto no se controla su funcionamiento. Pero,
en un nivel ms avanzado, un programador experimentado y cuidadoso
debera controlar siempre la entrada de datos.

2.12 Conversiones de tipo en expresiones


mixtas
Cuando en una expresin hay constantes o variables de distintos ti-
pos, C hace conversiones temporales de tipo, operacin (binaria) por
operacin, buscando el tipo que permita un mejor manejo de los ope-
randos, es decir, el tipo del operador de mayor nivel. Por ejemplo, en
una operacin binaria (como adicin, multiplicacin ... )

double y float --+ double,


double e int --+ double,
float e int --+ float,
short int e int --+ int,
long double y double --+ long double,
long double y float --+ long double,
long double e int --+ long double.

En el ejemplo

int i = 8, j = 3;
double x = 1.5, u, z,

35
2. GENERALIDADES

u = i/j*x;
z = i*x/j;
coutuendl;
coutzendl;
aparentemente u y z tienen el mismo valor, puesto que, segn el orden en
que se efectan las operaciones, en ambos casos se tiene (i x) / j. Pero
en realidad u vale 3.0 y z vale 4.0. En cada expresin hay dos operaciones
de igual prioridad, entonces el orden es de izquierda a derecha. Para u se
hace primero la divisin entera, con resultado 2, y enseguida el producto
doble precisin, y da 3.0. Para z se hace primero la multiplicacin doble
precisin, con resultado 12.0, y enseguida la divisin doble precisin, 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 algn momento se requiere usar
su valor como doble precisin. Esto se hace en C, anteponiendo el molde
(double). Por ejemplo:
int i, j;
double x, y;

i 3,
j 4;
y (double)i;
x y*y/(double)j;
En el ejemplo anterior, no se requiere colocar el molde a j, puesto
que la multiplicacin y*y da doble precisin, y al hacer la divisin de un
valor doble precisin por un entero, se hace previamente la conversin
del valor entero a doble precisin.
De igual manera se pueden utilizar los moldes (float) e (int). Al
utilizar el molde (int) para valores float o double, C trunca al entero
ms cercano comprendido entre O y el valor, o sea,
(int)x signo(x)llxlJ .

36
2.13. MOLDES

En C++ los moldes tienen forma funcional, visualmente ms clara. Por


ejemplo, el molde double ( ) es una funcin cuyo argumento es de cual-
quier tipo y el resultado es doble precisin. As, son ejemplos de moldes
en C++:

int i;
double y;

i = 3;
Y = sqrt(double(i));
l/y = sqrt(i);
coutyn nint(y)endl;

En este ejemplo tampoco se requiere el molde para i.

Ejercicios
Para cada uno de los enunciados siguientes, defina cules son los datos
necesarios. Haga un programa que lea los datos, realice los clculos y
muestre los resultados.

2.1 Resuelva un sistema de dos ecuaciones lineales con dos incgnitas.


Suponga que tiene una nica solucin.

2.2 Resuelva un sistema de tres ecuaciones lineales con tres incgnitas.


Suponga que tiene una nica solucin.

2.3 Resuelva una ecuacin polinmica (o polinomial) de tercer grado


por medio de la frmula de Tartaglia y Cardano. Suponga que se
tiene el caso ms sencillo.

2.4 Calcule el coseno de un ngulo medido en grados, minutos y se-


gundos.

2.5 Dado un ngulo en radianes, convirtalo a grados, minutos y se-


gundos.

2.6 Un objeto ha recorrido una distancia d (metros) en un tiempo


t (horas, minutos, segundos y milsimas de segundo). Calcule su
velocidad promedio en km/h y el nmero de segundos necesarios
para recorrer un kilmetro.

37
2. GENERALIDADES

2.7 Calcule la cuota mensual fija para un prstamo por un monto de


M pesos, con una tasa de inters mensual i (en porcentaje) y con
un plazo de n meses.

2.8 Dadas las longitudes de los lados de un tringulo, calcule, en gra-


dos, los ngulos.

2.9 Dadas las longitudes de los lados de un tringulo, calcule su rea.

2.10 Dadas las coordenadas, en JR.2, de los vrtices de un tringulo,


calcule, en grados, los tres ngulos.

2.11 Dadas las coordenadas, en JR.2, de los vrtices de un tringulo,


calcule su rea.

2.12 Dadas las coordenadas, en JR.2, de los vrtices de un tringulo,


calcule el centro del crculo inscrito.

2.13 Dadas las coordenadas, en JR.2, de los vrtices de un tringulo,


calcule el centro del crculo circunscrito.

2.14 Dadas las coordenadas, en JR.2, de los vrtices de un tringulo,


calcule el ortocentro.

2.15 Dadas las coordenadas, en JR.2, de los vrtices de un tringulo,


calcule el baricentro.

2.16 Dadas las coordenadas, en JR. 3, de los vrtices de un tringulo,


calcule, en grados, los 3 ngulos.

2.17 Dadas las coordenadas, en JR.3, de los vrtices de un tringulo,


calcule su rea.

2.18 Dadas las coordenadas de puntos puntos en JR. 3, calcule el volumen


del tetraedro y la rea total (suma de las cuatro reas).

2.19 Dadas las coordenadas de los vrtices de un cuadriltero convexo,


calcule su rea.

2.20 Dadas las coordenadas de los vrtices de un cuadriltero no con-


vexo, calcule su rea.

2.21 Calcule la distancia de un punto a una recta y encuentre el punto


de la recta ms cercano al punto dado.

38
2.13. MOLDES

2.22 Calcule la distancia de un punto a un plano y halle el punto del


plano ms cercano al punto dado.

2.23 Dada una parbola convexa (hacia arriba) y un punto X, encuentre


el punto de la parbola ms cercano a x.

2.24 Dado un plano y la recta que pasa por dos puntos u y v, halle el
punto de interseccin de la recta y el plano.

2.25 Dado un plano y la recta que pasa por un punto u y es paralela a


d, obtenga el punto de interseccin de la recta y el plano.

2.26 Dados dos vectores en ]R3, calcule el producto interno (escalar), el


ngulo entre ellos y el producto vectorial.

2.27 Hay dos maneras usuales de medir la eficiencia o la economa en


el consumo de combustible de un vehculo: nmero de litros ne-
cesarios para 100 kilmetros, y nmero de kilmetros por galn.
Dado el nmero de litros para 100 kilmetros, calcule el nmero
de kilmetros por galn.

2.28 Dado el nmero de kilmetros por galn, calcule nmero de litros


para 100 kilmetros.

)
/

39
2.13. MOLDES

2.22 Calcule la distancia de un punto a un plano y halle el punto del


plano ms cercano al punto dado.

2.23 Dada una parbola convexa (hacia arriba) y un punto X, encuentre


el punto de la parbola ms cercano a x.

2.24 Dado un plano y la recta que pasa por dos puntos u y v, halle el
punto de interseccin de la recta y el plano.

2.25 Dado un plano y la recta que pasa por un punto u y es paralela a


d, obtenga el punto de interseccin de la recta y el plano.

2.26 Dados dos vectores en ]R3, calcule el producto interno (escalar), el


ngulo entre ellos y el producto vectorial.

2.27 Hay dos maneras usuales de medir la eficiencia o la economa en


el consumo de combustible de un vehculo: nmero de litros ne-
cesarios para 100 kilmetros, y nmero de kilmetros por galn.
Dado el nmero de litros para 100 kilmetros, calcule el nmero
de kilmetros por galn.

2.28 Dado el nmero de kilmetros por galn, calcule nmero de litros


para 100 kilmetros.

)
/

39
3

Estructuras de control

En los ejemplos vistos hasta ahora, los programas tienen una estruc-
tura lineal, es decir, primero se efecta la primera orden o sentencia,
enseguida la segunda, despus la tercera y as sucesivamente hasta la
ltima. Por el contrario, la mayora de los programas, dependiendo del
cumplimiento o no de alguna condicin, toman decisiones diferentes.
Tambin es muy usual repetir una o varias instrucciones mientras sea
cierta una condicin. Estas bifurcaciones y repeticiones se logran me-
diante las sentencias o estructuras de control.
(
3.1 if

En uno de los casos ms sencillos el if tiene la siguiente forma:

sentencia_1 ;
if ( condicion) sentencia_a;
else sentencia_b;
sentencia_2 ;

La lneas primera y ltima no hacen parte del if, pero aparecen para ver
mejor la secuencia de realizacin de las rdenes. Tal como est presenta-
do, las rdenes de estas dos lneas siempre se realizan. Si la condicin se
cumple, se realiza sentencia_a, y si no se cumple, se realiza sentencia_b.
En resumen, dependiendo de que se cumpla o no la condicin, se realiza

41
3. ESTRUCTURAS DE CONTROL

una de las dos secuencias siguientes:

sentencia_l ; sentencia_l ;
sentencia_a; sentencia_b;
sentencia_2 ; sentencia_2 ;

El siguiente ejemplo, muy sencillo, permite asignar a e el mximo entre


a y b.

double a, b, e;

printf (" a = %lf b %lf\n", a, b);


i f ( a >= b ) e = a;
el se e = b;
printf(" e = %lf\n", e);

En este ejemplo no estn todas las instrucciones necesarias para el fun-


cionamiento correcto; aparecen nicamente las instrucciones ms rele-
vantes para ilustrar el tema en estudio. Los puntos suspensivos indi-
can 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 la anterior convencin a lo
largo del libro.
En la estructura i f no es necesaria la parte else. Se puede tener
una estructura de la siguiente forma.

sentencia_l ;
i f ( condicion) sentencia_a;
sentencia_2 ;

En este caso, si la condicin 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 realizacin son:

sentencia_l; sentencia_l ;
sentencia_a; sentencia_2 ;
sentencia_2 ;

En el siguiente ejemplo, tambin se asigna a e el mximo entre a y b.

int a, b, e;

42
3.1. IF

cout" a = "a" b "bendl;


e = a',
if( b > a ) e = b;
cout" e = "cendl;

En el if, tanto sentencia_a como sentencia_b se pueden reemplazar por


bloques de sentencias. Un bloque de sentencias, o simplemente un
bloque, es una sucesin de sentencias encerradas entre llaves {, }.

sentencia_l ;
if ( condicion) {
sentencia_al;
sentencia_a2 ;

}
el se {
sentencia_bl;
sentencia_b2 ;

}
sentencia_2 ;

Si la condicin se cumple, se realiza el primer bloque; si no se cumple, se


realiza el segundo bloque. En resumen, dependiendo de que se cumpla o
no la condicin, se realiza una de las dos secuencias siguientes:

sentencia_l; sentencia_l ;
sentencia_al; sentencia_bl;
sentencia_a2 ; sentencia_b2 ;

sentencia_2 ;

Un i f puede anidar (dentro de l), uno o varios i f u otras estructuras


de control, que a su vez pueden anidar otras estructuras de control.
El siguiente programa considera las races reales y las races comple-
jas de una ecuacin cuadrtica, dependiendo del valor del discriminante
b2 - 4ac.

43
3. ESTRUCTURAS DE CONTROL

II Raices de una ecuacion cuadratica.

II#include <iostream.h>
#include <math.h>
#include <stdio.h>

int mainO
{
double a, b, c, raizl, raiz2, d, a2, pReal, plmag;

printf("\n Raices de a*x*x + b*x + c O.\n\n");

printf(" Entre los coeficientes a b c lO);


scanf("%lf%lf%lf", &a, &b, &c);

printf (" \n %lf x*x + %lf x + %lf O.\n\n", a, b, c);

a2 = 2.0*a;
d = b*b-4.0*a*c;
i f ( d >= O. O ){
II raices reales
d = sqrt(d);
raizl = (-b + d )/a2;
raiz2 = (-b - d )/a2;
printf("\n Raices reales: %lf , %lf\n", raizl,
raiz2);
}
else{
II raices complejas
d = sqrt(-d);
pReal = -b/a2;
plmag = d/a2;
printf("\n Raices complejas: lO);
printf("%lf + %lf i , %lf - %lf i\n",
pReal, plmag, pReal, plmag);
}
return O;
}

44
3.2. OPERADORES RELACIONALES Y LGICOS

3.2 Operadores relacionales y lgicos


Los operadores relacionales -mayor, menor, mayor o igual, menor
o igual, igual, diferente- permiten comparar dos variables o valores
generalmente numricos:

< menor
> mayor
<= menor o igual
>= mayor o igual
igual
!= diferente

Los operadores lgicos son:

&& y
11 o
no

Sus tablas de verdad son exactamente las mismas de la lgica ele-


mental. Sean p, q dos proposiciones. La proposicin p y q es verdadera
nicamente cuando ambas son verdaderas; en los dems casos es falsa.
La proposicin p o q es verdadera cuando alguna de las dos es verdade-
ra; es falsa nicamente cuando las dos son falsas. La negacin de una
proposicin verdadera es falsa; la negacin de una proposicin falsa es
verdadera.
Como en C no existe explcitamente un tipo de dato lgico o boo-
leano, entonces se usan los enteros. As, falso se hace equivalente a O y
verdadero a cualquier valor no nulo, usualmente 1. Consecuentemente
en C, ms que mirar si una condicin es verdadera o falsa, se mira si la
expresin es no nula o nula.

Por ejemplo, es lo mismo escribir

if( i != O ) ..

que escribir

i f ( i ) ...

45
3. ESTRUCTURAS DE CONTROL

La primera expresin es, tal vez, ms fcil de entender, pues concuerda


con nuestra manera lgica de razonar. Es ms claro decir "si i es diferente
de cero ... " que decir" si i ... ".
Tambin se puede escribir como condicin del i f (y de otras estruc-
turas de control) expresiones menos simples.

if ( a*c-b*d ) ...

Ms an, esa expresin puede ser de tipo doble precisin. Esto es lci-
to aunque no muy usual. La condicin sera falsa nicamente cuando
a*c-b*d fuera exactamente 0.0. Para otros valores, an muy cercanos a
cero, como 1. OE-20, la condicin es verdadera. Lo anterior es un poco
inexacto, en realidad depende del compilador, del computador y del tipo
de la expresin. Para un valor doble precisin, en algunos compiladores,
los valores positivos menores a 2. 4E-323 se consideran nulos.
Como las comparaciones dan como resultado un valor entero O 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, enton-


ces n toma el valor O. El programa anterior, prog04a, haca el clculo
de las races reales o complejas de una ecuacin cuadrtica, pero no con-
sideraba algunos casos muy raros, pero posibles. Por ejemplo, a puede
ser cero, entonces la ecuacin no solamente no es cuadrtica, sino que el
programa presenta una divisin por cero (situacin que un programador
siempre debe evitar). El siguiente programa usa estructuras i f anidadas
y considera todos los posibles casos.

II Raices de una ecuacion cuadratica.


II Considera los casos extremos: a=O, a=b=O ...

II#include <iostream.h>
#include <math.h>
#include <stdio.h>

int main()
{

46
3.2. OPERADORES RELACIONALES Y LGICOS

double a, b, c, raizl, raiz2, d, a2, pReal, plmag;

printf("\n Raices de a*x*x + b*x + C = O.\n\n");

printf(" Entre los coeficientes a b c: ");


scanf("%lf%lf%lf" , &a, &b, &c);

printf ("\n %lf x*x + %lf x + %lf O.\n\n", a, b, c);

if( a != 0.0 ){
II ecuacion realmente cuadratica
a2 = 2.0*a;
d = b*b-4.0*a*c;
if ( d >= O. O ){
II raices reales
d = sqrt(d);
raizl = (-b + d )/a2;
raiz2 = (-b - d )/a2;
printf("\n Raices reales: ");
printf (" %lf , %lf\n" , raizl, raiz2);
}
else{
II raices complejas
d = sqrt(-d);
pReal = -b/a2;
plmag = d/a2;
printf("\n Raices complejas: ");
printf("%lf +- %lf i\n", pReal, plmag);
}
}
else{
II ecuacion no cuadratica
if( b != 0.0 ){
II ecuacion lineal
printf ("La ecuacion es lineal. Su raiz es: %lf\n",
-c/b);
}
else{

47
3. ESTRUCTURAS DE CONTROL

if( e == 0.0 )printf(" Todo real es solucion.\n");


else printf(" No hay solucion.\n");
}
}
return O;
}

3.3 for

La estructura for permite repetir varias veces una sentencia o una


secuencia de sentencias. Esta estructura repetitiva recibe el nombre de
bucle, lo mismo que las estructuras while y do while que se vern ms
adelante.
La aplicacin clsica del f or consiste en hacer algo para i variando
desde 1 hasta n. En el siguiente ejemplo, se calcula la suma de 1 hasta
15 de l/i con escritura de las sumas parciales.

double suma;
int i;

suma = 0.0;
for( i=1; i <= 15; i++){
suma += 1.0/i;
printf("%5d %12. 6lf\n" , i, suma);
}

Inicialmente i vale 1. Si i es menor o igual que 15, entonces se actualiza


suma y se hace la escritura. Enseguida se incrementa i en una unidad; si
todava i es menor o igual que 15 se repite el proceso. Al final se hace el
proceso para i con valor de 15. De nuevo se incrementa el valor de i, su
nuevo valor es 16. Ahora i no cumple la condicin, entonces se detiene
el proceso.

48
3.3. FOR

La forma general del f or es:

sentencia_a;
for(INIC; CDC; MODIF) {
sentencia_l ;
sentencia_2 ;

}
sentencia_b;

Si se necesita repetir una sola instruccin, la forma del for es:

sentencia_a;
for(INIC; CDC; MODIF) sentencia_l;
sentencia_b;

Dentro de los parntesis del f or hay tres partes:


inicializacin,
condicin de continuacin,
modificacin.
Las partes estn separadas entre s por punto y coma. Usualmente,
pero no es obligatorio, hay una variable llamada de control; en el ejemplo
anterior es la variable i.
En la inicializacin se asigna a la variable de control su valor inicial.
Esto se hace una sola vez, no se vuelve a hacer en el f or. Es lo primero
que se hace antes del resto del foro
Si la condicin de continuacin se cumple (si la expresin es no nula),
entonces se realiza el cuerpo del for (lo que est entre las llaves o la
nica instruccin presente). Si la primera vez no se cumple la condicin,
entonces nunca se realiza el cuerpo del f or.
Cada vez que se realiza el cuerpo del f or, despus de realizar la lti-
ma instruccin, se efecta la modificacin que est indicada en la tercera
parte. En muchos casos lo que se hace es simplemente incrementar en
una unidad la variable de control.
Ninguna de las tres partes es indispensable. Lo nico realmente in-
dispensable es la presencia de los dos signos punto y coma. El siguiente
ejemplo no presenta errores de sintaxis, pero tiene un defecto muy des-
agradable, nunca acaba.

49
3. ESTRUCTURAS DE CONTROL

for( ) cout"Buenos dias\n";

En el siguiente ejemplo se calcula el factorial de n, cuando n es pequeo.


El resultado es un valor entero. Para valores de n mayores que 12 es
necesario que la variable nFact sea doble precisin.

int n, i, nFact;

cout" n 11

cinn;
nFact = 1;
for( i = 2; i <= n; i++) nFact *= i;
coutnFact;

En la parte de inicializacin del for puede haber ms de una iniciali-


zacin. En este caso deben estar separadas por una coma. De manera
anloga, puede haber ms de una modificacin y tambin es necesario
separar con una coma. En el siguiente ejemplo, i empieza en 1 y j
empieza en 20; al final de cada repeticin i, aumenta en una unidad y
j disminuye en 2 unidades.

int n, i, j, suma;

n = 20;
suma = O;
for( i=l, j=n; i<j && i*i<j*j-l0*j i++, j 2){
suma += i+j;
printf(" %d %d \n",i,j);
}
printf(1I suma %d \n", suma);

El resultado producido ser la escritura de los valores de i y de j y al


final el valor de suma. Entonces escribir:

1 20
2 18
3 16
4 14
suma = 78

50
3.4. WHILE

Despus de realizar el for con i=4 y j=14, se hacen las modificaciones


indicadas; i pasa a valer 5 y j valdr 12. Se cumple la condicin i <j,
pero no la condicin i*i<j*j-10*j. Entonces se acaba el for y se pasa
a la siguiente instruccin, es decir, la escritura de suma.

3.4 while
La estructura while permite repetir varias veces una sentencia o
una secuencia de sentencias. Es como una simplificacin del f or. Aqu
no hay variable de control, no hay una parte explcita de inicializacin
ni de modificacin. Usualmente en el for se conoca por anticipado el
nmero de veces que se iba a efectuar el cuerpo del foro En el while,
simplemente, cuando no se cumpla la condicin se acaba el while. La
forma general del while es:
sentencia_a;
while ( condicion ) {
sentencia_1 ;
sentencia_2 ;

}
sentencia_b;
Si se necesita repetir una sola instruccin, la forma del while es:
sentencia_a;
while ( condicion ) sentencia_1;
sentencia_b;
Despus de sentencia_a, para empezar el while se verifica la condicin
de continuacin. Si se cumple, se realizan las sentencias dentro del cuerpo
del while: sentencia_1 , sentencia_2 ... Cada vez que se realiza la ltima
sentencia dentro del cuerpo del while, se pasa a verificar la condicin,
y si se cumple, se vuelve a realizar el grupo de sentencias del while. Si
la primera vez no se cumple la condicin, entonces nunca se efectan las
sentencias del while.
El desarrollo en serie de Taylor para la funcin exponencial est dado
por:

51
3. ESTRUCTURAS DE CONTROL

La frmula anterior es exacta, pero irrealizable para hacer una evalua-


cin numrica, puesto que no se puede efectuar un nmero infinito de
operaciones (n vara desde 1 hasta infinito). Lo que se hace usualmen-
te es aplicar la frmula hasta que el trmino xn In! sea muy pequeo
comparado con la suma parcial. Sea
n
Xk
ak = k! ' Sn = Lak'
k=O

Dado un valor positivo cercano a cero, por ejemplo 0.00000001, el


clculo aproximado de eX se realiza hasta que

lanl < .
1+ ISnl -
El 1 en el denominador se coloc simplemente para asegurar que el
denominador no sea nulo. Una salida ms elegante y precisa sera evaluar
una cota para el resto y utilizar este valor para detener el proceso.

// Programa para calcular una aproximacion de exp(x).

#include <math.h>
#include <stdio.h>

int maine)
{
double x, sn, an, nFact, eps;
int n;

printf(lI\n Calculo aproximado de exp(x).\n\n x " ) ;


scanf("%lf", &x);

eps = 1. Oe-8 ;
sn = 1.0 + x;
nFact = 1;
n = 1;
an = x;
while( fabs(an)/( 1.0 + fabs(sn) ) > eps ){
n++;
nFact *= n;

52
3.4. WHILE

an = pow(x,n)/nFact;
sn += an;
}
printf(" exp(x) %lf\n", sn);
return O;
}

Se puede lograr ms eficiencia, se evita el uso de pow y el clculo explcito


de n!, si se tiene en cuenta que
x
n
eps = 1. Oe-8;
sn = 1.0 + x;
n = 1;
an = x;
while( fabs(an)/( 1.0 + fabs(sn) ) > eps ){
n++;
an *= x/ni
sn += an;
}

Para la funcin coseno, su serie de Taylor, alrededor de cero, es:

X2 x4 x6 (Xl x2n
cos X = 1 - 2 + 24 - 720 + ... = 2:) -1 t
n=
(2n)!

La (una) frmula recursiva es:

2n(2n - 1) .

La porcin de programa siguiente calcula una aproximacin del valor de


cosx.

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. Oe-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
Es muy parecida a la estructura while, pero el control se hace al
final. Esto hace que el cuerpo del do while siempre se realice por lo
menos una vez. La forma general del do while es:
sentencia_a;
do {
sentencia_l ;
sentencia_2 ;

} while ( condicion );
sentencia_b;
Si se necesita repetir una sola instruccin, la forma del do-while es:
sentencia_a;
do sentencia_l;
while ( condicion );
sentencia_b;
Consideremos dos enteros positivos P y q. Su mximo comn divisor se
puede calcular por el algoritmo de Euclides. Este es un proceso iterativo
en el que en cada iteracin, dados dos enteros positivos Pk 2: qk, se halla
el cociente Ck y el residuo rk al dividir Pk por qk:

Pk = Ckqk + rk
54
3.5. DO WHILE

Para pasar a la nueva iteracin, el divisor pasa a ser dividendo y el


residuo pasa a ser divisor.

Pk+l = qk,
qk+l = Tk

El proceso se repite hasta que el residuo sea nulo. El mximo comn


divisor estar dado por el ltimo divisor q. Por ejemplo, consideremos
P = 60, q = 18. La siguiente tabla muestra los pasos intermedios del
algoritmo
Pk qk Ck Tk
60 18 3 6
18 6 3 O
Entonces el mximo comn divisor es 6. Para P = 34, q 15, los si-
guientes son los resultados parciales.

Pk qk Ck Tk
34 15 2 4
15 4 3 3
4 3 1 1
3 1 3 O

Entonces el mximo comn divisor es 1, es decir, 34 y 15 son primos


relativos.
Este algoritmo es un ejemplo adecuado para ver la utilizacin de la
estructura de control do-while. Es necesario efectuar por lo menos una
divisin. Si ese primer residuo fuera nulo, el m.c.d. sera el menor de los
dos nmeros.

II Maximo comun divisor de dos numeros

II#include <iostream.h>
#include <math.h>
#include <stdio.h>

int maine)
{
int p, q, e, r, temp;

printf("\n Maximo comun divisor de 2 enteros positivos");

55
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);

if( p < 1 II q < 1 ){


printf("\n\n Numeros inadecuados\n\n");
return;
}
II intercambio, si necesario, para que p > q
if(p<q){
temp = p;
p q;
q = temp;
}
do{
c = p/q;
r = p%q;
printf ( "%5d%5d%5d%5d \n", p, q, c, r);
p = q;
q = r;
} while( r!= O);
printf(" m.c.d. %d\n", p);
return O;
}

Observe que, para que dos variables intercambien sus valores, se ne-
cesita utilizar una variable intermedia que almacene temporalmente uno
de los dos valores.
La instruccin return permite salir inmediatamente de la funcin,
en este caso de la funcin main, es decir, permite salir del programa.
Ms adelante se ver que return tambin sirve para que las funciones
devuelvan un valor.

56
3.6. SWITCH

3.6 switch

El if permite la bifurcacin en dos vas, dependiendo de la verdad o


falsedad de una expresin. Algunas veces se requiere que la bifurcacin
se haga en ms de dos vas, dependiendo de que una variable de control
tome un valor, otro valor, un tercer valor ... Esto se podra hacer mediante
varios if, pero es poco elegante y pierde claridad. La estructura switch
permite las bifurcaciones en varias vas dependiendo de una variable de
control, cuyo tipo debe ser necesariamente int ochar. La forma general
es la siguiente:
switch( variable ){
case valorl :
sentencia_Ll
sentencia_l_2

break;
case valor2
sentencia_2_1

break;

default :
sentencia_d_l

}
sentencia_b;
Si la variable de control tiene el primer valor, se efectan las sentencias
del primer grupo y despus el programa pasa a realizar sentencia_b. Si
la variable de control tiene el segundo valor, se efectan las sentencias
del segundo grupo y despus 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 def aul t y en seguida efecta
sentencia_b. La parte def aul t no es indispensable desde el punto de
vista de la sintaxis, pero en la prctica puede ser 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 sim-
plemente case valor _i: case valor _j: grupo de sentencias.

57
3. ESTRUCTURAS DE CONTROL

En el siguiente ejemplo, a partir de una nota, valor entero entre


50, se escribe un aviso:

y

"Aprueba. Muy bien." si 40 :::; nota:::; 50,


"Aprueba." si 30 :::; nota:::; 39,
"Puede habilitar." si 20 :::; nota:::; 29,
"Reprueba." si : :;
nota:::; 19,
La siguiente porcin de programa hace la implementacin, basada
en la cifra de las decenas.

int nota, dec;

printf(1I nota = ");


scanf("%d", &nota);
if( O <= nota && nota <= 50 ){
dec = nota/lO;
switch( dec ){
case 5: case 4:
printf(1I %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(1I %2d Reprueba.\n", nota);
break;
}
}
el se printf(1I %d Nota inadecuada. \n", nota);

3.7 break
Adems del uso en la estructura switch, la instruccin 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

algunos casos, en programas bastante complejos puede ser til salir del
bucle, mediante un if, en un sitio intermedio del bucle. Para esto se usa
la instruccin break.
sentencia_a;
for( INIC; CDC; MODIF ){
sentencia_1 ;
sentencia_2 ;

if ( condicion_2 ) {
sentencia_c1 ;
sentencia_c2 ;

break;
}

}
sentencia_b;
Si en una pasada del programa por el cuerpo del bucle, se cumple la con-
dicin del if, condicion_2, entonces el programa realiza las instrucciones
sentencia_c_1, sentencia_c2, ... , y salta a la instruccin sentencia_b.
La siguiente porcin de programa calcula la suma de los enteros entre
ni inclusive y n2 inclusive, menores que el mnimo mltiplo de 10 en ese
mismo intervalo. Si en el conjunto {ni, ni +i ... , n2} no hay mltiplos
de 10, calcula la suma de todos ellos. Tambin calcula la suma de los
cuadrados de esos enteros.

int ni, n2, i, div, res;


double sx, sxx;

div = iO;
printf(" ni n2 : ");
scanf("%d%d", &ni, &n2);

sx = 0.0;
sxx = 0.0;
for( i = ni; i <= n2; i++){
res = i%div;
if( !res ) break; II if( res o) break;

59
3. ESTRUCTURAS DE CONTROL

sx += i;
sxx += i*i;
printf ("%5d\n", i);
}
printf(" suma x %lf, suma x*x %lf\n", sx, sxx);

Si hay varios bucles anidados, la instruccin f or permite salir de un solo


bucle, del bucle ms interno donde se encuentra el break.

3.8 continue
La instruccin continue permite saltar la parte restante del cuerpo
de un bucle -for, while o do while- y pasar a empezar una nueva
iteracin. Su uso en una parte intermediaria de un bucle va asociado
generalmente a un if.

sentencia_a;
for(INIC; CDC; MODIF) {
sentencia_l ;
sentencia_2 ;

if ( condicion_2 ) {
sentencia_c_l ;
sentencia_c2 ;

continue;
}
sentencia_3 ;
sentenciaA;

}
sentencia_b;

Si en una pasada del programa por el cuerpo del bucle, se cumple la con-
dicin del if, condicion_2, entonces el programa realiza las instrucciones
sentencia_cl, sentencia_c_2, ... , y vuelve a empezar una nueva itera-
cin sin ejecutar las sentencias restantes del bloque for (sentencia_3,
sentenciaA ... ). Como en el esquema anterior se trata de un for, en-
tonces realiza la modificacin indicada en MODIF.

60
3.9. GOTO y EXIT

La siguiente porcin de programa calcula la suma de los enteros no


mltiplos de 10, entre nl inclusive y n2 inclusive. Tambin calcula la
suma de los cuadrados de esos enteros.

int nl, n2, i, div, res;


double sx, sxx;

div = 10;
printf (" nl n2 : ");
scanf("%d%d", &nl, &n2);

sx = 0.0;
sxx = 0.0;
for( i = nl; i <= n2; i++){
res = i%div;
if( !res ) continue; II if( res O ) 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 mltiplo de 10, el programa pasa


a efectuar una nueva iteracin; entonces, antes de calcular res, como
est indicado en este for, incrementa en una unidad el valor de i.

3.9 goto y exit

La instruccin goto no debera usarse en los programas llamados


bien estructurados, pues permite salidas mltiples de un bucle y adems
puede transferir la secuencia del programa a instrucciones diferentes de
la siguiente al bucle. Sin embargo, usado con moderacin y en casos de
real necesidad, puede ser til, por ejemplo, para salir de varios bucles
anidados mediante una sola instruccin.
El goto debe estar seguido del nombre de una etiqueta. Una etiqueta
es simplemente un identificador seguido de dos puntos. La etiqueta debe
existir dentro de la misma funcin donde est el goto. Hasta ahora slo
se ha visto la funcin main. El siguiente captulo corresponde justamente

61
3. ESTRUCTURAS DE CONTROL

al tema de las funciones.

goto final!;

final! :

La funcin exi t ( ), en la biblioteca estndar, cuyo archivo de cabecera


es stdlib.h, permite salir anticipadamente de un programa. General-
mente se usa exi t (O) para indicar que se trata de una terminacin
normal y exi t (1) para indicar algn problema durante el programa
(tambin podra ser otro valor diferente de O).
Una de las formas para saber si un entero n, mayor que 1, es primo,
consiste en averiguar si n es divisible por los enteros entre 2 y la raz
cuadrada de n. El siguiente programa implementa este sencillo algorit-
mo.

II Programa para saber si un entero mayor que 1 es primo

II#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 n > 1 es primo.\n");


printf("\n n = 11);
scanf("%d", &n);
printf("\n\n n = %d", n);

if ( n<= 1 ){
printf(lI\n\n Valor inadecuado.\n\n");
exit (1) ;

62
3.9. GOTO y EXIT

}
nPrimo = 1;
II 1 indica que n es primo, O indica que no.
II Inicialmente se supone que n es primo.
for( i=2; i*i <= n; i++){
res = n%i; II residuo
if( !res ){
nPrimo = O;
break;
}
}
if( nPrimo ) printf(" es primo.\n");
else printf(II no es primo, es divisible por %d\n", i);
return O;
}

Ejercicios
Para cada uno de los enunciados siguientes, defina cules son los da-
tos necesarios. Haga un programa que lea los datos, verifique que no hay
inconsistencias (por ejemplo, distancias negativas o nulas; dos vrtices
de un tringulo iguales; recta que pasa por un punto paralela a d = O... ),
estudie todas las posibilidades relajando algunas suposiciones (por ejem-
plo: solucin nica, sin solucin, nmero infinito de soluciones ... ), realice
los clculos y muestre los resultados.

3.1 Considere los ejercicios del captulo anterior.

3.2 Dadas las longitudes de los lados de un tringulo, averige si ste


es acutngulo, rectngulo u obtusngulo.

3.3 Escriba la expresin binaria, en orden inverso, de un entero no


negativo.

3.4 Escriba la expresin en base p (p entero, 2 ::; p ::; 9), en orden


inverso, de un entero no negativo.

3.5 Escriba la expresin hexadecimal, en orden inverso, de un entero


no negativo.

63
3. ESTRUCTURAS DE CONTROL

3.6 Escriba en letras un entero n, 31 S n S 99.

3.7 Escriba en letras un entero n, 1 S n S 99.

3.8 Escriba en letras un entero n, 1 S n S 999.

3.9 Calcule una aproximacin del valor de e utilizando parte de la serie

00 1
Lk!'
k=

3.10 Calcule por medio de la serie de Taylor truncada un valor apro-


ximado de seno(x). Muestre el nmero de trminos de la serie
necesarios para que el valor absoluto de la diferencia entre el valor
obtenido y el valor producido por la funcin sin sea menor que
1.0E-12.

3.11 Convierta coordenadas cartesianas en polares.

3.12 Convierta coordenadas cartesianas en esfricas.

3.13 Convierta coordenadas polares en cartesianas.

3.14 Convierta coordenadas esfricas en cartesianas.

3.15 Dados tres nmeros, escrbalos en orden creciente.

3.16 Dados tres nmeros, escrbalos en orden decreciente.

3.17 Dados cuatro nmeros, escrbalos en orden creciente.

3.18 Dados cuatro nmeros, escrbalos en orden decreciente.

3.19 Calcule el mnimo comn mltiplo 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 zn, donde z es un complejo y n un entero positivo.

3.24 Dado un entero positivo n, escriba los primos menores o iguales a


n.

64
3.9. GOTO y EXIT

3.25 Dado un entero positivo n, calcule el nmero de primos menores


o iguales a n.

3.26 Dado un entero positivo n, calcule su descomposicin canomca,


n = pr.: 1p;;:2 ... p";k , donde los Pi son primos diferentes y los mi son
enteros positivos.

3.27 Dado un entero positivo n, calcule la funcin de Mbius f..L(n). Re-


curdese que f..L(1) = 1, f..L(n) = a si n es divisible por un cuadrado
distinto de 1; f..L (n) = (-1) k si 1 es el nico cuadrado divisor de n
y n tiene k divisores primos.

3.28 Dado un entero positivo n, calcule por conteo la funcin de Euler


<p(n). Recurdese que <p(n) indica el nmero de primos relativos
con n en el conjunto {a, 1,2, ... , n - 1}. Por convencin <p(1) = 1.

3.29 Dado un entero positivo n, calcule la funcin de Euler <p(n). Re-


curdese que <p(1) = 1 Y para n > 1, si la descomposicin cannica
es n = PImI P2m2 . "Pkmk ' ent onces

1 1 1
<p(n) = n(1 - - )(1 - - ) ... (1 - -).
PI P2 Pk

3.30 Dados tres enteros a, b y m positivos, halle todas las soluciones de


la congruencia ax == b (md. m).

3.31 Dados un nmero x y un entero no negativo n, calcule una apro-


ximacin de la funcin de Bessel de primera clase y de grado n,

n 00 (-1)m x2m
Jn(x) = x L
m=O
22m+n m! (n + m)!'

= ~ (_1)m (~)2m+n.
~ m! (n+m)! 2
m=O

3.32 Halle, para el compilador y el computador que usted usa, el ma-


yor entero y el menor entero utilizables con variables tipo int.
Compare con los valores de limits.h

65
3. ESTRUCTURAS DE CONTROL

3.33 Halle, para el compilador y el computador que usted usa, el mayor


entero y el menor entero utilizables con variables tipo long int.
Compare con los valores de limi ts . h

3.34 Halle, para el compilador y el computador que usted usa, el mayor


entero y el menor entero utilizables con variables tipo unsigned
int. Compare con los valores de limi ts. h

3.35 Dado un entero positivo n, escriba los primeros n nmeros de Fi-


bonacci. Recurdese que Ul = 1, U2 = 1, Uk = Uk-l + Uk-2, k 2: 3.

3.36 Dado un nmero x y un entero no negativo n, calcule el polinomio


de Legendre de grado n evaluado en x. Recurdese que Po(x) = 1,
Pl(X) = X = 1,

2k+ 1 k
Pk+1(X) = -k-- x Pk(X) - -k-Pk-1(X).
+1 +1

66
4

Funciones

Como se mencion anteriormente, de manera muy esquemtica, se


puede decir que un programa fuente en C es una sucesin de funciones
que se llaman (se utilizan) entre s. Siempre tiene que estar la funcin
main.

4.1 Generalidades
La forma general de una funcin en C es la que se presenta a con-
tinuacin. Posteriormente hay varios ejemplos que permiten un mejor
manejo de las las funciones.

tipo nombre_funcionCtipo argumento, tipo argumento, ... )


{
cuerpo de la funcon
}

Considere el siguiente programa. En l hay una funcin que calcula el


factorial de un nmero entero. Esta funcin es llamada varias veces desde
el programa principal.

II Factorial de los enteros entre O y 15.


II Usa una funciono
11---------------------------------------------------------
#include <math.h>
#include <stdio.h>

67
4. FUNCIONES

#include <stdlib.h>
jj---------------------------------------------------------
double fact( int k );
jj=========================================================
int maine)
{
int n;

printf("\n Factorial de los enteros en [0,15J\n");

printf("\n\n n n!\n\n");
for( n = O; n <= 15; n++){
printf(I%5d%14.01f\n", n, fact(n));
}
return O;
}
jj=========================================================
double fact( int k )
{
jj calcula el factorial de k >= O
jj devuelve O si k < O.

int n;
double kFact 1.0;

H( k < O ){
printf(" %d valor inadecuado para factorial\n");
return 0.0;
}
for( n = 2; n <= k; n++) kFact *= n;
return kFact;
}

Antes del comienzo de la funcin main est el prototipo de la funcin


fact. Este prototipo es casi igual a la primera lnea del sitio donde
realmente se define la funcin, despus del final de la funcin main. La
nica diferencia es que al final del prototipo hay un punto y coma. El
prototipo informa que la funcin f act devuelve un valor doble precisin
y tiene un nico parmetro (o argumento) tipo entero.

68
4.1. GENERALIDADES

El cuerpo de la funcin debe estar entre dos corchetes (entre { y } ).


La funcin usa dos variables, n de tipo entero y kFact de tipo doble
precisin. Esta variable n de la funcin f act es completamente distinta
de la variable n de la funcin main.
Como la funcin f act devuelve un valor (hay funciones que no de-
vuelven ningn valor), en alguna parte del cuerpo de la funcin, por
lo menos una vez, debe estar return seguido de un valor adecuado.
Adems, siempre la ltima instruccin en una salida normal de la fun-
cin, antes de que el programa regrese al sitio donde fue llamada la
funcin, debe ser un return. Por ejemplo, la siguiente modificacin pro-
duce, durante su compilacin, advertencias (warnings) sobre posibles
errores.

double factMal( int k )


{
int n;
double kFact 1.0;

if( k < O ){
printf(" %d valor inadecuado para factorial\n");
return 0.0;
}
return kFact;
for( n = 2; n <= k; n++) kFact *= n;
}

La lnea for nunca se realizara pues el programa al pasar por return


kFact sale de la funcin.
La funcin del siguiente ejemplo tiene un nico parmetro entero
y no devuelve ningn valor. Esto se indica por medio de void. Esta
funcin simplemente escribe en la pantalla el nmero indicado de lneas
en blanco (en realidad hace n saltos de lnea). Su llamado puede ser
lineas (2); o tambin lineas (j) ;

void linease int n )


{
II escribe n lineas en blanco.

int i;

69
4. FUNCIONES

for( i 1; i <= n; i++) printf("\n");


}

La siguiente funcin tiene dos parmetros doble precisin y devuelve un


valor doble precisin. Devuelve el valor dominante entre dos valores. El
valor dominante es aquel cuyo valor absoluto es mayor.

double dominante( double a, double b )


{
II calcula el valor dominante.

if( fabs(a) >= fabs(b) ) return a;


else return b;
}

La funcin del siguiente ejemplo no tiene parmetros ni devuelve un


valor. Su oficio es simplemente crear una detencin hasta que el usuario
oprima la tecla Enter. Su llamado es simplemente pausaO ;

void pausa(void)
{
char c;

printf(" Oprima ENTER para continuar ");


scanf(lI%c",&c);
}

En el ejemplo que sigue, tambin hay una pausa hasta que el usuario
oprima cualquier tecla. Requiere el uso de la funcin getchO, que no
hace parte de la norma ANSI C. Su archivo de cabecera es conio.h.
Viene con algunos compiladores, por ejemplo, los de la casa Borland.

void pausa2(void)
{
II necesita conio.h

printf(" Oprima una tecla para continuar ");


getchO;
}

70
4. FUNCIONES

Si no se ha encontrado una raz, el proceso contina con uno de los dos


intervalos [a, m] o [m, b]. En cada iteracin el tamao del intervalo se
reduce a la mitad. Entonces, o se encuentra la raz, o se llega a un inter-
valo muy pequeo donde hay una raz y cualquiera de los dos extremos
del intervalo se puede considerar como raz.
Por ejemplo, considere la ecuacin f(x) = x 5 - 3x 4 + lOx - 8 = O.
f(2) = -4, f(3) = 22,
adems, f es continua en el intervalo [2, 3], luego se puede iniciar el
mtodo de biseccin. 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) > O, luego el
nuevo intervalo ser [2.5, 3].
El punto medio es m = 2.75, f(2.75) = 5.202, f(a)f(m) < O, luego el
nuevo intervalo ser [2.5, 2.75].
El punto medio es m = 2.625, f(2.625) = 0.445, f(a)f(m) < O, luego el
nuevo intervalo ser [2.5, 2.625].
El punto medio es m = 2.562, f(2.562) = -1.239, f(a)f(m) > O, luego
el nuevo intervalo ser [2.562, 2.625].
El punto medio es m = 2.594, f(2.594) = -0.449, f(a)f(m) > O, luego
el nuevo intervalo ser [2.594, 2.625].
Los valores anteriores y otros ms estn en la siguiente tabla. El
proceso se detuvo cuando el tamao del intervalo fue menor que 0.0005 .

k a b f(a) f(b) m f(m)


O 2.000 3.000 -4.000 22.000 2.500 -2.531
1 2.500 3.000 -2.531 22.000 2.750 5.202
2 2.500 2.750 -2.531 5.202 2.625 0.445
3 2.500 2.625 -2.531 0.445 2.562 -1.239
4 2.562 2.625 -1.239 0.445 2.594 -0.449
5 2.594 2.625 -0.449 0.445 2.609 -0.016
6 2.609 2.625 -0.016 0.445 2.617 0.211
7 2.609 2.617 -0.016 0.211 2.613 0.097
8 2.609 2.613 -0.016 0.097 2.611 0.040
9 2.609 2.611 -0.016 0.040 2.610 0.012
10 2.609 2.610 -0.016 0.012 2.610 -0.002
11 2.610 2.610

72
4.1. GENERALIDADES

Tambin se puede usar la funcin getcharO, de e estndar, con ar-


chivo de cabecera stdio. h Sin embargo, algunos autores no son muy
partidarios de su uso con compiladores como Turbo e. Ver [Sch92].

void pausa3(void)
{
int c;

printf(" Oprima ENTER para continuar. ");


c = getcharO;
i f ( c*c >= O ) printf (" ");
}

La ltima lnea de la funcin es realmente tonta, ya que la condicin


siempre es cierta. Si no existiera, el compilador hara una advertencia
( warning) indicando que a c se le asigna un valor y no se usa para
nada.
Una funcin de pausa puede ser til para hacer paradas en progra-
mas que producen bastantes resultados en pantalla, pues los resultados
desfilan rpidamente por la pantalla y el usuario no los alcanza a leer.
Tambin es til cuando se usan ambientes integrados de edicin, com-
pilacin y ejecucin. En estos casos, la mayor parte del tiempo el editor
est activo; mediante un botn se activa la ejecucin y, acabada la eje-
cucin del programa, aparece de nuevo el editor y el usuario no alcanza
a ver los resultados del programa.
En e, como en casi todos o tal vez todos los lenguajes de programa-
cin, una funcin puede llamar a otra y a su vez sta a otra, etc.
El siguiente programa permite hallar una raz de la ecuacin f(x) =
O, mediante el mtodo de la biseccin o de dicotoma. El mtodo es muy
sencillo y seguro. Si se conocen a y b, a < b, tales que f es continua
en [a, b] y f(a)f(b) < O (f cambia de signo por lo menos una vez en
[a, b]), entonces f tiene por lo menos una raz en [a, b]. Partiendo de
este intervalo se calcula m, el punto medio, y se tienen tres posibilidades
excluyentes:
f(m) = O, en este caso m es una raz;
f(a)f(m) < O, en este caso hay una raz en el intervalo [a, m];
f(a)f(m) > O, en este caso hay una raz en el intervalo [m, b].

71
4.1. GENERALIDADES

Entonces x = 2.610 es una raz (aproximadamente).

jj Calcula una raiz de la funcion definida en f


jj por el metodo de biseccion
jj---------------------------------------------------------
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
jj---------------------------------------------------------
double f( double x);
double bisecO(double a, double b, double eps);
jj=========================================================
int maine)
{
double a, b, raiz;

printf("\n Calcula una solucion de f(x) = O\n");


printf("Se empieza con a, b tales que f(a)f(b) < O\n");
do{
printf(" Entre los valores a b : lO);
scanf( "%lf%lf", &a, &b);
} while ( a >= b II f(a)*f(b) >= 0.0 );
printf("\n raiz = %lf\n", bisecO(a, b, 0.000001) );
return O;
}
jj=========================================================
double f( double x )
{

return x*x*x*x*x - 3.0*x*x*x*x + 10.0*x - 8.0;


}
jj---------------------------------------------------------
double bisecO(double a, double b, double eps)
{
double fa, fb, m, fm;

fa f(a);
fb f(b);

73
4. FUNCIONES

while( b-a > eps){


m = (a+b)/2.0;
fm = Cm);
if( fm == 0.0 ) return m;
if( fa*fm < 0.0 ){
II nuevo intervalo [a,m]
b = m;
fb = fm;
}
else{
II nuevo intervalo [m,b]
a = m;
fa = fm;
}
}
if( fabs(fa) <= fabs(fb) ) return a;
else return b;
}

Con respecto al programa anterior y a las funciones, es conveniente hacer


varios comentarios. El programa halla una raz de la funcin definida en
f. Si se desea otra funcin, es necesario modificar el programa fuente y
compilar de nuevo.
La funcin bisecO no controla si los parmetros estn bien o mal.
Tal como aparece, la funcin supone que los parmetros estn bien. Pero
es mejor que la funcin bisecO controle que los parmetros estn bien:
a < b,
f(a)f(b) < 0,

eps> pero no muy grande.
Adems, desde el sitio donde se hace el llamado a bisecO, se debe saber
si hubo errores y de qu clase. Ms adelante se ver, utilizando parme-
tros por referencia, que una funcin puede devolver varios valores y as
sobrepasar estos inconvenientes.
Ni en el programa principal ni en la funcin bisecO se consider el
caso en que f(a)f(b) = 0, caso en que no es necesario continuar la
bsqueda de una raz puesto que a o b son races.

74
4.2. FUNCIONES RECURRENTES

El programa principal llama de manera adecuada la funcin bisecO


pero se podran presentar casos problemticos, por ejemplo, si en la
evaluacin de f fuera necesario calcular et para algn valor muy grande
de t, se producira overflow.
El mtodo de la biseccin es seguro para funciones continuas. El pro-
gramador o el usuario deben verificar que la funcin definida en f sea
realmente continua. El programa mismo no puede controlar la continui-
dad.

4.2 Funciones recurrentes


En e una funcin puede llamarse a s misma, se dice entonces que
la funcin es recurrente, a veces se usa el anglicismo "recursiva" (pro-
veniente de recursive). Esto puede ser una solucin elegante pero debe
usarse con mucho cuidado. Un programa que usa funciones recurrentes
puede ser ineficiente (ms lento). Adems la recurrencia crea una pila
(stack), que puede ser muy grande si la recurrencia es muy profunda.
Para enteros no negativos, el factorial puede definirse de manera
recurrente:
nl-
1 si n = 0,1
. - { n(n - 1)! si n 2: 2.
A continuacin aparece una versin recurrente para el clculo de n!.

double factRec( int n)


{
II devuelve O si n es negativo,
II en los demas casos devuelve n!
II Version recurrente.

double i;

if( n < O ){
printf(1I n = %d inadecuado.\n", n);
return 0.0;
}
if( n < 2 ) return 1.0;
else return( n*factRec(n-l) );
}

75
4. FUNCIONES

4.3 Parmetros por valor y por referencia

Considere el siguiente programa y los resultados producidos por l.


Aunque aparentemente la funcin intercO intercambia dos valores, fi-
nalmente no lo hace. Aunque parezca una contradiccin, lo hace pero no
lo hace.

II Funcion que intercambia dos valores pero


II no lo hace definitivamente.

#include <math.h>
#include <stdio.h>
#include <stdlib.h>

void intercO( int i, int j);


11=========================================================
int maine)
{
int m, n;

m = 2;
n = 5;
printf(1I MAIN1: m %d n %d\n", m, n);
intercO(m, n);
printf(" MAIN2: m %d n %d\n", m, n);
return O;
}
11=========================================================
void intercO( int i, int j)
{
int t;

printf(" FUNC1: i %d , j %d \n ", i, j);


t i;
i j;
j t;
printf(1I FUNC2: i %d , j %d \n ", i, j);
}

76
4.3. PARMETROS POR VALOR Y POR REFERENCIA

Los resultados son:

MAIN1 : m 2 n 5
FUNC1 : i 2 j 5
FUNC2: i 5 j 2
MAIN2: m 2 n 5

Las tres primeras lneas concuerdan con lo esperado. Lo nico raro es


la cuarta lnea: los valores de m y de n, despus del llamado de la fun-
cin, no han sido intercambiados. Sin embargo, en la tercera lnea de los
resultados, se ve que en la funcin hubo intercambio. Entonces, dnde
est el error?
La razn es sencilla. En C y C++, por defecto, los parmetros se
pasan por valor. Esto quiere decir que, al hacer el llamado a la funcin,
se manda una copia de los valores de los parmetros. Entonces la funcin
intercO intercambia una copia de los valores de los parmetros, pero
no intercambia los originales.
Si se desea mandar el parmetro "original", esto se llama parme-
tros por referencia. En C se hace como en el siguiente ejemplo.

II Funcion que intercambia dos valores.


II Version a la manera de C.
11---------------------------------------------------------
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
11---------------------------------------------------------
void interc1( int *i, int *j);
11=========================================================
int mainO
{
int m, n;

m = 2;
n = 5;
printf(" MAIN1: m %d n %d\n", m, n);
interc1(&m, &n);
printf(" MAIN2: m %d, n %d\n", m, n);
return O;

77
4. FUNCIONES

}
11=========================================================
void intercl( int *i, int *j)
{
int t;

t = *i;
*i *j;
*j = t;
}

En C++ el paso de parmetros por referencia es mucho ms sencillo.


Por eso a continuacin hay nicamente explicaciones muy someras sobre
la forma de pasar parmetros por referencia en C:

En el llamado a la funcin, el parmetro pasado por referencia


debe ir precedido de &; ms adelante, cuando se vea el tema de
apuntadores, el lector entender que eso significa que se pasa la
direccin del parmetro.

En la definicin de la funcin, el parmetro pasado por referencia


debe estar precedido de un asterisco. Esto indica (tema posterior)
que se trata de un apuntador.

A continuacin se presenta el ejemplo anlogo, a la manera de C++.

II Funcion que intercambia dos valores.


II Version a la manera de C++.

#include <math.h>
#include <stdio.h>
#include <stdlib.h>

void interc( int &i, int &j);


11=========================================================
int maine)
{
int m, n;

78
4.3. PARMETROS POR VALOR Y POR REFERENCIA

m = 2;
n = 5;
printf (" MAIN1: m %d n %d\n", m, n);
interc(m, n);
printf(" MAIN2: m %d, n %d\n", m, n);
return O;
}
11=========================================================
void interc( int &i, int &j)
{
int t;

t i',
i j;
j t;
}

Observe lo sencillo que es pasar parmetros por referencia en C++. Bas-


ta con colocar el signo & precediendo al parmetro en la primera lnea
de definicin de la funcin. Consecuentemente debe hacerse lo mismo
donde est el prototipo de la funcin.
En la funcin del siguiente ejemplo se utiliza el mtodo de biseccin
visto anteriormente. Hay algunas diferencias con la funcin bisecO. La
funcin bisec devuelve un valor que posiblemente corresponde a la raz;
adems, en un parmetro por referencia, se tiene informacin sobre el
buen o mal desarrollo del proceso.

double bisec(double a, double b, int &indic,


double epsX, double epsF)
{
II Metodo de biseccion para f(x) = o.
II f debe ser continua en [a,b] y f(a)f(b) < O.

II Esta funcion calcula dos valores: r , indic


II Devuelve r, posiblemente una raiz.
II indic es un parametro por referencia.

II indic valdra:
II 1 si se obtuvo una raiz,

79
4. FUNCIONES

II o si f(a)f(b) > 0.0


II -1 si a >= b
II -2 si epsX <= O o epsF < 0.0

II Si indic = 1, el valor devuelto sera una raiz.


II En los demas casos el valor devuelto sera 0.0
II Sea x una raiz exacta; r es raiz (aproximada)
II si If(r)1 <= epsF o si Ir-xl <= epsX

double fa, fb, m, fm;

if( epsX <= 0.0 II epsF < 0.0 ){


indic = -2;
return 0.0;
}
fa = f(a);
fb = f(b);
if( fabs(fa) <= epsF ){
indic = 1;
return a;
}
if( fabs(fb) <= epsF ){
indic = 1;
return b;
}
if( a >= b ){
indic = -1;
return 0.0;
}
if( fa*fb > 0.0 ){
indic = O;
return 0.0;
}
while( b-a > epsX){
m = (a+b)/2.0;
fm = f(m);
if( fabs(fm) <= epsF ){
indic = 1;

80
4.4. PARMETROS POR DEFECTO

return m;
}
if( fa*fm < 0.0 ){
II nuevo intervalo [a,m]
b = m;
fb = fm;
}
else{
II nuevo intervalo [m,b]
a = m;
fa = fm;
}
}
indic = 1;
if( fabs(fa) <= fabs(fb) ) return a;
else return b;
}

El llamado a la funcin bisec puede ser de la forma siguiente:

raiz = bisec(a, b, result, 1.0e-4, 1.0e-6);


if( result == 1) printf(lI\n raiz = %15. 10lf\n" , raiz);
el se printf(lI result=%d: ERROR en llamado a bisec\n",
result) ;

4.4 Parmetros por defecto


En C++ es posible pasar parmetros por defecto. Esto quiere decir
que en el prototipo de la funcin se define para el ltimo parmetro (o los
ltimos parmetros) un valor predeterminado. El llamado de la funcin
se puede hacer con un valor especfico o utilizar el valor predeterminado.
En el siguiente ejemplo se retoma la funcin bisec y se definen los dos
ltimos parmetros por defecto.

double bisec(double a, double b, int &indic,


double epsX = 1.0E-6, double epsF = 1.0E-8);
int mainO
{

81
4. FUNCIONES

}
jj---------------------------------------------------------
int bisec(double a, double b, double &raiz, double epsX,
double epsF)
{

Si se hace el llamado bisec(a, b, ind, 1.0E-9, LOe-lO), entonces


la funcin trabajar con esos dos valores pasados explcitamente, es de-
cir, epsX = 1. OE-9, Y epsF = 1. OE-l0.
Si se hace el llamado bisec(a, b, ind, 1. OE-9) , entonces la fun-
cin tomar para el parmetro faltante, el ltimo, el valor predetermi-
nado, o sea, epsX = 1. OE-9, epsF = 1. OE-8.
Si se hace el llamado bisec(a, b, ind) , entonces la funcin to-
mar para los parmetros faltantes, los dos ltimos, los dos valores pre-
determinados, o sea, epsX = 1. OE-6, epsF = 1. OE-8.

4.5 Variables locales y variables globales


En los ejemplos de programas vistos hasta ahora, todas las varia-
bles usadas eran propias a cada funcin (recuerde que main tambin es
una funcin), es decir, son variables locales. Tambin se dice que tie-
nen mbito local. Si hay variables con el mismo nombre en diferentes
funciones, son cosas completamente distintas.
A veces es conveniente tener variables que se puedan usar en varias
funciones; en realidad se podrn usar en todas las funciones. Estas va-
riables se llaman globales, pues tienen mbito global. Esto va un poco
en contrava de la filosofa de las funciones de tipo general, que deben
usar nicamente variables locales. Sin embargo, algunas veces puede ser
til. Para esto basta con declararlas antes de todas las funciones.

double PI = 3.141592654, RADIAN = 57.29577951;


int nLlamadasF;

funcl( ... );

82
4.6. SOBRECARGA DE FUNCIONES

int main(void)
{

nLlmadasF = O;

... = sin(t/RADIAN);
}
//--------------------------------------
fune1( ... )
{

nLlamadasF++;

... = 2.0*PI;
}

En el esquema anterior, los valores de las variables PI y RADIAN pueden


ser utilizados en cualquier funcin, sin tener que redefinirlos en cada
funcin. La variable nLlamadasF permite saber, en cualquier parte, el
nmero de veces que la funcin funel ha sido llamada. En algunos mto-
dos numricos, la eficiencia se mide por el nmero de veces que se realice
una operacin (sumas o multiplicaciones) o por el nmero de veces que
se haga un llamado a una funcin.

4.6 Sobrecarga de funciones

En e, dos funciones no pueden tener el mismo nombre. En e++


est permitido; esto se llama la sobrecarga de funciones. Pero, para poder
reconocer una u otra funcin, se necesita que el nmero de parmetros
sea diferente o que los tipos de los parmetros sean diferentes. Dicho de
otra forma, en e++ no puede haber dos funciones con el mismo nombre,
con el mismo nmero de parmetros y con el mismo tipo de parmetros.
El siguiente ejemplo es completamente lcito.

double maximo( double a, double b);


double maximo( double a, double b, double e);

83
4. FUNCIONES

int maximo( int a, int b);


int maximo( int a, int b, int e);
jj================================================
int main(void)
{
double x, y, z;
int i, j;

max(x, y);
= maxCi, j);
max(x, y, z);
max Ci, j, 4);

}
jj================================================
double maximo( double a, double b)
{
if( a >= b ) return a;
el se return b;
}
jj------------------------------------------------
double maximo( double a, double b, double e)
{
if( a >= b && a >= e) return a;
if( b >= e ) return b;
el se return e;
}
jj------------------------------------------------
int maximo( int a, int b)
{
if( a >= b ) return a;
else return b;
}
jj------------------------------------------------
int maximo( int a, int b, int e)
{
if( a >= b && a >= e) return a;
if( b >= e ) return b;

84
4.7. BIBLIOTECA ESTNDAR

el se return e;
}

En cambio, el siguiente ejemplo no est permitido:

int factorial( int n);


double factorial( int n);
//================================================
int main(void)
{

}
//================================================
int factorial( int n )
{

}
//------------------------------------------------
double factorial( int n )
{

4.7 Biblioteca estndar


alloc.h Asignacin dinmica de memoria.
complex.h Nmeros complejos. C++. No es estndar.
ctype.h Manejo de caracteres.
errno.h Cdigos de error.
float.h Definicin de constantes para punto flotante.
iostream.h Flujo de entrada y salida. C++.
limits.h Lmites de enteros, depende de la implementacin.
math.h Matemticas.
stddef.h Constantes de uso comn.
stdio.h Entrada y salida (Input/Output) estndar.
stdlib.h Declaraciones varias.
string.h Manejo de cadenas de caracteres.
time.h Funciones de tiempo del sistema.

85
4. FUNCIONES

El estndar ANSI C provee varias funciones listas para usar. Tambin


hay funciones exclusivas de C++. Los principales archivos de cabecera
para funciones y valores predeterminados de ANSI C y de C++ son los
de la tabla anterior.
Dependiendo del compilador, existen muchos ms archivos de cabe-
cera para C++. En [DeD99] hay una lista bastante completa de archivos
de cabecera para C++, los cuales no se utilizan en este libro.

Ejercicios

Para cada uno de los enunciados siguientes, defina cules son los
datos necesarios. Haga un programa que lea los datos, llame la funcin
que realiza los clculos y devuelve los resultados y, finalmente,
en la funcin main, muestre los resultados. La funcin debe analizar los
parmetros, estudiar su consistencia o inconsistencia e informar sobre
ello por medio de los resultados devueltos. Tambin, cuando se justifica,
haga una funcin para la lectura de los datos. Puede ser til, cuando
el proceso es bastante complejo, hacer funciones ms simples que hacen
partes especficas del proceso y son llamadas desde otra funcin que
coordina los clculos.

4.1 La gran mayora de los ejercIcIOs de los dos captulos anteriores


pueden ser resueltos por medio de funciones.

4.2 Dado un nmero x y un entero no negativo n, calcule xn. Hgalo


mediante un foro Verifique comparando con el resultado producido
por la funcin pow.

4.3 Dado un nmero x y un entero no negativo n, calcule xn. Hgalo


mediante una funcin recurrente, xn = X x n - 1.

4.4 Dado un nmero x y un entero no negativo n, calcule x n , tratando


de efectuar pocas multiplicaciones. Por ejemplo para calcular x 8
se requiere calcular x2 = xx, x 4 = x2x2 y finalmente x 8 = x 4X4 ,
o sea, tres multiplicaciones. El clculo de x 6 se puede hacer con
tres multiplicaciones. Aparentemente, para calcular x 7 es necesario
hacer cuatro multiplicaciones. Adems de calcular x n , muestre el
nmero de multiplicaciones realizadas entre nmeros double.

86
5

Arreglos

Los arreglos (arrays) permiten almacenar vectores y matrices. Los


arreglos unidimensionales sirven para manejar vectores y los arre-
glos bidimensionales para matrices. Sin embargo, las matrices tam-
bin se pueden almacenar mediante arreglos unidimensionales y por me-
dio de apuntadores a apuntadores, temas que se vern en el captulo
siguiente.
La palabra unidimensional no indica que se trata de vectores en
espacios de dimensin 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

El siguiente ejemplo muestra la definicin de tres arreglos, uno de


80 elementos doble precisin, otro de 30 elementos enteros y uno de 20
elementos tipo carcter.

double x [80] ;
int factores[30];
char codSexo[20];

Los nombres deben cumplir con las normas para los identificadores. La
primera lnea indica que se han reservado 80 posiciones para nmeros
doble precisin. Estas posiciones son contiguas. Es importante recalcar

87
5. ARREGLOS

que en C, a diferencia de otros lenguajes, el primer elemento es x [O],


el segundo es x [1], el tercero es x [2], y as sucesivamente; el ltimo
elemento es x [79] .
En x hay espacio reservado para 80 elementos, pero esto no obliga a
trabajar con los 80; el programa puede utilizar menos de 80 elementos.
C no controla si los subndices estn fuera del rango previsto; esto es
responsabilidad del programador. Por ejemplo, si en algn momento el
programa debe utilizar x [90] , lo usa sin importar si los resultados son
catastrficos.
Cuando un parmetro de una funcin es un arreglo, se considera
implcitamente que es un parmetro por referencia. O sea, si en la funcin
se modifica algn elemento del arreglo, entonces se modific realmente
el valor original y no una copia. Pasar un arreglo como parmetro de
una funcin y llamar esta funcin es muy sencillo. Se hace como en el
esquema siguiente .
... funcione ... , double x[], ... ); II prototipo
11------------------------------------------------
int mainevoid)
{
double v[30];

funcione ... , v, ... ); II llamado a la funcion

}
11------------------------------------------------
funcione ... , double x[] , .. . )11 definicion de la funcion
{
II cuerpo de la funcion

En el esquema anterior, el llamado a la funcin se hizo desde la funcin


main. Esto no es ninguna obligacin; el llamado se puede hacer desde
cualquier funcin donde se define un arreglo o donde a su vez llega un
arreglo como parmetro.
Tambin se puede hacer el paso de un arreglo como parmetro de la
siguiente manera. Es la forma ms usual. Tiene involucrada la nocin
de apuntador que se ver en el siguiente captulo.

88
5.1. ARREGLOS UNIDIMENSIONALES

... funcion( ... , double *x, ... ); // prototipo


//------------------------------------------------
int main(void)
{
double v[30] ;

funcion( ... , v, ... ); // llamado a la funcion

}
//------------------------------------------------
funcion( ... , double *x, ... )// definicion de la funcion
{
// cuerpo de la funcion

El programa del siguiente ejemplo lee el tamao de un vector, lee los


elementos del vector, los escribe y halla el promedio. Para esto utiliza
funciones. Observe la manera como un arreglo se pasa como parmetro.

// 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 mainO
{
double v [40] ;
int n;

printf("\n Promedio de elementos de un vector.\n\n");

89
5. ARREGLOS

printf(" numero de elementos lO);


scanf ( "%d", &n);
i f ( n > 40 ){
printf("\n Numero demasiado grande\n\n");
exit (1) ;
}
lectX(v, n, 'v');
printf(" v : \n");
escrX(v, n);
printf(" promedio %lf\n", promX(v, n));
return O;
}
jj================================================
void lectX(double *x, int n, char c )
{
jj lectura de los elementos de un "vector".

int i;

for( i = O; i < n; i++){


printtC" %c (%d) = ", c, i+1);
scanf ("%lf", &x [i] );
}
}
jj------------------------------------------------
void escrX(double *x, int n )
{
jj escritura de los elementos de un "vector".
int i;
int nEltosLin 5; jj numero de elementos por linea
for( i = O; i < n; i++){
printf ("%15. 8lf", x [i] ) ;
if( (i+1)%nEltosLin == O II i n-1) printf ("\n");
}
}
jj------------------------------------------------

90
5.1. ARREGLOS UNIDIMENSIONALES

double promX( double *x, int n)


{
II promedio de los elementos del 'vector' x

int i;
double s = 0.0;
i f ( n <= O ){
printf (" promX: n %d inadecuado\n", n);
return 0.0;
}
for( i = O; i < n; i++) s += xCi] ;
return sin;
}

La funcin lectX tiene tres parmetros: el arreglo, el nmero de elemen-


tos y una letra. Esta letra sirve para el pequeo aviso que sale antes de
la lectura de cada elemento. En el ejemplo, cuando se "llama" la fun-
cin, el tercer parmetro es 'v'; entonces en la ejecucin aparecern los
avisos:

v(1)
v(2)

Observe que en el printf de la funcin lectX aparece i +1; entonces


para el usuario el "vector" empieza en 1 y acaba en n. Internamente
empieza en O y acaba en n-lo
Es importante anotar que si durante la entrada de datos hay errores,
es necesario volver a empezar para corregir. Suponga que n = 50, que el
usuario ha entrado correctamente 40 datos, que en el dato cuadragsimo
primero el usuario digit mal algo y despus oprimi la tecla Enter. Ya
no puede corregir. Slo le queda acabar de entrar datos o abortar el
programa (parada forzada del programa desde el sistema operativo) y
volver a empezar. Esto sugiere que es ms seguro hacer que el programa
lea los datos en un archivo. La entrada y salida con archivos se ver en
un captulo posterior.
Cuando un arreglo unidimensional es parmetro de una funcin, no
importa que el arreglo haya sido declarado de 1000 elementos y se trabaje

91
5. ARREGLOS

con 20 o que haya sido declarado de 10 y se trabaje con 10. La funcin


es de uso general siempre y cuando se controle que no va a ser llamada
para usarla con subndices mayores que los previstos. En la siguiente
seccin se trata el tema de los arreglos bidimensionales. All, el paso de
parmetros no permite que la funcin sea completamente general.
En el siguiente ejemplo, dado un entero n ~ 2 (pero no demasiado
grande), el programa imprime los factores primos. El algoritmo es muy
sencillo. Se busca d > 1, el divisor ms pequeo de n. Este divisor es
necesariamente un primo. Se divide n por d y se contina el proceso con
el ltimo cociente. El proceso termina cuando el cociente es 1. Si n = 45,
el primer divisor es 3. El cociente es 15. El primer divisor de 15 es 3. El
cociente es 5. El primer divisor de 5 es 5 y el cociente es 1.

II Arreglos unidimensionales
II Factores primos de un entero >= 2
11------------------------------------------------
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
11------------------------------------------------
int primerDiv( int n);
int factoresPrimos( int n, int *fp, int &nf, int nfMax);
11================================================
int maine)
{
int vFactPrim[40]; II vector con los factores primos
int n;
int nFact; II numero de factore primos
int i;

printf("\n Factores primos de un entero >= 2.\n\n");

printf(" n = ");
scanf ( "%d", &n);
if( factoresPrimos(n, vFactPrim, nFact, 40) ){
for(i = O; i < nFact; i++) printf(" %d",
vFactPrim [i] ) ;
printf("\n");
}

92
5.1. ARREGLOS UNIDIMENSIONALES

el se printf(II ERROR\n");
return O;
}
11================================================
int primerDiv( int n)
{
II n debe ser mayor o igual a 2.
II Calcula el primer divisor, mayor que 1, de n
II Si n es primo, devuelve n.
II Si hay error, devuelve O.

int i',

if( n < 2 ){
printf (" primerDi v: %d inadecuado. \n ", n);
return O;
}
for( i = 2; i*i <= n; i++) if( n%i O ) return i;
return n;
}
11================================================
int factoresPrimos( int n, int *fp, int &nf, int nfMax)
{
II factores primos de n
II devuelve O si hay error.
II devuelve 1 si todo esta bien.
II fp vector con los factores primos
II nf numero de factores primos
II nfMax : tamano del vector fp

int d, indic;

if( n < 2 ){
printf(" factoresPrimos: %d inadecuado.\n", n);
return O;
}
nf O;
do{

93
5. ARREGLOS

if( nf >= nfMax ){


printf("factoresPrimos: demasiados factores.\n");
return O;
}
d = primerDiv(n);
fp[nf] = d;
nf++;
n j= d;
} while( n > 1);
return 1;
}

5.2 Arreglos multidimensionales


La declaracin 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 x 4 = 12 elementos doble


precisin. El primer subndice vara entre O y 2, Y el segundo vara entre
O y 3. Usualmente, de manera anloga 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 estn contiguos en el orden fila por
fila, o sea, a [O] [O], a [O] [1], a [O] [2], a [O] [3], a [1] [O], a [1] [1] ,
a[l] [2], a[l] [3], a[2] [O], a[2] [1], a[2] [2], a[2] [3].
En el siguiente ejemplo, el programa sirve para leer matrices, escri-
birlas y calcular el producto. Lo hace mediante la utilizacin de funciones
que tienen como parmetros arreglos bidimensionales.

j j prog14
j j Arreglos bidimensionales

94
5.2. ARREGLOS MULTIDIMENSIONALES

jj Lectura y escritura de 2 matrices y calculo del producto


jj------------------------------------------------
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
jj------------------------------------------------
void lectAO(double a[J [40J, int m, int n, char c );
void escrAO(double a[J [40J, int m, int n );
int prodABO(double a[J [40J, int m, int n, double b[J [40J,
int p, int q, double c[J [40J);
jj================================================
int maine)
{
double a[50J [40J, b[20J [40J, c[60J [40J;
int m, n, p, q;

printf("\n Producto de dos matrices.\n\n");

printf(" numo de filas de A ");


scanf ( "%d", &m);
printf(" numo de columnas de A 11);
scanf ( "%d", &n);
jj es necesario controlar que m, n no son muy grandes
jj ni negativos

printf(" numo de filas de B ");


scanf ( "%d", &p);
printf(" numo de columnas de B 11);
scanf ( "%d", &q);
jj es necesario controlar que p, q no son muy grandes
jj ni negativos
if( n != p ){
printf(II Producto imposible\n");
exit(1) ;
}
lectAO(a, m, n, 'A');
printf(" A : \n");

95
5. ARREGLOS

escrAO(a, m, n);

lectAO(b, n, q, 'B');
printf(" B : \n");
escrAO(b, n, q);

if( prodABO(a,m,n, b,p,q, c) ){


printf(1I e : \n");
escrAO(c, m, q);
}
else printf("\ ERROR\n");
return O;
}
11================================================
void lectAO(double a[] [40], int m, int n, char c )
{
II lectura de los elementos de una matriz.

int i, j;

for( i = O; i < m; i++){


for( j=O; j < n; j++){
printf (" %c [%d] [%d] 11
c, i+l, j+l);
scanf("%lf", &a[i] [j] );
}
}
}
11------------------------------------------------
void escrAO(double a[] [40], int m, int n )
{
II escritura de los elementos de una matriz

int i, j;
int nEltosLin 5; II numero de elementos por linea

for( i = O; i < m; i++){


for( j = O; j < n; j++){
printfClI%15.8lfll, a[i] [j]);

96
5.2. ARREGLOS MULTIDIMENSIONALES

ifj+l)%nEltosLin o 11 j==n-l)printf("\n");
}
}
}
jj------------------------------------------------
int prodABO(double a[] [40], int m, int n, double be] [40],
int p, int q, double c[] [40])
{
jj producto de dos matrices, a mxn, b pxq
jj devuelve 1 si se puede hacer el producto
jj devuelve O si no se puede

int i, j, k;
double s;

if(m<Olln<Ollp<Ollq<O 11 n!= p ) return O;


for( i=O; i < m; i++){
for( j=O; j < q; j++){
s = 0.0;
for( k=O; k<n; k++) s += a[i] [k]*b[k] [j];
c[i] [j] = s;
}
}
return 1;
}

Cuando en una funcin un parmetro es un arreglo bidimensional, la


funcin debe saber, en su definicin, el nmero de columnas del arreglo
bidimensional. Por eso en la definicin de las funciones est a [] [40] .
Esto hace que las funciones del ejemplo sirvan 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 ver en


el siguiente captulo.
Almacenando las matrices en arreglos unidimensionales con la con-
vencin de que los primeros elementos del arreglo corresponden a
la primera fila de la matriz, los que siguen corresponden a la segun-
da fila, y as sucesivamente. Esta modalidad es muy usada, tiene

97
5. ARREGLOS

algunas ventajas muy importantes. Se ver con ms detalle ms


adelante.

En resumen, los arreglos bidimensionales no son muy adecuados para


pasarlos como parmetros a funciones. Su uso debera restringirse a casos
en que el arreglo bidimensional se usa nicamente en la funcin donde
se define.
En el ejemplo anterior, en la funcin lectAO, antes de la lectura del
elemento a[i] [j], el programa escribe los valores i+l y j+l, entonces
para el usuario el primer subndice empieza en 1 y acaba en m; el segundo
empieza en 1 y acaba en n.

5.3 Cadenas
Los arreglos unidimensionales de caracteres, adems de su manejo
estndar como arreglo, pueden ser utilizados como cadenas de caracteres,
siempre y cuando uno de los elementos del arreglo indique el fin de la
cadena. Esto se hace mediante el carcter especial

'\0'

En el ejemplo

II Arreglo de caracteres como tal.


#include <math.h>
#include <stdio.h>
#include <stdlib.h>
int maine)
{
char aviso[30];
int i;

aviso [O] 'e' ;


aviso [1] 'o' ;
aviso [2] 'm' ;
aviso [3] 'o' ;
aviso [4] , , ,.
aviso [5] 'e' ;
aviso [6] 's' ;

98
5.3. CADENAS

aviso [7] 't' ;


aviso [8] 'a' ;
aviso [9] '?' ;
for (i=0; i <= 9; i++) printf ("%c", aviso [iJ) ;
return O;
}

el arreglo aviso se consider 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.

II prog15b
II Cadena de caracteres
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
int maine)
{
char aviso [30] ;

aviso [O] '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 O;
}

99
5. ARREGLOS

Si se modifica ligeramente de la siguiente manera:

char aviso[30];

aviso [O] 'C' ;


aviso [1J 'o' ;
aviso [2J 'm' ;
aviso [3J 'o' ;
aviso [4] '\0' ;
aviso [5J 'e' j
aviso [6J 's' j
aviso [7J 't' ;
aviso [8J 'a' ;
aviso [9J '?' ,.
aviso [10J =' \0' ;
printf("%s", aviso);

entonces nicamente escribe Como, ya que encuentra el fin de cadena (el


primero) despus de la segunda letra o.
La lectura de cadenas de hace mediante la funcin gets ( ). Su
archivo de cabecera es stdio. h. Su nico parmetro es precisamente la
cadena que se desea leer.

char nombre[81J;

printf(" Por favor, escriba su nombre: lO);


gets(nombre);
printf("\n Buenos dias %s\n", nombre);

En C++ se puede utilizar cin para leer cadenas que no contengan es-
pacios. Cuando hay un espacio, es reemplazado por fin de cadena.

char nombre[81J;

cout" Por favor, escriba su nombre: lO;


cinnombre;
coutendl" Buenos dias "nombreendl;

Si el usuario escribe Juani to, el programa (la parte de programa) ante-


rior escribir Buenos dias Juani too Pero si el usuario escribe el nombre
de dos palabras Juan Manuel, el programa escribir Buenos dias Juan.

100
5.3. CADENAS

En C++ es posible leer cadenas de caracteres con espacios mediante


cin. getline O. Este tema no se trata en este libro.
Para tener acceso a las funciones para el manejo de cadenas, se ne-
cesita el archivo de cabecera string. h. Las funciones ms usuales son:

strcpyC , )
strcat C , )
strlenC )

El primer parmetro de strcpy (string copy) debe ser un arreglo de


caracteres. El segundo parmetro debe ser una cadena constante o una
cadena en un arreglo de caracteres. La funcin copia en el arreglo (primer
parmetro) la cadena (el segundo parmetro). Se presentan problemas si
el segundo parmetro no cabe en el primero. En un manual de referencia
de C puede encontrarse informacin ms detallada sobre estas y otras
funciones relacionadas con las cadenas.
La funcin strlen (string length) da como resultado la longitud de
la cadena sin incluir el fin de cadena.
U na cadena constante es una sucesin de caracteres delimitada por
dos comillas dobles; por ejemplo: "Hola". No necesita explcitamente el
signo de fin de cadena, ya que C lo coloca implcitamente. La cadena
constante ms sencilla es la cadena vaca: "". La cadena constante de
un solo carcter es diferente del carcter. Por ejemplo, "x" es diferente
de 'x'.

El programa prog15b se puede escribir ms rpidamente as:

#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int mainO
{
char aviso [30] ;

strcpy(aviso, "Como esta?");


printf("%s", aviso);
printf("\n longitud = %d\n", strlen(aviso));

101
5. ARREGLOS

return O;
}

Como era de esperarse, el programa anterior escribe Como esta? y


en la lnea siguiente longitud = 10. Efectivamente las diez primeras
posiciones del arreglo aviso, de la O a la 9, estn ocupadas. La posicin
10 est ocupada con el fin de cadena. El arreglo aviso puede contener
cadenas de longitud menor o igual a 29, pues se necesita un elemento
para el signo de fin de cadena.
La funcin strcat sirve para concatenar dos cadenas. El primer
parmetro de strcat debe ser una cadena en un arreglo de caracteres.
El segundo parmetro debe ser una cadena constante o una cadena en un
arreglo de caracteres. La funcin pega la segunda cadena a la derecha de
la primera cadena. Aparecen problemas si en el primer arreglo no cabe
la concatenacin de la primera y la segunda cadenas. La concatenacin
se hace de manera limpia: la funcin quita el fin de cadena en el primer
arreglo y pega la segunda incluyendo su fin de cadena.

II funcion strcat

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int mainO
{
char nombre [41] , apell[41] , Nombre[81];

printf(II Por favor, escriba su nombre ");


gets(nombre);
printf(" Por favor, escriba su apellido ");
gets(apell);
strcpy(Nombre, nombre);
strcat (Nombre , 11 " ) ;
strcat (Nombre , apell);
printf("Buenos dias %s\n", Nombre);
return O;
}

102
5.4. INICIALIZACIN DE ARREGLOS

5.4 Inicializacin de arreglos


Los arreglos pequeos se pueden inicializar de la siguiente manera:

double x[4] = { 1.1, 1.2, 1.3, 1.4};

Esto es lo mismo que escribir:

double x[4];

x [O] 1.1 ;
x[1] 1.2;
x [2] 1.3;
x[3] 1.4;

Si dentro de los corchetes hay menos valores que el tamao del arreglo,
generalmente e asigna O. O a los faltantes. El ejemplo

double x[4] = { 1.1, 1.2};

produce el mismo resultado que

double x[4];

x[O] 1.1 ;
x [1] 1.2;
x[2] 0.0;
x [3] 0.0;

Si no se precisa el tamao del arreglo en una inicializacin, e le asigna


el tamao dado por el nmero de elementos. El ejemplo

double x[] = { 1.1, 1.2, 1.3};

es equivalente a

double x[3];

x[O] 1.1;
x[l] 1.2;
x [2] 1. 3;

103
5. ARREGLOS

En este otro ejemplo, con una cadena en un arreglo de caracteres,

char saludo[]= IIBuenos dias ll ;

resulta lo mismo que escribir

char saludo[12]= {'B', 'u', 'e', 'n', 'o', 's',


'd', 'i', 'a', 's', '\O'};

o igual que escribir

char saludo[12];

saludo [O] 'B' ;


saludo [1] 'u' ;
saludo [2] 'e' ;
saludo [3] 'n' ;
saludo [4] 'o' ;
saludo [5] 's' ;
saludo [6] , , ,.
saludo [7] 'd' ;
saludo [8] 'i' ;
saludo [9] 'a' ;
saludo [10] 's' ;
saludo [11] '\0' ;

Para arreglos bidimensionales, basta con recordar que primero estn los
elementos de la fila 0, enseguida los de la fila 1, y as sucesivamente. La
inicializacin

double a[2] [3] = { 1.1, 1.2, 1.3, 1.4, 1.5, 1.6};

produce el mismo resultado que

double a[2] [3];

a [O] [O] = 1. 1;
a[O] [1] = 1.2;
a [O] [2J = 1. 3;
a[l] [O] = 1.4;
a[1] [1] = 1.5;
a [1J [2J = 1. 6 ;

104
5.4. INICIALIZACIN DE ARREGLOS

La siguiente inicializacin tambin hubiera producido el mismo resultado


anterior:

double a[] [3] = { 1.1, 1.2, 1.3, 1.4, 1.5, 1.6};

En el ejemplo anterior, e sabe que las filas tienen tres elementos, en-
tonces en el arreglo a debe haber dos filas. En el ejemplo que sigue, e
asigna ceros a lo que queda faltando hasta obtener filas completas.

double a[] [3] = { 1.1, 1.2, 1.3, 1.4};

Lo anterior es equivalente a

double a [2] [3] ;

a [O] [O] 1.1 ;


a [O] [1] 1.2;
a[O] [2] 1.3;
a [1] [O] 1.4;
a [1] [1] 0.0;
a[1] [2] 0.0;

En las siguientes inicializaciones hay errores. Para los arreglos bidimen-


sionales, e necesita conocer el tamao de las filas (el nmero de colum-
nas).

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
Para cada uno de los enunciados siguientes, defina cules son los
datos necesarios. Elabore un programa que lea los datos, llame la funcin
(o las funciones) que realiza los clculos y devuelve los resultados, y
finalmente, haga que el programa principal (la funcin main) muestre
los resultados.

5.1 Intercambie los elementos de un vector: el primero pasa a la ltima


posicin y el ltimo a la primera posicin, el segundo pasa a la
penltima posicin y viceversa ...

105
5. ARREGLOS

5.2 Obtenga la expresin binaria de un entero no negativo.

5.3 Obtenga la expresin en base p (p entero, 2 ::; p ::; 9), de un entero


no negativo.

5.4 Obtenga la expresin hexadecimal de un entero no negativo.

5.5 Averige si una lista de nmeros est ordenada de menor a mayor.

5.6 Averige si una lista de nmeros est ordenada de manera estric-


tamente creciente.

5. 7 Averige si una lista tiene nmeros repetidos.

5.8 Ordenar, de menor a mayor, los elementos de una lista.

5.9 Averige si una lista ordenada de menor a mayor tiene nmeros


repetidos.

5.10 Dada una lista de n nmeros, averige si el nmero t est en la


lista.

5.11 Dada una lista de n nmeros, ordenada de menor a mayor, averige


si el nmero t est en la lista.

5.12 Halle el promedio de los elementos de un vector.

5.13 Halle la desviacin estndar de los elementos de un vector.

5.14 Dado un vector con componentes (coordenadas) no negativas, halle


el promedio geomtrico.

5.15 Halle la moda de los elementos de un vector.

5.16 Halle la mediana de los elementos de un vector.

5.17 Dados un vector x de n componentes y una lista, VI, V2, ... , V m es-
trictamente creciente, averige cuantos elementos de x hay en cada
uno de los m + 1 intervalos (00, VI], (VI, V2], (V2, V3], ... , (Vm-I, V m ],
(V m , 00).
5.18 Dado un vector de enteros positivos, halle el m.c.d.

5.19 Dado un vector de enteros positivos, halle el m.c.m. (mnimo comn


mltiplo).

106
5.4. INICIALIZACIN DE ARREGLOS

5.20 Dado un polinomio definido por el grado n y los n + 1 coeficientes,


calcule el verdadero grado. Por ejemplo, si n = 4 Y p( x) = 5 + Ox +
6x 2 + Ox 3 + Ox 4 , su verdadero grado es 2.

5.21 Dado un polinomio halle su derivada.

5.22 Dado un polinomio p y un punto (a, b) halle su antiderivada q tal


que q(a) = b.
5.23 Dados dos polinomios (pueden ser de grado diferente), halle su
suma.
5.24 Dados dos polinomios, halle su producto.

5.25 Dados dos polinomios, halle el cociente y el residuo de la divisin.

5.26 Dados n puntos en ]R2, PI, P2, ... , P n . Verifique que la lnea poli-
gonal cerrada P1 P2... Pn P1 sea de Jordan (no tiene "cruces").
5.27 Dados n puntos en ]R2, PI, P2, ... , P n , tal que la lnea poligonal
cerrada P 1 P2 ... Pn P 1 es de Jordan, averige si el polgono determi-
nado es convexo.
5.28 Dados n puntos en ]R2, PI, P2, ... , Pn , tal que la lnea poligonal
cerrada PtP2 ... Pn P1 es de Jordan, halle el rea del polgono deter-
minado.
5.29 Sea x un vector en ]Rn y A una matriz de tamao m x n definida
por una lista de p triplas de la forma (ik,jk, Vk) para indicar que
aik1k = Vk Y que las dems componentes de A son nulas; calcule
Ax.
5.30 Considere un conjunto A de n elementos enteros almacenados en
un arreglo a. Considere un lista de m parejas en A x A. Esta lista
define una relacin sobre A. Averige si la lista est realmente
bien definida, si la relacin es simtrica, antisimtrica, reflexiva,
transitiva y de equivalencia.
5.31 Considere un conjunto A de n elementos y una matriz M de ta-
mao n x n que representa una operacin binaria sobre A. Averige
si la operacin binaria est bien definida, si es conmutativa, si es
asociativa, si existe elemento identidad, si existe inverso para cada
elemento de A.

107
5.4. INICIALIZACIN DE ARREGLOS

5.20 Dado un polinomio definido por el grado n y los n + 1 coeficientes,


calcule el verdadero grado. Por ejemplo, si n = 4 Y p( x) = 5 + Ox +
6x 2 + Ox 3 + Ox 4 , su verdadero grado es 2.

5.21 Dado un polinomio halle su derivada.

5.22 Dado un polinomio p y un punto (a, b) halle su antiderivada q tal


que q(a) = b.
5.23 Dados dos polinomios (pueden ser de grado diferente), halle su
suma.
5.24 Dados dos polinomios, halle su producto.

5.25 Dados dos polinomios, halle el cociente y el residuo de la divisin.

5.26 Dados n puntos en ]R2, PI, P2, ... , P n . Verifique que la lnea poli-
gonal cerrada P1 P2... Pn P1 sea de Jordan (no tiene "cruces").
5.27 Dados n puntos en ]R2, PI, P2, ... , P n , tal que la lnea poligonal
cerrada P 1 P2 ... Pn P 1 es de Jordan, averige si el polgono determi-
nado es convexo.
5.28 Dados n puntos en ]R2, PI, P2, ... , Pn , tal que la lnea poligonal
cerrada PtP2 ... Pn P1 es de Jordan, halle el rea del polgono deter-
minado.
5.29 Sea x un vector en ]Rn y A una matriz de tamao m x n definida
por una lista de p triplas de la forma (ik,jk, Vk) para indicar que
aik1k = Vk Y que las dems componentes de A son nulas; calcule
Ax.
5.30 Considere un conjunto A de n elementos enteros almacenados en
un arreglo a. Considere un lista de m parejas en A x A. Esta lista
define una relacin sobre A. Averige si la lista est realmente
bien definida, si la relacin es simtrica, antisimtrica, reflexiva,
transitiva y de equivalencia.
5.31 Considere un conjunto A de n elementos y una matriz M de ta-
mao n x n que representa una operacin binaria sobre A. Averige
si la operacin binaria est bien definida, si es conmutativa, si es
asociativa, si existe elemento identidad, si existe inverso para cada
elemento de A.

107
6

Apuntadores

Los apuntadores, llamados tambin punteros, son variables que


guardan direcciones de memoria de variables doble precisin o de va-
riables enteras o de variables de otro tipo. En el siguiente ejemplo, p
y q estn declaradas como apuntadores, p est disponible para guardar
una direccin de una variable doble precisin. Usualmente se dice que
p apunta a una variable doble precisin. 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 real-


mente asignarles una direccin, se debe escribir algo de la forma:

P &x;
q &i;

Escribir p = &i es un error. El operador & es un operador unario (llama-


do algunas veces monario) que devuelve la direccin de memoria de una
variable. El otro operador para apuntadores es *, que devuelve el valor
contenido en una direccin. Estos dos operadores son inversos entre s.
Por un lado, * (&x) es exactamente lo mismo que x. Anlogamente,
&( *p) es exactamente igual a p.

Considere el siguiente ejemplo:

double *p, x = 0.5, y, *r;

109
6. APUNTADORES

int *q, i 4, j, *s;

P &x;
q &i;

y *p;
j *q;
r = p+1;
s q+3;
printf(" %p %d %lf\n", p, int(p), y);
printf(II %p %d %d\n" , q, int(q), j);
printf(" %p %d\n", r, int(r;
printf (" %p %d\n", s, int(s;

Estos son los resultados:

0064FDFC 6618620 0.500000


0064FDFO 6618608 4
0064FE04 6618628
0064FDFC 6618620

Los dos primeros resultados de la primera lnea corresponden al valor de


p, en formato %p (para apuntadores) y convertido a entero en formato
entero. El primer valor est en hexadecimal, es decir, en base 16. Recuer-
de que se usan los dgitos 0,1, ... ,9 Y las letras A, B, C, D, E Y F, cuyos
valores son A = 10, B = 11, C = 12, D = 13, E = 14, F = 15. Entonces
0064FDFC = 6 x 165 +4 X 164 + 15 X 163 + 13 X 162 + 15 x 16+ 12 = 6618620.
Este es el segundo valor de la primera lnea. Estos dos valores son simple-
mente la direccin de la variable doble precisin x. Esto quiere decir que
en los 8 bytes que empiezan en la direccin de memoria 0064FDFC est el
valor de x. O sea, en los bytes con direccin 0064FDFC, 0064FDFD,
0064FDFE, 0064FDFF, 0064FEOO, 0064FEOl, 0064FE02, 0064FE03,
est el valor de x.
La orden y = *p asigna a y el valor contenido en la direccin
apuntada por p. Como justamente p es la direccin de x, entonces a y se
le asigna el valor de x, es decir, 0.5 que es precisamente el ltimo valor
de la primera lnea.
En realidad, los dos primeros valores son vlidos durante cada corrida
del programa, pero pueden cambiar de corrida a corrida. Muy probable-

110
6.1. APUNTADORES Y ARREGLOS UNIDIMENSIONALES

mente cambien al compilar y correr el programa en otro computador o


con otro compilador. Obviamente el tercer valor siempre ser el mismo,
no importa el compilador ni el computador.
De manera anloga, en la segunda lnea est el valor de q, en formato
hexadecimal, y como entero. A la variable j se le asign el valor apuntado
por q, o sea, el valor de i, es decir, 4.
Los valores de la tercera lnea son en apariencia sorprendentes. Sim-
plemente estn los valores del apuntador r. Pero se esperara que apare-
ciera 0064FDFD 6618621 ya que r fue definido como p+1. Lo que pasa es
que se usa la aritmtica de apuntadores. El apuntador p tiene una
direccin de memoria de una variable doble precisin; r es un apuntador
doble precisin y al hacer la asignacin r = p+1, la aritmtica de apun-
tadores le asigna lo que sera la direccin de la siguiente variable doble
precisin. Como una variable doble precisin utiliza 8 bytes, entonces
los valores se incrementaron en 8 unidades. Ahora s los valores de la
tercera lnea son comprensibles.
En la cuarta lnea aparece lo que sera la direccin de la tercera varia-
ble entera, enseguida de i (q es la direccin de i). En este compilador los
enteros utilizan 4 bytes; entonces, el valor del apuntador s corresponde
al valor de q ms 12 unidades.
Las nicas operaciones permitidas a los apuntadores son:
sumar un entero; por ejemplo, p += 9;
restar un entero; por ejemplo, p -= 2;
operador de incremento; por ejemplo, q++;
operador de decremento; por ejemplo, p--;
En ellas se utiliza la aritmtica de operadores.

6.1 Apuntadores y arreglos unidimensionales

Considere el siguiente ejemplo:

double x[156] = {1.1, 1.2, 1.3, 1.4};


double *p;

cout" x = "X", dir. de x[O] "&X[O] endl;


p = x;

111
6. APUNTADORES

coutn p npendl;

El resultado es el siguiente:

x = Ox0064f924 , dir. de x[O] Ox0064f924


p = Ox0064f924

La variable x es un arreglo unidimensional de 156 elementos doble preci-


sin, pero para ciertas cosas se considera como una direccin de memoria.
Al escribir x, el resultado es una direccin de memoria. Observe tam-
bin que es exactamente la direccin del primer elemento del arreglo, o
sea, de x [O]. Usando cout la direccin aparece con minsculas y hay 10
caracteres. En los ejemplos anteriores, con printf hay maysculas y 8
caracteres. Siendo p un apuntador, la asignacin p = x es correcta. En la
segunda lnea de resultados, aparece efectivamente la misma direccin.
En el siguiente ejemplo, a es un arreglo bidimensional; hay varias
coincidencias con el ejemplo anterior, pero la asignacin p = a es in-
correcta.

double a [10] [20] {1.1, 1.2, 1.3, 1.4};


double *p;

coutn a = nan dir. de a[O] [O] = n&a[O] [O] endl;


II p = a;
II La instruccion anterior (en comentario) es incorrecta.
p = &a[O] [O] ;
coutn p = npendl;

El resultado es:

a = Ox0064f7c4 dir. de a[O] [O] Ox0064f7c4


p = Ox0064f7c4

En e los apuntadores y los arreglos estn ntimamente ligados. En el


siguiente ejemplo se ve que x [i] y * (p+i) son exactamente lo mismo.

double x[40] {1.1, 1.2, 1.3}, *p, *q;


int i;

p x;

112
6.1. APUNTADORES Y ARREGLOS UNIDIMENSIONALES

q = X;
for( i=O; i <= 5; i++){
printf(I%6.2lf%6.2lf%6.2lf\n", x[iJ, *(p+i), *q);
q++;
}

El resultado es el siguiente:

1.10 1.10 1.10


1.20 1.20 1.20
1.30 1.30 1.30
0.00 0.00 0.00
0.00 0.00 0.00
0.00 0.00 0.00

Es ms fcil ver la equivalencia entre x [iJ y * (p+i) si esta ltima


expresin se escribe * (&x [OJ +i), o sea, el contenido de la direccin de
x [OJ incrementada en i.
En el ejemplo anterior, el uso del apuntador q sugiere el uso de apun-
tadores para el manejo de los arreglos. A continuacin hay varias formas
de una funcin que calcula el promedio de los primeros n elementos de
un arreglo.

double promX1( double *x, int n)


{
II promedio de los elementos del 'vector' x

int i;
double s = 0.0;

II error si n <= O

for( i O; i < n; i++) s += x[iJ;


return sin;
}
11------------------------------------------------
double promX2( double *x, int n)
{
II promedio de los elementos del 'vector' x

113
6. APUNTADORES

double *p, *pFin;


double S = 0.0;

II error si n <= O

pFin = x+n;
for( p = x ; p < pFin; p++) s += *p;
return sin;
}
11------------------------------------------------
double promX3( double *x, int n)
{
II promedio de los elementos del 'vector' x

double *p, *pFin;


double s = 0.0;

II error si n <= O

p = x;
pFin = x+n;
while( p < pFin){
s += *p;
p++;
}
return sin;
}
11------------------------------------------------
double promX4( double *x, int n)
{
II promedio de los elementos del 'vector' x

double *p, *pFin;


double s = 0.0;

II error si n <= O

114
6.1. APUNTADORES Y ARREGLOS UNIDIMENSIONALES

p = X;
pFin = x+n;
while( p < pFin) S += *p++;
return s/n;
}

En ciertos casos el manejo de un arreglo con apuntadores es ms eficien-


te que el manejo con subndices. Sin embargo, para una persona no muy
acostumbrada a la utilizacin de los apuntadores, es ms fcil escribir
o leer un programa donde los arreglos se tratan por medio de subndi-
ces. A lo largo de este libro habr 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 comprensin y manejo. Un programador de nivel intermedio puede
fcilmente "traducir" un programa con subndices a un programa con
apuntadores.
Considere ahora la siguiente porcin de cdigo donde se utiliza cual-
quiera de las cuatro funciones que calculan el promedio.

double x[100] = { 0.1, 0.2, 0.3};

printf("%lf\n", promXl(x,4) );
printf("%lf\n", promX1C &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 funcin promXl,
el primer parmetro es la direccin de memoria del elemento x [2] y
el segundo es el valor 10; entonces, la funcin promXl, que espera un
arreglo, considera un arreglo que empieza exactamente en esa direccin
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 parmetro
un arreglo que en realidad es parte de un arreglo ms grande, es muy til
y eficiente para el manejo de vectores y matrices en mtodos numricos.

115
6. APUNTADORES

6.2 Apuntadores a apuntadores


Un apuntador a apuntador, a veces llamado apuntador doble (dife-
rente de un apuntador a doble precisin), es una variable que contiene
la direccin de memoria de un apuntador. Se declara colocando doble
asterisco delante del nombre. Considere el siguiente ejemplo:

int i, *p, **q;

i 16;
P &i;
q &p;
printf("%p %d %p %p %d\n", p, *p, q, *q, **q);
El resultado es el siguiente:
0064FEOO 16 0064FDFC 0064FEOO 16
p es un apuntador a entero; despus de la asignacin tiene la direccin
de i. q es un apuntador a apuntador a entero; dicho de otra forma, un
apuntador doble a entero. Despus de la asignacin q tiene la direccin
del apuntador p. La orden printf escribe cinco valores:
p, es decir, la direccin de i,
el contenido apuntado por p, es decir, el valor de i,
q, es decir, la direccin de p,
el contenido apuntado por q, es decir, el valor de p,
el contenido apuntado por lo apuntado por q, o sea, el valor de i.
El primero y el cuarto valor coinciden; tambin coinciden el segundo y
el quinto valor.

6.3 Apuntadores y arreglos bidimensionales

Como los arreglos bidimensionales almacenan las matrices fila por


fila, entonces se puede saber en qu posicin, a partir del elemento
a [O] [O], est el elemento a [i] [j]. Si n es el tamao de una fila, es
decir, el nmero de columnas, entonces el elemento a [i] [j] est in + j
posiciones despus de a[O] [O].

El siguiente ejemplo produce como resultado dos valores iguales:

116
6.4. MATRICES Y ARREGLOS UNIDIMENSIONALES

double *p, c[4] [3] = {. 1, .2, .3, .4, .5, .6,


.7, .8, .9, 1. O, 1. 1, 1. 2} ;
int n, i, j ;

n = 3;
i 2;
j l',
P &c [O] [O] ;

printf(lI%lf %lf\n", c[i] [j], *(p + Hn + j) );

Teniendo en cuenta los valores del ejemplo, el resultado es:

0.800000 0.800000

6.4 Matrices y arreglos unidimensionales


Anteriormente se vio que el paso de arreglos bidimensionales le qui-
taba generalidad a las funciones. Una manera de resolver este incon-
veniente es almacenando la matriz en un vector, fila por fila. Tambin
se podra hacer columna por columna; es menos usual, pero en algunos
casos especficos podra ser ms conveniente. La frmula para calcular
la posicin es la misma o anloga a la de los apuntadores y los arreglos
bidimensionales.
Si se considera una matriz, con elementos aij, donde 1 :S i :S m,
1 :S j :S n, almacenada en un arreglo unidimensional v, entonces

aij = v [(i -1) *n + j -1 ].

Si se considera una matriz, con elementos aij, donde O :S i :S m - 1,


O :S j :S n - 1, almacenada en un arreglo unidimensional v, entonces

En el siguiente ejemplo, como en el programa prog14, se hace la lectura


y escritura de dos matrices, y luego el producto. El almacenamiento de
las matrices se hace fila por fila en arreglos unidimensionales.

II Matrices en arreglos unidimensionales

117
6 APUNTADORES

II Lectura y escritura de 2 matrices y calculo del producto

#include <math.h>
#include <stdio.h>
#include <stdlib.h>

void escrX(double *x, int n );


void lectAl(double *a, int m, int n, char c );
void escrAl(double *a, int m, int n );
int prodABsubl(double *a, int m, int n, double *b, int p,
int q, double *c);
11================================================
int main()
{
double a[1000] , b[1000] , c[1000];
int m, n, p, q;

printf("\n Producto de dos matrices.\n\n");

printf(" numo de filas de A " ) ;


scanf ( "%d", &m);
printf(" numo de columnas de A");
scanf ( "%d", &n);
II es necesario controlar que m, n no son muy grandes
II ni negativos
printf(1I numo de filas de B 11);
scanf ( "%d", &p);
printf(" numo de columnas de B : 11);
scanf ( "%d", &q);
II es necesario controlar que p, q no son muy grandes
II ni negativos
if( n != p ){
printf(" Producto imposible\n");
exit(1) ;
}
lectAl(a, m, n, 'A');

118
6,4 MATRICES Y ARREGLOS UNIDIMENSIONALES

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(" e : \n");
escrA1(c, m, q);
}
else printf("\ ERROR\n");
return O;
}
11================================================
void lectA1(double *a, int m, int n, char c )
{
II lectura de los elementos de una matriz.
II almacenada en un "vector"

int i, j

for( i = O; i < m; i++){


for( j=O; j < n; j++){
printf(" %c[%d] [%d] =" c, i+1, j+1)
scanf("%lf", &a[i*n+j] )
}
}
}
11------------------------------------------------
void escrA1(double *a, int m, int n )
{
II escritura de los elementos de una matriz
II almacenada en un vector
II utiliza escrX

int i;

119
6. APUNTADORES

for(i=O;i<m;i++) escrX( &a[i*n], n);


}
11------------------------------------------------
void escrX(double *x, int n )
{
II escritura de los elementos de un "vector"

int j;
int nEltosLin 5; II numero de elementos por linea

for( j = O; j < n; j++){


printf ("%15. 8lf", x [j]) ;
if( (j+1)%nEltosLin == O 11 j n-1) printf ("\n");
}
}
11------------------------------------------------
int prodABsub1(double *a, int m, int n, double *b, int p,
int q, double *c)
{
II producto de dos matrices, a mxn, b pxq
II devuelve 1 si se puede hacer el producto
II devuelve O si no se puede
II Las matrices estan almacenadas en "vectores"
II El manejo se hace mediante subindices

int i, j, k;
double s;

if(m<Olln<Ollp<Ollq<O 11 n!= p ) return O;


for( i=O; i < m; i++){
for( j=O; j < q; j++){
s = 0.0;
for( k=O; k<n; k++) s += a[i*n+k]*b[k*q+j];
c[i*q+j] = s;
}
}
return 1;
}

120
6.4. MATRICES Y ARREGLOS UNIDIMENSIONALES

Observe que la funcin que escribe la matriz, escrAl, lo hace fila por fila.
Para esto llama varias veces la funcin 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 direccin de a [i*n] .
En el programa anterior, como en un ejemplo ya visto, durante la
lectura de la matriz, aparecen lo subndices i+l 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 continuacin hay una versin
de la funcin que calcula el producto entre matrices, almacenadas en
vectores, mediante el uso de apuntadores.

int prodABapl(double *a, int m, int n, double *b, int p,


int q, double *c)
{
II producto de dos matrices, a mxn, b pxq
II devuelve 1 si se puede hacer el producto
II devuelve O si no se puede
II Las matrices estan almacenadas en "vectores"
II el producto se hace por medio de apuntadores

double *cij, *aik, *bkj;11 apuntadores a: Cij, Aik, Bkj


double *cmq; II apuntador a la direccion de c [m*q]
double *ciq; II apunto a C(i+l,O) c [i*q]
double *aiO; II apuntador a AiO
double *ain; II apunto a A(i+l,O) a[i*n]
double *bOj; II apuntador a B(O,j)

if(m<Olln<Ollp<Ollq<O 11 n!= p ) return O;


cij c,
cmq = c+m*q;
aiO = a;
while( cij < cmq ){
ciq = cij + qj
bOj = b;
while( cij < ciq ){
aik = aiO;

121
6. APUNTADORES

ain = aiO+n;
bkj = bOj;
*cij = 0.0;
while( aik < ain ){
*cij += (*aik++)*(*bkj);
bkj += q;
}
cij++;
bOj++;
}
aiO ain;
}
return 1;
}

La elaboracin de la funcin prodABsub1 es ms fcil que la de la funcin


prodABap1. Su lectura, por otro programador, tambin es ms fcil. Sin
embargo, la funcin prodABsub1 tiene algunas ineficiencias claras.
Dentro de un bucle f or (y dentro de los otros bucles) no se deben
realizar operaciones independientes de las variables que se modifican
dentro del for; es ms eficiente usar una variable a la que se le asigna,
fuera del for, el valor de la operacin y, en lugar de efectuar la operacin
dentro del for, se usa la variable suplementaria. Por ejemplo, en la
funcin prodABsub 1, dentro del bucle f or (k= ... ) se realiza varias veces,
quizs muchas, la operacin Hn+k. Como las variables i, n no se
modifican dentro de este f or, entonces es preferible utilizar una variable
entera adicional, por ejemplo llamada in, fuera de este f or hacer la
asignacin in = i*n; y dentro del for(k= ... ) utilizar a [in+k] .
La siguiente funcin, prodABsub2, es una versin ms eficiente de
la funcin prodABsub1 .

int prodABsub2(double *a, int m, int n, double *b, int p,


int q, double *c)
{
II ...

int i, j, k, in, iq;


double s;

122
6.4. MATRICES Y ARREGLOS UNIDIMENSIONALES

if(m<Olln<Ollp<Ollq<O 11 n!= p ) return O;

for( i=O; i < m; i++){


in = i*n;
iq = i*q;
for( j=O; j < q; j++){
s = 0.0;
for( k=O; k<n; k++) s += a[in+k]*b[k*q+j];
c[iq+j] = s;
}
}
return 1;
}

En la funcin anterior se observa que la variable de control para el primer


for es la variable i, pero ella no se utiliza sola dentro del for, sirve para
calcular in e iq. Se puede pensar que el for puede estar controlado
directamente por una de las dos variables. Tambin se puede pensar en
cambiar el f or por while o viceversa. A manera de ilustracin, aparecen
a continuacin otras dos funciones que tambin realizan el producto de
dos matrices almacenadas en arreglos unidimensionales.

int prodABsub3(double *a, int m, int n, double *b, int p,


int q, double *c)
{
II ...

int i, j, k, in, iq, kq, ink, iqj;


double s;

if(m<OI In<OI Ip<OI Iq<O 11 n!= p ) return O;

iq = O;
for( in=O; in < n*m; in += n){
iqj = iq;
for( j=O; j < q; j++){
s = 0.0;
ink = in;
for( kq=O; kq<n*q; kq += q){

123
6. APUNTADORES

S += a[ink]*b[kq+j];
ink++;
}
c[iqj] s;
iqj++;
}
iq += q;
}
return 1;
}
11---------------------------------------------------------
int prodABap2(double *a, int m, int n, double *b, int p,
int q, double *c)
{
II ...

double *cij, *aik, *bkj;11 apuntadores a: Cij, Aik, Bkj


double *aiO; II apuntador a AiO
double *ain; II apunto a A(i+1,O) : a[i*n]
double *bOj; II apuntador a B(O,j)
double *amn;
double *bOq;

i f (m<O I In<O I Ip<O I Iq<O I In! = p ) return O;

amn a + m*n;
bOq b+q;
cij c;
ain a+n;
for( aiO = a; aiO < amn; aiO += n){
for( bOj = b; bOj < bOq; bOj++){
bkj = bOj;
*cij = 0.0;
for(aik = aiO; aik < ain; aik++ ){
*cij += (*aik)*(*bkj);
bkj += q;
}
cij++;

124
6.4. MATRICES Y ARREGLOS UNIDIMENSIONALES

}
ain += n;
}
return 1;
}

Esta funciones pueden ser mejoradas dependiendo, parcialmente, de la


plataforma y del compilador. Todas tienen una eficiencia ms 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 x 500 y 1000 x 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 nmero de operaciones para el producto de dos matrices n x n es
proporcional a n 3 . Es interesante comprobar que, al duplicar el tamao
de las matrices, el tiempo, aproximadamente, se multiplica por 23 = 8.

I n = 500 I n = 1000 I
subndices prodABsub1 8.8 67.8
subndices prodABsub2 8.0 63.3
subndices prodABsub3 7.7 60.9
apuntadores prodABap1 7.8 63.1
apuntadores prodABap2 7.9 63.4

Otra manera de hacer el producto de dos matrices almacenadas en vec-


tores, mediante el uso de apuntadores, que permite ms clridad 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 produc-
to 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 di-
reccin del primer elemento de la fila y tiene n elementos, uno despus
del otro, de manera contigua. En la columna j de la matriz B hay un
ligero inconveniente, los elementos estn en un arreglo, pero no conse-
cutivamente. Para pasar de un elemento al siguiente, hay que saltar q
posiciones (suponiendo que B es p x q).
A continuacin hay dos funciones que hacen el producto escalar de
dos vectores de n elementos. El primero est almacenado en el arre-
glo x; hay que saltar sal tox posiciones para pasar de un elemento al
siguiente. Es decir, son los elementos x [O], x [sal tox] , x [2*sal tox] ,

125
6. APUNTADORES

.. , X [(n-l) *sal tox]. De manera anloga, los elementos del segundo

vector son: y[O], y [saltoy], y [2*saltoy], ... , y[(n-1)*saltoyJ. La


primera funcin prodXYsub se hace de manera casi natural; la segunda,
prodXY, es posiblemente ms eficiente, pero su programacin requiere
ms tiempo. Se puede utilizar el siguiente criterio: es til gastar ms
tiempo haciendo una funcin ms eficiente si sta se va a usa muchas
veces. Como es ms eficiente i ++ que i += 1, entonces esta ltima
funcin considera por aparte el caso salto == 1 Y el caso salto ! = 1.

double prodXYsub( double *x, int saltox, double *Y,


int saltoy, int n)
{
II producto escalar de dos vectores
II uso de subindices
II x[O] , x [saltox], x [2*saltox], ... , x[(n-l)*saltox]
II y[O], y [saltoy], y [2*saltoy], ... , y[(n-l)*saltoy]

double s 0.0;
int i;

if(n<O){
printf("prodXY: n negativo\n");
return s;
}
if( n==O ) return s;
for(i=O; i<n; i++) s += x[i*saltox]*y[i*saltoy];
return s;
}
11------------------------------------------------
double prodXY( double *x, int saltox, double *y,
int saltoy, int n)
{
II producto escalar de dos vectores
II uso de apuntadores
II x[O] , x [saltox] , x [2*saltox] , ... , X [(n-1) *saltox]
II y[O], y [saltoy], y [2*saltoy], y [(n-l) *saltoy]

double s = 0.0;
double *xi, *yi, *xn, *yn;

126
6.4. MATRICES Y ARREGLOS UNIDIMENSIONALES

if( n < O ){
printf("prodXY: n negativo\n");
return 0.0;
}
if( n==O ) return 0.0;

if( saltox == 1 ){
if( saltoy == 1 ){
II saltox = saltoy 1
xi x',
xn x + n;
yi y;
while( xi < xn ) s += (*xi++)*(*yi++);
}
else{
II saltox = 1; saltoy != 1
xi x;
xn = x + n;
yi = y;
while( xi < xn ){
s += (*xi++)*(*yi);
yi += saltoy;
}
}
}
else{
if( saltoy == 1 ){
II saltox > 1; saltoy 1
yi y;
yn y + n;
xi x;
while( yi < yn ){
s += (*xi)*(*yi++);
xi += saltox;
}
}
else{

127
6. APUNTADORES

II 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 funcin prodXY, la funcin 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)
{
II Producto de dos matrices, A mxn, B pxq.
II Devuelve 1 si se puede hacer el producto,
II devuelve O si no se puede.
II Las matrices estan almacenadas en "vectores".
II El producto se hace por medio de apuntadores.
II Utiliza una funcion de producto escalar.

double *cij; II apuntador a Cij


double *cmq; II apuntador a la direccion de c[m*q]
double *ciq; II apunto a C(i+1,0) : Ciq : c [i*q]
double *aiO; II apuntador a AiO
double *bOj; II apuntador a BOj

if(m<Olln<Ollp<Ollq<O 11 n!= p ) return O;


cij c;
cmq = c+m*q;
aiO = a;
while( cij < cmq ){
ciq = cij + q;

128
6.5. ARREGLOS ALEATORIOS

bOj = b;
while( cij < ciq ){
*cij = prodXY(aiO, 1, bOj, q, n);
cij++;
bOj++;
}
aiO += n;
}
return 1;
}

Normalmente una funcin es un poco menos eficiente cuando llama otra


funcin para hacer un proceso, que cuando directamente lo hace inter-
namente. Pero, por otro lado, repartir el trabajo en funciones permite
revisar, depurar y tratar de optimizar ms fcilmente cada funcin por
aparte.
En el ejemplo del producto de matrices, result an ms eficiente esta
ltima funcin ~prodAB1~ que la funcin prodABap1. Esto se debe tal
vez a que la funcin prodXY es bastante eficiente y que muy posiblemente
la funcin prodABsubl 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.

I n = 500 I n = 1000 I
subndices prodABsub2 8.0 63.3
apuntadores prodABapl 7.8 63.1
apuntadores + prod. escalar prodABl 7.0 56.0

6.5 Arreglos aleatorios


El lector podr preguntarse:

Cmo trabajar con matrices 500 x 500?

Entrando los valores por teclado? (el autor de este libro no lo


hizo).

Leyendo los datos en un archivo? Podra ser, pero todava no se


ha visto este tema.

129
6. APUNTADORES

Creando la matriz con alguna frmula especfica? Podra ser, por


ejemplo, aij = 10000i + j.

Creando la matriz aleatoriamente? Porqu no?

C provee una funcin para crear nmeros aleatorios: rand (). Es-
ta funcin da como resultado enteros entre O y RANO_MAX, cuyo valor
est definido en el archivo de cabecera stdlib. h. La siguiente funcin
devuelve un valor doble precisin aleatorio, o seudoaleatorio, en el inter-
valo [a, b]. Se utiliza el cambio de variable
b-a
t = a + RANO...MAX r .
Cuando r vale O, entonces t vale a. Cuando r vale RANO_MAX, entonces t
vale b.

double aleat(double a, double b)


{
II calculo de un numero aleatorio en [a, b ]

double r;

r = a + rand()*(b-a)/RANO_MAX;
return r;
}

Utilizando la anterior funcin se puede hacer una funcin que da valores


aleatorios a los elementos de un arreglo unidimensional.

void aleatX( double *x, int n, double a, double b)


{
II vector aleatorio, valores entre a y b

int k;

for( k=O; k<n; k++) x[k] aleat(a,b) ;


}

En el siguiente trozo de programa, se hace el llamado a la funcin ante-


rior, primero para un vector, luego para una matriz almacenada en un
arreglo unidimensional.

130
6.6. ASIGNACIN DINMICA DE MEMORIA

double x[1000];
double a[250000]; II 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 Asignacin dinmica de memoria


Cuando se declara un arreglo en una funcin, por ejemplo en main,
con un tamao determinado, C separa para l la memoria durante todo
el tiempo que el control del programa est en esa funcin (desde que
entra hasta que sale). Buscando que el programa sea general, es nece-
sario declarar el arreglo con un nmero muy grande de elementos. Sin
embargo, la mayora de las veces se va a usar ese arreglo con un nmero
pequeo de elementos. La memoria reservada para ese arreglo no puede
ser utilizada por otro arreglo que podra necesitarla. Como la memoria es
un recurso finito, no debe desperdiciarse. Ms an: si se trata de utilizar
arreglos demasiado grandes podra producirse un error, durante la com-
pilacin, por memoria insuficiente. En algunos sistemas operacionales,
cuando se pide ms memoria que la disponible, el sistema utiliza el disco
duro para reemplazar la memoria faltante, pero hay un inconveniente: el
acceso al disco duro es mucho menos rpido que el acceso a la memoria.
C permite trabajar con arreglos del tamao exactamente necesita-
do, mediante la asignacin dinmica de memoria. Considere el siguiente
ejemplo, que usa las funciones anteriores escrX, aleat, aleatX.

double *x;
int n;

printf(" n = ");
scanf("%d", &:n );

131
6. APUNTADORES

x = malloe( n*sizeof(double) );
if ( X == NULL ){
printf(" Memoria insufieiente\n");
exit(1) ;
}
aleatX(x, n, -1.0, 1.0);
eserX(x, n);
free(x);
A lo largo de este libro se supondr que cuando un programa usa funcio-
nes definidas con anterioridad, para que funcione, es necesario agregar, al
cdigo presentado, el prototipo, la definicin y los archivos de cabecera
de cada una de las funciones utilizadas.
La funcin sizeof, del lenguaje C, da como resultado un entero
que indica el nmero de bytes que utilizan las variables cuyo tipo es
el indicado por el parmetro. En la mayora de las implementaciones
sizeof (double) es 8. La funcin malloe reserva el nmero de bytes in-
dicado por el parmetro. Se hubiera podido escribir x = malloe (n*8),
pero podra no funcionar en un computador con un compilador de C
donde los nmeros doble precisin utilicen un nmero de bytes diferente
de 8. Cuando no hay suficiente memoria disponible, la funcin malloe
devuelve NULL, o sea, el apuntador valdr NULL. Es muy conveniente
controlar siempre si hubo suficiente memoria. La funcin free libera el
espacio que haba sido reservado para x.
El ejemplo anterior, hecho en C, y suponiendo que las funciones estn
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 malloe:
x = (double *)malloe( n*sizeof(double) );

La asignacin anterior es vlida tanto en C como en C++.

La asignacin de memoria en C++ es ms sencilla; se hace por medio


de new. La memoria que ya fue utilizada y que no se necesita ms, se
libera mediante delete. Aunque a veces no es absolutamente indispen-
sable liberar la memoria al salir de una funcin, de todas maneras s es
una buena costumbre de programacin el hacerlo.

132
6.6. ASIGNACIN DINMICA DE MEMORIA

Los ejemplos que siguen se refieren a la evaluacin de un polinomio


p en un valor dado t. Supongamos que en un arreglo p estn almace-
nados los coeficientes de un polinomio de grado n. Las siguientes lneas
permiten leer el grado del polinomio, asignar memoria dinmicamente
para almacenar los coeficientes, dar valores aleatorios a los coeficientes
e imprimirlos.

double *p;
int n;

printf(" n = 11);
scanf("%d", &n );

p = new double[n+l] ;
if( P == NULL ){
printf(" Memoria insuficiente\n");
exit(1) ;
}
aleatX(p, n+l, -10.0, 10.0);
escrX(p, n+l);

delete p;

La siguiente funcin muestra una manera sencilla, pero ineficiente, de


evaluar p(t).

double evalPolOO( double *p, int n, double t)


{
II evaluacion simplista de p(t)
II p(x) = p[O] + p[l]*x + p[2]*x*x + ... + p[n]*x-n

int i;
double pt = 0.0;

for( i=O; i<= n; i++) pt += p[i]*pow(t,i);


return pt;
}

Una manera ms eficiente de evaluar p(t) = ao + alt + a2t2 + ... + antn


133
6. APUNTADORES

consiste en observar la siguiente manera de agrupar.

p(t) = ( ... (((an)t + an-l)t + an-2)t + ... + al)t + ao.


Es decir, se empieza con el valor ano A continuacin se repite el proce-
so: se multiplica por t y se adiciona el siguiente coeficiente (en orden
decreciente). Esta manera de calcular se conoce con el nombre de esque-
ma de Horner o tambin hace parte del proceso conocido como divisin
sinttica. La divisin sinttica permite evaluar p(t) y, al mismo tiempo,
proporciona el polinomio cociente al efectuar la divisin p(x)j(x - t).
Como ejemplo, considere el polinomio p(x) = 3 - 4x + 5x 2 - 16x 3 + 7x 4
dividido por x - 2.
7 -16 5 -4 312
14 -4 2 -4
7 -2 1 -2 -1
Entonces p(2) = -1 y 7x 4 - 16x3 + 5x2 - 4x + 3 = (7x 3 - 2x2 +X -

2)(x - 2) + (-1).
La primera de las dos funciones que siguen, evalPol, evala el poli-
nomio en un valor t usando el esquema de Horner. La segunda funcin
devuelve p(t) (que tambin es el residuo) yen el arreglo apuntado por q
estn los coeficientes del polinomio cociente de la divisin. El arreglo p
debe tener n + 1 elementos; el cociente, de grado n - 1, tiene n elementos.

double evalPol( double *p, int n, double t)


{
jj evaluacion de p(t) utilizando el esquema de Horner
jj p(x) = p[O] + p[1]*x + p[2]*x*x + ... + p[n]*x-n

double pt, *pi, *pn;

pi = P + n;
pt = *pi;
pi--;
while( pi >= P ) pt pt*t + *pi--;
return pt;
}
jj------------------------------------------------
double divSint( double *p, int n, double t, double *q)

134
6.7. MATRICES Y APUNTADORES DOBLES

{
II division sintetica de p(x)/(x-t)
II n es el grado del polinomio
II p(x) = p[O] + p[l]*x + p[2]*x*x + ... + p[n]*x-n
II devuelve el residuo
II q contiene el cociente

double pt; II p(t) : residuo


double *pi, *pn, *qi;

pi = P + n;
pt = *pi;
pi--;
qi = q+n-l;
while( pi >= P ){
*qi-- = pt;
pt = pt*t + *pi--;
}
return pt;
}

Al utilizar las funciones evalPolOO y evalPol con polinomios creados


aleatoriamente, se ve una gran gran diferencia entre la eficiencia de los
dos mtodos. La siguiente tabla muestra algunos tiempos en segundos.

n= 500000 1000000 5000000


evalPolOO 0.33 0.65 3.56
evalPol 0.03 0.06 0.29

6.7 Matrices y apuntadores dobles

Otra de las maneras tiles para el manejo de matrices, que no quitan


generalidad a las funciones, es mediante apuntadores dobles (apuntado-
res a apuntadores).
Consideremos una matriz de m filas y n columnas. Cada fila tiene n
elementos y se puede considerar como un arreglo unidimensional de n
elementos. Para el manejo de cada fila, basta con conocer la direccin
del primer elemento de la fila. O sea, cada fila se maneja por medio de un

135
6. APUNTADORES

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 direccin del primer apuntador, o sea, con un
apuntador a apuntador.
Si a es un apuntador doble, entonces a [iJ es la direccin de a [iJ [OJ
y a es la direccin de a [O J , es decir,

a [iJ &a [iJ [OJ,


a &a[OJ.

En el siguiente ejemplo se hace un asignaclOn dinmica 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;
jj--------------------------------------------
jj asignacion de memoria
a = new double *[mJ
if( a == NULL ){
printf("Memoria insuficiente\n");
exit(1) ;
}
for( i=O; i<m; i++) {
a[iJ = new double [nJ;
if( a[iJ == NULL ){
printf(IIMemoria insuficiente\n");
exit(1) ;
}
}
jj--------------------------------------------
jj algunos resultados
for( i = O; i < m; i++){
for( j = O; j < n; j++)

136
6.7. MATRICES Y APUNTADORES DOBLES

printf("&a[%d] [%d]=%d ", i, j, &a[i] [j] );


Ilprintf(lI&a%d%d=%d ", i, j, &a[i] [j]);
printf("\n");
}
printf("\n");
for(i=O; i<m; i++) printf("a[%d]=%d\n", i, a[i]);
printf("\n");
for(i=O; i<m; i++) printf("&a[%d]=%d\n", i, &a[i]);
printf("\n");
printf(" a = %d\n", a);
11--------------------------------------------
II liberacion de memoria

for( i=O; i<m; i++) delete a[i] ;


delete a;

Los resultados pueden ser los siguientes:

&a[O] [0]=6695108 &a[O] [1]=6695116 &a[O] [2]=6695124


&a[l] [0]=6695136 &a[l] [1]=6695144 &a[l] [2]=6695152
&a[2] [0]=6695164 &a[2] [1]=6695172 &a[2] [2]=6695180
&a[3] [0]=6695192 &a[3] [1]=6695200 &a[3] [2]=6695208

a[O] =6695108
a[l] =6695136
a[2] =6695164
a[3] =6695192

&a[O] =6695088
&a[1]=6695092
&a[2]=6695096
&a[3] =6695100

a = 6695088

Observe, en el ejemplo anterior, los siguientes hechos:

En la declaracin, el nombre del apuntador doble est precedido


por dos asteriscos.

137
6. APUNTADORES

Primero se asigna memoria para un arreglo de apuntadores.

En la asignacin de memoria para un arreglo de apuntadores, se


coloca un asterisco antes del parntesis cuadrado izquierdo.

A cada uno de los apuntadores del arreglo de apuntadores se le


asigna memoria para los elementos de la fila correspondiente.

La liberacin de memoria se hace en el orden inverso, primero se


libera la memoria apuntada por cada uno de los apuntadores del
arreglo de apuntadores.

Despus se libera la memoria apuntada por el apuntador doble.

En los resultados se pueden comprobar varios hechos. El primer pa-


quete muestra las direcciones de cada uno de los elementos de la matriz.
Observe que en cada fila las direcciones son consecutivas (de 8 en 8 por
tratarse de nmeros doble precisin). El primer elemento de una fila
no est en la direccin siguiente a la direccin del ltimo elemento de
la fila anterior. El segundo paquete muestra los valores del arreglo de
apuntadores. Obviamente el valor de a [i] es exactamente la direccin
de a [i] [O]. El tercer paquete de resultados muestra las direcciones de
los elementos del arreglo de apuntadores. Las direcciones son contiguas,
pero no de 8 en 8. El valor de a es exactamente la direccin del primer
elemento del arreglo de apuntadores.
La asignacin dinmica de memoria para una matriz en un apuntador
doble, y su liberacin, pueden hacerse por medio de las funciones que
aparecen a continuacin.

double **creaA( int m, int n)


{
II asigna dinamicamente memoria para una matriz m x n
II m >= 1, n >= 1
II devuelve un valor de apuntador a apuntador
II tipo doble precision

double **p;
int i;

p new double *[m]

138
6.8. ARREGLOS A PARTIR DE 1

if( p == NULL ) return( NULL );

for( i=O; i<m; i++) {


p[i] = new double[n];
if( p[i] == NULL ) return( NULL );
}
return p;
}
11---------------------------------------------------------
void libA( double **a, int m)
{
II libera memoria asignada a una matriz
II m numero de filas

int i;

for( i = O; i < m; i++) delete a[i];


delete a;
}

A continuacin aparece un ejemplo de la utilizacin de estas dos funcio-


nes.

double **a;
int m, n;

a = creaA(m, n);

libA( a, m);

Observe en la definicin de la funcin, que creaA devuelve un apuntador


doble, indicado por los dos asteriscos que preceden al nombre de la
funcin. Por supuesto en el llamado se necesita un apuntador doble.

6.8 Arreglos a partir de 1


Como se ha visto, los arreglos en C empiezan en o. A veces por
mayor comodidad, o por necesidad, deben comenzar en el subndice 1.

139
6. APUNTADORES

Mediante un desplazamiento del valor del apuntador, se puede manejar


un apuntador con subndices entre 1 y n. Ms an, es posible hacer
variar el subndice entre dos valores enteros i1 <i2.
Considere la siguiente porcin de programa.

double *x; II arreglo entre 1 y n

int n, i;

n 7;
x new double[n];
x-_,

fore i 1; i <= n; i++) x[i] i*i*i;

x++;
delete x;

Suponga que el valor de x, despus de la asignacin de memoria, es


la direccin 10328. Entonces las 7 direcciones para los 7 elementos del
arreglo son: 10328+0 x 8, 10328+1x8, 10328+2x8, ... , 10328+6x8. La
orden x-- hace que el valor de x se disminuya en una unidad de memoria
doble precisin, 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 x 8, 10320 + 2 x 8, 10320 + 3 x 8, ... ,
10320 + 7 x 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, en-
tonces es necesario incrementar su valor en una unidad (de memoria
doble precisin).
La siguiente porcin de programa muestra cmo podra ser el ma-
nejo de arreglos bidimensionales con asignacin dinmica de memoria,
comenzando en el subndice 1.

double **a; II matriz con subindices en [1,m], [1,n]

intm, n, i, j;

m 3;

140
6.8. ARREGLOS A PARTIR DE 1

n = 4;
a = new double * [m] ;
i f ( a == NULL ){
printf(1I Memoria insuficiente\n");
exit(1) ;
}
a--;
for( i = 1; i <= m; i++){
a[i] = new double[n] ;
if( a[i] == NULL ){
printf(1I Memoria insuficiente\n");
exit(1) ;
}
a [i] --;
}

fore i 1; i <= m; i++){


for( j = 1; j <= n; j++) a[i] [j] i*j;
}

II liberacion de la memoria

fore 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 i 1. El siguiente ejemplo ilustra lo anterior.

double *y; II arreglo entre i1 e i2, i1 < i2

int i, i 1, i2;

141
6. APUNTADORES

i1 -2;
i2 7;

y = new double[i2-il+l];
y -= i1;

for( i =il; i <= i2; i++) y[i] randO;

y += i1;
delete y;

Ejercicios
Para cada uno de los enunciados siguientes, defina cules son los datos
necesarios. Haga un programa que lea los datos, llame la funcin (o las
funciones) que realiza los clculos y devuelve los resultados, y finalmente
que el programa principal (la funcin main) muestre los resultados. En
todos los casos haga asignacin dinmica 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 mltiplo de otra
fila.

6.3 Construya la traspuesta de una matriz.

6.4 Dada una matriz A, calcule ATA.

6.5 Averige si una matriz es simtrica.

6.6 Averige si una matriz es diagonal.

6.7 Averige si una matriz es triangular superior.

142
7

Lectura y escritura en
archivos

Este captulo presenta las nociones de e sobre la lectura y escritura


en archivos de texto. La lectura de un archivo existente, se hace de
manera secuencial, es decir, lo que est en el archivo se lee en el orden en
que aparece. No se puede leer un dato al principio del archivo, despus
al final y despus en la mitad. La escritura tambin es secuencial.
En realidad, de manera artificial, s se podra, por ejemplo, leer el
primer dato, leer los datos que siguen pero desechndolos hasta llegar
al final, leer el dato deseado, devolverse hasta el principio, leer datos
desechndolos y leer el dato deseado en un punto intermedio del archivo.
Sin embargo, en este libro, siempre se supondr 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 estn a continuacin. La palabra entrada se refiere a lectura: la
informacin entra, desde un archivo, al "programa". La palabra salida se
refiere a escritura: la informacin sale del "programa" hacia un archivo.
Observe que por convencin todas empiezan por la letra f (de file).

fopen,
fscanf,
fclose,
fprintf,
feof.

143
7. LECTURA Y ESCRITURA EN ARCHIVOS

7.1 fopen, fscanf, fclose, fprintf


El siguiente programa lee en un archivo el tamao de un vector, lee
las componentes del vector, calcula el promedio y escribe este ltimo
resultado en otro archivo.

II lectura de un vector en un archivo


II escritura del promedio en otro archivo

#include ...

int mainO
{
double *x, prom;
FILE *archDat, *archRes;
int n, i;

archDat = fopen(ldatos1", "r");


if( archDat == NULL ){
printf(lI\n\n Archivo inexistente.\n\n");
exit (1) ;
}
fscanf (archDat, "%d", &n);
x = new double[n];
i f ( x == NULL ){
printf("\n\n Memoria insuficiente.\n\n");
exit(1) ;
}
for( i=O; i<n; i++) fscanf(archDat, "%lf", &x[i]);
f close (archDat) ;

archRes fopen("ejemplo.res", "W");

prom = promX(x, n);


fprintf (archRes, 11 promedio %12. 4lf\n ", prom);
fclose(archRes);
return O;
}

144
7.1. FOPEN, FSCANF, FCLOSE, FPRINTF

El programa usa las variables arehDat y arehRes. Estas variables apun-


tan 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 arehDat es el nombre de un archivo dentro del programa.
El nombre externo del archivo, en el sistema operacional, es datos1.
La funcin f open hace la correspondencia entre el nombre interno y el
nombre externo, y abre el archivo. El segundo parmetro de f open, o
sea la cadena de caracteres "r", indica que se trata de un archivo para
lectura.
Las maneras ms usuales de manejo de archivos de texto mediante
fopen son:

"r" Para lectura.


"w" Para escritura.
"a" Para escritura, al final del archivo.
"r+" Para lectura y escritura.

Al abrir un archivo para lectura, necesariamente debe existir. Si la fun-


cin fopen no puede abrir el archivo, entonces devuelve NULL. Es una
buena costumbre verificar si el programa pudo abrir el archivo.
La lectura en un archivo se puede hacer mediante la funcin f seanf.
Su manejo es semejante al de seanf, pero tiene un parmetro adicional,
antes de la cadena de formato. Este primer parmetro indica en qu ar-
chivo (nombre interno dentro del programa) va a hacerse la lectura. En
el programa del ejemplo, la funcin fseanf se utiliz para leer n (tamao
del vector) y para leer cada una de las componentes del vector.
Supongamos que el vector tiene cuatro componentes y sus valores son
1.2, 1.8, 3 Y 4. Como la lectura es secuencial, cualquiera de los siguientes
tres ejemplos de archivo (hay muchos otros ms) son adecuados.

Primer ejemplo del archivo datos!:

4
1.2 1.8 3 4

Segundo ejemplo del archivo datos!:

4 1.2
1.8
3 4

145
7. LECTURA Y ESCRITURA EN ARCHIVOS

Tercer ejemplo del archivo datos!.

1.2
1.8

3 4 5.1

La funcin fclose permite cerrar los archivos de texto previamente


abiertos. Algunas veces no es absolutamente necesario cerrar los archi-
vos, pero es una buena costumbre de programacin cerrar los archi-
vos abiertos cuando finaliza su uso. El nico parmetro para la funcin
fclose es el nombre (interno) del archivo.
La escritura en un archivo se puede hacer con la funcin fprintf.
Su manejo es semejante al de printf, pero tiene un parmetro adicio-
nal, antes de la cadena de formato. Este primer parmetro indica en
qu archivo (nombre interno en el programa) va a hacerse la escritura.

Al tratar de abrir un archivo para escritura, en modo "w", pueden pre-


sentarse tres casos.

Existe el archivo con ese nombre, entonces f open borra el existente


y crea uno nuevo, listo para empezar a escribir en l.

El nombre de archivo es adecuado pero no existe, entonces fopen


crea uno con ese nombre, listo para empezar a escribir en l.

El nombre del archivo es inadecuado, entonces fopen devuelve el


valor NULL.

El programa del ejemplo anterior hace uso de una funcin promX, que
calcula el promedio de los primeros n elementos de un arreglo. Puede
ser cualquiera de las cuatro funciones promX del captulo 5. Obviamente
hay que incluirla dentro del programa, lo mismo que su prototipo.
En el programa del ejemplo, el archivo de lectura se llama datos 1 y
el archivo de escritura se llama ej emplo. res. Si se quiere modificar los
datos, basta con editar el archivo datos1, efectuar los cambios necesarios
y correr de nuevo el programa. En algunos casos esto puede ser til.

146
7.1. FOPN. FSCANF, FCLOSE, FPRINTF

Pero en otros casos puede ser ms flexible dar al programa, durante su


ejecucin, los nombres de los archivos que van a ser usados.
El siguiente programa, modificacin del anterior, permite que duran-
te la ejecucin reciba los nombres de los archivos.

II Lectura y escritura en archivos


II lectura de los nombres de los archivos

#include ...

int mainO
{
II lectura de un vector en un archivo
II escritura del promedio en otro archivo

double *x, prom;


FILE *archDat, *archRes;
char nombre [41] ;
int n, i;

printf("\n Nombre del archivo con los datos: lO);


gets(nombre);
archDat = fopen(nombre, "r");
if( archDat == NULL ){
printf("\n\n Archivo inexistente.\n\n");
exit(1) ;
}
fscanf (archDat, "%d", &n);
x = new double[n];
i f ( x == NULL ){
printf("\n\n Memoria insuficiente.\n\n");
exit(1) ;
}
for( i=O; i<n; i++) fscanf(archDat, "%lf", &x[i]);
fclose(archDat);

printf("\n Nombre del archivo para resultados: lO);


gets(nombre);
archRes = fopenCnombre, "w");

147
7. LECTURA Y ESCRITURA EN ARCHIVOS

if( archRes == NULL ){


printf("Nombre de archivo de resultados erroneo.\n");
exit(1) ;
}
prom = promX(x, n);
fprintf(archRes, 11 promedio %12.4lf\n", prom);
fclose(archRes);
return O;
}

La funcin fscanf, de manera anloga a la funcin scanf, devuelve un


valor entero que indica el nmero de campos bien ledos y almacenados.
Si no hubo almacenamiento, fscanf devuelve O; si encuentra el final del
archivo, devuelve EOF (generalmente EOF es lo mismo que -1).

7.2 feof
En los dos ejemplos anteriores, el primer dato indicaba el nmero
de valores que el programa deba leer. En algunos casos se sabe que
un archivo contiene valores y es necesario leerlos, pero no se conoce
por anticipado el nmero de valores. Entonces el programa debe leer
hasta que encuentre el final del archivo. Para esto se utiliza la funcin
f eof (end of file). Esta funcin tiene como parmetro un archivo (un
apuntador a tipo FILE). Devuelve un valor no nulo si se ha alcanzado
el fin de archivo, y O en caso contrario.
Suponga que es necesario calcular el promedio y la desviacin estn-
dar de los valores contenidos en un archivo. La definicin de desviacin
estndar
(J = (~=1 (~i - x)2) 1/2

indicara que es necesario conocer primero el promedio, x, para poder


calcular los valores (Xi - x)2, es decir, se necesitara leer dos veces el
archivo, la primera para poder calcular el promedio y la segunda para
los valores (Xi - x)2. Otra posibilidad consistira en almacenar todos
los valores en un arreglo y despus hacer todos los clculos necesarios.
Esto implicara el uso de mucha memoria, si el archivo es muy grande.
Finalmente, una solucin mucho ms eficiente consiste en utilizar otra

148
7.2. FEOF

definicin equivalente de desviacin estndar:


""n
i-1Xi2 - nx-2) 1/2
(J=
( n
El siguiente programa lee valores numricos en un archivo, hasta que
encuentra el fin de archivo o hasta que detecta problemas en la lectura
mediante fscanf. Calcula el promedio y la desviacin estndar de los
valores ledos.

II Calculo de la desviacion estandar


II Utilizacion de feof

#include ...

int mainO
{
double xi, prom, sumax, sumaxx, desvEst;
FILE *archDat, *archRes;
char nombre [41] ;
int n, fin, res;

printf("\n Nombre del archivo con los datos: 11);


gets(nombre);
archDat = fopen(nombre, "r");
if( archDat == NULL ){
printf("\n\n Archivo inexistente.\n\n");
exit (1) ;
}

printf("\n Nombre del archivo para resultados: 11);


gets(nombre);
archRes = fopen(nombre, "W");
if( archRes == NULL ){
printf("Nombre de archivo de resultados erroneo.\n");
exit(1) ;
}
sumax 0.0;
sumaxx 0.0;
n = O;

149
7. LECTURA Y ESCRITURA EN ARCHIVOS

fin = O;
while( !fin ){
res = fscanf(archDat, "%lf", &xi);
if( feof(archDat) II res <= O ) fin = 1;
else{
fprintf (archRes, "%12. 6lf\n", xi);
n++;
sumax += xi;
sumaxx += xi*xi;
}
}
fclose(archDat);

if( n > O ){
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);
}
el se {
fprintf(archRes, " No hay numeros.\n");
}
fclose(archRes);
return O;
}

Si en el archivo solamente hay nmeros bien escritos, el programa calcula


su promedio y desviacin estndar. Si antes del fin de archivo la funcin
fscanf detecta errores en la lectura, entonces el programa calcula el
promedio y desviacin estndar de los valores ledos hasta ese momento.

7.3 Algunos ejemplos


A continuacin 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
7.3. ALGUNOS EJEMPLOS

{
II Lectura en un archivo de los primeros n
II elementos de un arreglo x.

II Devuelve 1 si se efectuo la lectura normalmente,


II O si se encontro fin de archivo antes
II de acabar la lectura,
II -1 si hubo un error durante la lectura
II con fscanf.

int i, res;

for(i=O; i< n; i++){


res = fscanf(arch, "%lf" , &x[i]);
if( feof(arch) ) return O;
if( res <= O ) return -1;
}
return 1;
}
11---------------------------------------------------------
void fescrX(FILE *arch, double *x, int n )
{
Ilescritura en un archivo de los elementos de un vector

int j;
int nEltosLin 5; II numero de elementos por linea

for( j = O; j < n; j++){


fprintf(arch, "%15.8lf", x[j]);
ifj+1)%nEltosLin == O II j== n-1)
fprintf (arch, "\n") ;
}
}

A continuacin se presenta un ejemplo esquemtico de la utilizacin de


las dos funciones anteriores.

double *x;
FILE *archDat, *archRes;

151
7. LECTURA Y ESCRITURA EN ARCHIVOS

int n, res;

archDat = fopen( ... , "r");


if( archDat == NULL ){
printf(lI\n\n Archivo inexistente.\n\n");
exit(1) ;
}

archRes fopen( ... , "W");

fscanf (archDat, "%d", &n);


x = new double[n];
res = flectX(archDat, x, n);
switch( res ){
case 1:
fprintf(archRes," x :\n");
fescrX(archRes, x, n);
break;
case O:
fprintf(archRes,"Fin de archivo imprevisto.\n");
break;
case -1:
fprintf(archRes, "Error en lectura.\n");
break;
default:
fprintf(archRes, IRARISIMO.\n");
break;
}

Las siguientes funciones sirven para lectura y escritura en archivos de


matrices en arreglos unidimensionales o mediante apuntadores dobles.

int flectA1(FILE *arch, double *a, int m, int n)


{
II Lectura en un archivo de una matriz m x n
II almacenada en un arreglo unidimensional

152
7.3. ALGUNOS EJEMPLOS

II Devuelve 1 si se efectuo la lectura normalmente,


II O si se encontro fin de archivo antes
II de acabar la lectura,
II -1 si hubo un error durante la lectura
II con fscanf.

II usa flectX

int i, res;

for(i=O; i< m; i++){


res = flectX(arch, &a[i*n], n);
if( res <= O ) return res;
}
return 1;
}
11------------------------------------------------
void fescrA1(FILE *arch, double *a, int m, int n)
{
II Escritura en un archivo de una matriz m x n
II almacenada en un arreglo unidimensional

II usa fescrX

int i;

for(i=O; i< m; i++) fescrX(arch, &a[i*n], n);


}
11------------------------------------------------
int flectA(FILE *arch, double **a, int m, int n)
{
II Lectura en un archivo de una matriz m x n
II almacenada mediante un apuntador doble.

II Devuelve 1 si se efectuo la lectura normalmente,


II O si se encontro fin de archivo antes
II de acabar la lectura,
II -1 si hubo un error durante la lectura

153
7. LECTURA Y ESCRITURA EN ARCHIVOS

II con fscanf.

II usa flectX

int i, res;

for(i=O; i< m; i++){


res = flectX(arch, a[i], n);
if( res <= O ) return res;
}
return 1;
}
11------------------------------------------------
void fescrA(FILE *arch, double **a, int m, int n)
{
II Escritura en un archivo de una matriz m x n
II almacenada mediante un apuntador doble.
II usa fescrX

int i;

for(i=O; i< m; i++) fescrX(arch, a[i], n);


}

Ejercicios
Para cada uno de los enunciados siguientes, defina cules son los da-
tos necesarios. Haga un programa que lea los datos en un archivo, llame
la funcin que realiza los clculos y finalmente escriba los resultados en
un archivo.

7.1 Considere los ejercicios de los captulos anteriores, especialmente


aquellos en que el nmero de datos puede ser grande.
7.2 Considere un archivo que contiene nicamente nmeros; por ejem-
plo:

3.141592 -342

154
7.3. ALGUNOS EJEMPLOS

1.5e-2

-32.1542
32.5E+02 +31 31.45 1000
0.31415El

Haga un programa que detecte si hay errores. Si los hay, indique


el nmero de la lnea donde est el error (por lo menos el primero)
y muestre el trozo de lnea donde est el error. Si no hay erro-
res, habiendo averiguado el nmero de nmeros, asigne memoria
dinmicamente y almacene los nmeros. Sugerencia: lea cada lnea
del archivo como una cadena. En cada lnea determine la subcade-
na correspondiente a un posible nmero y convirtala, si es posible,
en un nmero.

7.3 Considere un archivo de texto donde estn los resultados de una


encuesta. Defina la estructura del archivo; por ejemplo, de las co-
lumnas 1 a 10 hay un cdigo, 11-12 edad, 13 sexo, 14-20 sueldo,
21-22 nmero de hijos, etc. Haga un programa que lea el archivo
y encuentre las posibles inconsistencias, no solo de cada campo
(edad, sueldo ... ) sino tambin 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 desigualda-


des) 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 pro-


grama que lea el archivo, detecte si est bien hecho y escriba en
otro archivo el nmero de variables, el nmero 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 trminos
independientes.

155
7.3. ALGUNOS EJEMPLOS

1.5e-2

-32.1542
32.5E+02 +31 31.45 1000
0.31415El

Haga un programa que detecte si hay errores. Si los hay, indique


el nmero de la lnea donde est el error (por lo menos el primero)
y muestre el trozo de lnea donde est el error. Si no hay erro-
res, habiendo averiguado el nmero de nmeros, asigne memoria
dinmicamente y almacene los nmeros. Sugerencia: lea cada lnea
del archivo como una cadena. En cada lnea determine la subcade-
na correspondiente a un posible nmero y convirtala, si es posible,
en un nmero.

7.3 Considere un archivo de texto donde estn los resultados de una


encuesta. Defina la estructura del archivo; por ejemplo, de las co-
lumnas 1 a 10 hay un cdigo, 11-12 edad, 13 sexo, 14-20 sueldo,
21-22 nmero de hijos, etc. Haga un programa que lea el archivo
y encuentre las posibles inconsistencias, no solo de cada campo
(edad, sueldo ... ) sino tambin 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 desigualda-


des) 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 pro-


grama que lea el archivo, detecte si est bien hecho y escriba en
otro archivo el nmero de variables, el nmero 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 trminos
independientes.

155
8

Temas varios

Este captulo contiene varios temas sueltos, que no son indispensables


pero pueden ser muy tiles en algunos casos.

8.1 sizeof

La funcin sizeof sirve principalmente para conocer el nmero de


bytes que utiliza un compilador especfico para los diferentes tipos de
datos. El siguiente ejemplo muestra su uso y los resultados con un com-
pilador y en un computador especfico. Con otro compilador o en otra
clase de computador los resultados pueden ser diferentes.

jj sizeof
#include ...
jj-------------------------------------------------
int mainO
{
double *x, y[10], a[10] [10], *p;

x = new double[20];

printf ("Tama-nos (bytes) de los diferentes tipos.\n\n");


printf(" int %d \n", sizeof(int));
printf(" float %d \n", sizeof(float));
printf(" double %d \n", sizeof(double));

157
8. TEMAS VARIOS

printf(II char %d \n\n", sizeof(char;

printf(II short int %d \n", sizeof(short int;


printf(II long int %d \n", sizeof(long int;
printf(" unsigned %d \n", sizeof(unsigned;
printf(II long double: %d \n\n", sizeof(long double;

p = y;
printf(" arreglo y %d\n", sizeof(y) );
printf(" arreglo a %d\n", sizeof(a) );
printf(II apuntador x %d\n", sizeof(x;
printf (" apuntador p %d\n", sizeof(p;
return O;
}

El programa anterior produce los siguientes resultados:

Tama-nos (bytes) de los diferentes tipos.

int 4
float 4
double 8
char 1

short int 2
long int 4
unsigned 4
long double: 10

arreglo y 80
arreglo a 800
apuntador x 4
apuntador p 4

En este caso, en el mismo computador con el mismo compilador, los


tipos int y long int tienen el mismo tamao; entonces no se justifica
utilizar variables o constantes tipo long int. Al utilizar sizeof con un
arreglo, la respuesta es el nmero total de bytes utilizados por el arre-
glo; por ejemplo, para los arreglos y y a. Los arreglos y los apuntadores

158
8.2. CONST

tienen, en general, una manejo casi idntico, pero son en realidad dife-
rentes. Observe que utilizar sizeof para x, un apuntador al que se le
ha asignado memoria dinmicamente, no da como resultado el total de
memoria asignada. Tampoco devuelve el valor "imaginado", es decir 80,
la utilizacin de sizeof con el apuntador p al que se le asign el valor
de y.

8.2 const
Si en la declaracin de algunas variables, el especificador const pre-
cede al tipo, entonces el compilador sabe que esas variables no pueden
ser modificadas en el programa. Ms especficamente, no puede haber
asignaciones donde el lado izquierdo sea una de esas variables. Adems,
hace ms legible el programa fuente, al indicar que se trata de una cons-
tante.

const double c = 2.998E8, velSon = 331.0;


II velocidades de la luz y del sonido en mis
const int nMax = 100;

El compilador producir un mensaje de error si posteriormente se tra-


ta de hacer una asignacin. El mensaje de error puede ser anlogo a
"Error ... : Cannot modify a const object in function mainO".

c *= 1.001;
nMax += O;

Observe que realmente nMax += O no trata de modificar la variable nMax,


pero para el compilador es un error por estar en el lado izquierdo de una
asignacin.

8.3 typedef
La utilizacin de typedef simplemente introduce un sinnimo para
un tipo de datos. El esquema de su uso es el siguiente:
typedef tipo sinnimo;
Por ejemplo,

159
8. TEMAS VARIOS

typedef int entero;

permite usar entero en lugar de int en las declaraciones de tipo de las


variables, como la siguiente declaracin:

entero i, j 4, m;

En el siguiente ejemplo, referente al psilon de la mquina, se usa la


palabra clave typedef. La representacin de un nmero real en el com-
putador tiene un nmero finito de cifras significativas. Para conocer un
valor aproximado del nmero de cifras significativas se utiliza el psilon
de la mquina.
6maq = min {6 > O : 1 + 6 > 1}.
En la definicin anterior, la comparacin 1+6 > 1 no se hace en el sentido
matemtico estricto; se hace segn la interpretacin del computador, es
decir, muy probablemente para el computador, en lenguaje e, 1 + .001 >
1, pero 1 + 10-100 lo considera igual a 1. U na manera aproximada de
calcular 6 maq consiste en empezar con 6 = 1 e ir disminuyendo su valor
hasta que no se detecte diferencia entre 1 + 6 Y 1. El siguiente ejemplo
calcula una aproximacin de 6 maq cuando se trabaja con nmeros doble
precisin.

jj uso de typedef

#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include "misfunc.h"
#include <iostream.h>

typedef double numero;

numero epsMaq(void);
jj======================================
int maine)
{
cout" eps de la maquina "epsMaq()endl;
return O;

160
8.4. INCLUDE

}
11======================================
numero epsMaq(void)
{
II 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 1= divisor;
unoEps = uno+eps;
}
eps *= divisor;

return eps;
}

El resultado puede ser 2. 22045e-16. Esto indica que los nmeros doble
precisin utilizan aproximadamente 16 cifras significativas.
Si se desea calcular el psilon de la mquina usando nmeros de
precisin sencilla, basta con cambiar nicamente la lnea typedef, para
que quede

typedef float numero;

En este caso el resultado puede ser 1. 1920ge-07, lo que indica que


los nmeros de precisin sencilla utilizan aproximadamente siete cifras
significativas.

8.4 include
En un programa fuente, adems de las rdenes y controles corres-
pondientes al lenguaje C o C++, hay otras rdenes o directrices para el
preprocesador, quien las realiza antes de la compilacin. Las directrices
para el preprocesador, una nicamente por lnea, empiezan con # .

161
8. TEMAS VARIOS

Cuando aparece en el programa fuente #include <nombrearchivo>,


entonces el preprocesador reemplaza esta lnea por el archivo completo.
Su uso puede ser de dos formas:

#include <nombrearchivo>

#include "nombrearchivo"

En el primer caso, es un archivo de cabecera estndar o ha sido creado


por el programador, pero debe estar donde se encuentran los archivos
de cabecera.
En el segundo caso, el archivo debe estar en el directorio o carpeta de
trabajo, es decir, donde est el programa fuente. Si no est en la misma
carpeta donde est el programa fuente, entonces es necesario indicar la
direccin exacta del archivo. Generalmente el nombre de estos archivos
tiene al final . h o . hpp .
Cuando se trata de un proyecto pequeo, un archivo de cabecera
creado por el programador tiene generalmente los prototipos de las fun-
ciones y despus las definiciones de las funciones. Tambin puede tener
otras directrices para el preprocesador.
El siguiente es un ejemplo de un archivo de cabecera para una pe-
quea biblioteca creada por el programador. Supongamos que el nombre
de este archivo es mibibl.h.

double mine double a, double b);


double max( double a, double b);

double mine double a, double b)


{
II minimo de {a, b}

if( a <= b ) return a;


else return b;
}
11--------------------------------------
double max( double a, double b)
{
II maximo de {a, b}

162
8.4. INeLUDE

if( a >= b ) return a;


else return b;
}

El siguiente ejemplo, muy sencillo, calcula el mnimo y el mximo de


tres nmeros. Usa el archivo de cabecera mibibl.h.

II minimo y maximo de 3 numero s

#include <iostream.h>
#include "mibibl.h"

int mainO
{
double a, b, e;

cout"\n\n Minimo y maximo de 3 numeros.\n\n";


cout" entre los 3 numeros " ,.
cinabc;
couta" "b" "cendl;
cout" minimo "min(a, min(b, e) )endl;
cout" maximo = "max(a, max(b, e) )endl;
return O;
}

Para proyectos de mayor tamao, el archivo de cabecera, un archivo . h,


tiene nicamente los prototipos de las funciones. En otro archivo, un
archivo . e o . cpp, estn las definiciones de las funciones. Este ltimo,
cuando ya est depurado, se compila una sola vez y est listo para el
enlace o link. El resultado es un archivo . obj. El archivo donde est la
funcin main tiene un include para el archivo. h, no para el archivo don-
de estn las definiciones. As, cuando se compila el programa principal
(lo cual se hace muchas veces), ste incluye el archivo . h, muy pequeo,
y despus se hace el enlace con el .obj que est 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 def ine tiene dos usos. El primero sirve para definir
constantes. Por tradicin estas constantes se escriben en maysculas.
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 instruccin. 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 identificadorCidentificador, ... , identificador) cadena

El anterior esquema es poco diciente. Los dos ejemplos siguientes


muestran mejor el uso de define.

#include ...

#define CUADRADo(x) (x)*(x)


#define CUADRADoB(x) x*x
#define NORMA (x , y) (sqrtx)*(x)+(y)*(y)))

int mainO
{
double x 3.0, y 4.0;

coutCUADRADo(x)endl;
coutCUADRADoB(x)endl;

164
8.6. APUNTADORES A FUNCIONES

coutCUADRADO(x+y) endl;
coutCUADRADOB(x+y)endl;
coutNORMA(x, y)endl;
return O;
}

Los resultados producidos son:

9
9
49
19
5

En la definicin de CUADRADO, aparentemente, hay muchos parnte-


sis; parece ms 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 razn es la siguiente: cuando el compilador encuen-
tra CUADRADOB (x+y) , lo reemplaza por x+y*x+y, diferente de lo es-
perado, es decir de (x+y) * (x+y). Ahora es comprensible el resultado
19. Algunos autores recomiendan, por seguridad, empezar y terminar la
cadena con parntesis, como en NORMA. Entonces CUADRADO que-
dara as:

#define CUADRADO(x) x)*(x))

8.6 Apuntadores a funciones

Antes de ver exactamente la utilidad y la manera de usar los apun-


tadores a funciones, veamos un ejemplo de una funcin que efecta el
clculo aproximado de la integral definida por la frmula del trapecio.
Su uso se puede mejorar y generalizar por medio de apuntadores a fun-
ciones.
Sea

f = fU, a, b) = lb f(x) dx.

165
8. TEMAS VARIOS

El valor de 1 se puede aproximar as:

I", h ('~a) + ~ f(Xi) + f~)) , donde h


b- a
= --,
n
Xi
.
= a + zh.

Considere el siguiente programa:

II formula del trapecio para integrales,


II SIN apuntadores a funciones.

#include ...

double trapecioO( double a, double b, int n);


double f( double x);
double g( double x);
11======================================
int main()
{
double a, b;
int n;

cout"\n\n Calculo de la integral definida"


" por medio de la formula del trapecio\n\n";
cout" entre a b n ";
cinabn;
cout"\n\n integral "trapecioO(a, b, n);
return O;
}
11======================================
double trapecioO( double a, double b, int n)
{
II Calculo de la integral definida de la funcion f(x)
II en el intervalo [a,b] , utilizando n subintervalos.
II f(x) esta definida en la funcion f

double s, h;
int i;

i f ( n <= O ){

166
8.6. APUNTADORES A FUNCIONES

coutn\n\n trapecioO: ERROR: n nnendl;


return 0.0;
}
s = (f(a) + f(b))/2.0;
h (b-a)/n;
for( i = 1; i <= n-1; i++) s += f( a + i*h );
return s*h;
}
//------------------------------------------------
double f( double x)
{
return exp(-x*x);
}
//------------------------------------------------
double g( double x)
{
const double DOSPI = 6.283185307179586;

return exp(-x*x/2.0)/sqrt(DOSPI);
}

El programa de este ejemplo calcula una aproximacin de 1 para la


funcin definida en double f ( ... ), pero no puede calcular una apro-
ximacin de 1 para la funcin definida en double g ( ... ). De manera
natural se desea que uno de los parmetros de trapecioO sea la funcin.
Esto se logra mediante los apuntadores a funciones. Veamos, mediante
una modificacin del ejemplo anterior, su uso.

// formula del trapecio para integrales,


// CON apuntadores a funciones.

#include ...

double trapecio( double (*f) (double x), double a, double b,


int n);
double f1( double x);
double f2( double x);
//======================================
int mainO

167
8. TEMAS VARIOS

{
double a, b;
int n;

coutn\n\n Calculo de la integral definida n


n por medio de la formula del trapecio\n\nn;
coutn entre a b n: n;
cinabn;
coutn\n\n integral de fl - ntrapecio(fl, a, b, n);
coutn\n\n integral de f2 - ntrapecio(f2, a, b, n);
return O;
}
jj======================================
double trapecio(double (*f) (double x), double a, double b,
int n)
{
jj Calculo de la integral definida de la funcion f(x)
jj en el intervalo [a,b] , utilizando n subintervalos.
jj f(x) esta definida en la funcion f

double s, h;
int i;

i f ( n <= O ){
coutn\n\n trapecio: ERROR: n nnendl;
return 0.0;
}
s = ( (*f)(a) + (*f)(b) )j2.0;
h = (b-a)jn;
for( i = 1; i <= n-l; i++) s += (*f)( a + i*h );
return s*h;
}
jj------------------------------------------------
double fl( double x)
{
return exp(-x*x);
}
jj------------------------------------------------

168
8.7. FUNCIONES EN LNEA

double f2( double X)


{
const double DOSPI = 6.283185307179586;

return exp(-x*x/2.0)/sqrt(DOSPI);
}

Este ejemplo muestra las principales caractersticas del uso de los apun-
tadores a funciones. En la definicin de la funcin trapecio, un parme-
tro es un apuntador a funcin. El identificador est precedido de aste-
risco y aparece entre parntesis: (*f). Adems estn el tipo devuelto
por la funcin y los parmetros: double (*f) (double x). Esto impli-
ca que trapecio se puede usar para cualquier funcin que devuelva un
nmero doble precisin y que tenga un nico parmetro tipo doble pre-
cisin. Cuando se utiliza el apuntador dentro de trapecio para evaluar
la funcin en un valor especfico, tambin est precedido de asterisco y
encerrado entre parntesis: (*f) (a) .

8.7 Funciones en lnea


Cuando una funcin, por ejemplo la funcin main, llama a otra, hay
un pequeo incremento en el tiempo de ejecucin correspondiente al
llamado en s de la funcin y a la pasada de los parmetros. Este incre-
mento 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 funcin en
lnea en cada sitio del programa donde se utiliza la funcin. As, no hay
paso de parmetros y se gana en eficiencia, pero usualmente el programa
ejecutable resulta ms grande. Las funciones en lnea son aconsejables
para funciones pequeas, de una o dos instrucciones.
El ejemplo siguiente tiene dos partes. En la primera se hace uso de
la funcin cosGrd, funcin comn y corriente, que calcula el coseno,
cuando el ngulo est dado en grados. En la segunda parte se hace uso
de una funcin en lnea con el mismo objetivo.

// coseno de un angulo en grados,


// SIN funciones en linea.

169
8. TEMAS VARIOS

#include <math.h>
#include <iostream.h>

double cosGrd( double X);


11======================================
int mainO
{
double a;

cout"\n\n Calculo de cos(a) , a en grados.\n\n";


cout" a = ";
cina;
cout"\n\n cos("a") "cosGrd(a);
return O;
}
11======================================
double cosGrd( double x)
{
return cos(O.01745329251994*x);
}

II coseno de un angulo en grados,


II CON una funcion en linea.

#include <math.h>
#include <iostream.h>

inline double cosGrd(double x)return cos(.017453292519*x);}


11======================================
int maine)
{
double a;

cout"\n\n Calculo de cos(a), a en grados.\n\n";


cout" a = tI;
cina;
cout"\n\n cos("a") "cosGrd(a);

170
8.8. ARGUMENTOS DE LA FUNCIN MAIN

return O;
}

Es usual que una funcin en lnea est escrita en una nica lnea, pero
no es obligatorio. La funcin en lnea cosGrd se hubiera podido escribir
as:

inline double cosGrd(double x)


{
II calculo del coseno de un angulo en grados

return cos(0.0174532925199433*x);
}

Otro ejemplo de una funcin en lnea puede ser el siguiente, que calcula
el mximo entre dos nmeros doble precisin.

inline double max(double x, double y)


{
if( x >= y ) return x;
el se return y;
}

En varios libros el ejemplo clsico de funciones en lnea corresponde a


una funcin que hace el mismo trabajo que la anterior, pero est escrita
de una forma mucho ms compacta. El lector interesado debe consultar
en un manual de e sobre el uso del operador ?, pues esta funcin hace
uso de l.

inline double max(double x, double y){returnx>y) ? x:y);}

8.8 Argumentos de la funcin main

Hasta ahora se haba supuesto que la funcin main no tena argu-


mentos. En realidad, s puede tenerlos. Estos argumentos se usan en la
lnea de comandos donde se da la orden de ejecucin al programa; por
ejemplo en DOS o en Unix.
Supongamos que el programa se llama prog28. Normalmente, pa-
ra comenzar la ejecucin del programa, es necesario digitar prog28 y

171
8. TEMAS VARIOS

despus oprimir la tecla Enter. Supongamos adems que, empezando el


programa, ste pregunta por el nombre del archivo de datos y el nombre
del archivo para resultados. En lugar de hacer lo anterior, se puede escri-
bir enseguida de prog28, antes de oprimir Enter, el nombre del archivo
de datos y el nombre del archivo para los resultados; por ejemplo,

prog28 caso1.dat result

Los parmetros para main son argc y argv. El primero es de tipo ente-
ro y sirve para contar el nmero 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 resul t hay tres palabras. El parme-
tro 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.

II prog28
II Parametros en la linea de comandos,
II uso de argc, argv

#include ...

int maine int argc, char *argv[])


{
FILE *archDat, *archResj

i f ( argc ! = 3 ){
cout"ERROR: el llamado debe ser:\n"
"progr28 nombre_arch_datos nombre_arch_result"
endlj
exit(1) j
}

archDat = fopen(argv[1] , "r");


if( archDat == NULL ){
printf("\n\n Archivo inexistente.\n\n")j
exit(1) j
}

172
8.8. ARGUMENTOS DE LA FUNCIN MAIN

archRes = fopen(argv[2] , "'iN");


if( archRes == NULL ){
printf("Nombre de archivo de resultados erroneo.\n");
exit(1) ;
}

fclose(archDat);
fclose(archRes);
return O;
}

Como argv es un arreglo de cadenas, entonces empieza en el subndice


cero. Supongamos que el llamado se hace

prog28 casol.dat result

entonces la primera palabra en la lnea de comandos ser argv [O], o


sea la cadena "prog28". La segunda palabra en la lnea de comandos,
la cadena" caso!. dat", quedar almacenada en argv [1] y finalmente
la cadena "result" quedar almacenada en argv[2].
Otros temas de C que no se presentan en este libro son: enumera-
ciones, uniones, el operador ?, static, externo El lector interesado
podr encontrarlos en un manual de C y C++.

173
8.8. ARGUMENTOS DE LA FUNCIN MAIN

archRes = fopen(argv[2] , "'iN");


if( archRes == NULL ){
printf("Nombre de archivo de resultados erroneo.\n");
exit(1) ;
}

fclose(archDat);
fclose(archRes);
return O;
}

Como argv es un arreglo de cadenas, entonces empieza en el subndice


cero. Supongamos que el llamado se hace

prog28 casol.dat result

entonces la primera palabra en la lnea de comandos ser argv [O], o


sea la cadena "prog28". La segunda palabra en la lnea de comandos,
la cadena" caso!. dat", quedar almacenada en argv [1] y finalmente
la cadena "result" quedar almacenada en argv[2].
Otros temas de C que no se presentan en este libro son: enumera-
ciones, uniones, el operador ?, static, externo El lector interesado
podr encontrarlos en un manual de C y C++.

173
9

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 Un ejemplo con complejos


El siguiente ejemplo define una estructura para los nmeros comple-
jos. Tiene dos elementos: la parte real y la parte imaginaria.

struct complejo {
double pReal; II parte real
double plmag; II parte imaginaria
};

La palabra clave struct dice que se trata de una estructura. La palabra


complejo es el nombre de este nuevo tipo de estructura (o simplemente
tipo de dato). Siguiendo con el ejemplo, ahora es permitido:

struct complejo z, w, c;

La instruccin anterior es de C y es reconocible por cualquier compilador


de C o de C++. En compiladores modernos de C++ se puede escribir
sencillamente:

complejo z, w, c;

175
9. ESTRUCTURAS

Para tener acceso a un elemento de una variable del tipo de la nueva


estructura es necesario dar el nombre de la variable seguido de punto y
del nombre del elemento; por ejemplo, z. plmag. El siguiente programa
muestra realiza el producto de dos complejos.

II Estructuras, ejemplo con complejos.


11------------------------------------------------
#include <stdlib.h>
#include <stdio.h>
11------------------------------------------------
struct complejo {
double pReal; II parte real
double plmag; II parte imaginaria
};
11================================================
int mainC void )
{
complejo z, w, c,

z.pReal 1.0;
z.plmag 1.0;

w.pReal 1.0;
w.plmag -1.0;

c.pReal z.pReal*w.pReal - z.plmag*w.plmag;


c.plmag z.pReal*w.plmag + z.plmag*w.pReal;

printf (" parte real = %lf parte imag. %lf\n" ,


c.pReal, c.plmag);
return O;
}

Una vez definida una estructura, sta puede servir para describir un
parmetro de una funcin, para declarar arreglos cuyos elementos sean
estructuras, para declarar apuntadores, para asignar memoria dinmi-
camente, para que una funcin devuelva una estructura.
El siguiente ejemplo usa la estructura complejo definida anterior-
mente. El programa lee en un archivo el valor de n. Asigna dinmica-

176
9.1. UN EJEMPLO CON COMPLEJOS

mente 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.

II Estructuras pasadas como parametros,


II arreglos de estructuras,
II funciones que devuelven una estructura.
11------------------------------------------------
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
11------------------------------------------------
struct complejo {
double pReal; II parte real
double pImag; II parte imaginaria
};
11------------------------------------------------
complejo prodCompl( complejo zl, complejo z2);
int flectXCompl(FILE *arch, complejo *x, int n);
double normaCompl(complejo x);
complejo complMaxNorma(complejo *x, int n);
11================================================
int maine void )
{
II Lee en un archivo n.
II Lee en el archivo n complejos. Para leer un
II complejo lee la parte real y la parte imaginaria.
II Busca el complejo de mayor norma y escribe su
II cuadrado.

complejo *z, w;
int n, resLect;
FILE *archDat;
char nombre [51] ;

printf("\n Nombre del archivo con los datos: 11);


gets(nombre);

177
9. ESTRUCTURAS

archDat = fopen(nombre, "r");


if( archDat == NULL ){
printf("\n\n Archivo inexistente.\n\n");
exit(1) ;
}

fscanf (archDat, "%d", &n);


z = new complejo[n];
i f ( z == NULL ){
printf("\n\n Memoria insuficiente.\n\n");
exit (1) ;
}

resLect = flectXCompl(archDat, z, n);


if( resLect != 1 ){
printf(" ERROR leyendo archivo.\n");
exit(1) ;
}

w = complMaxNorma(z, n);
printf(" parte real = %lf parte imag. %lf\n",
w.pReal, w.plmag);

w = prodCompl(w, w);
printf (" parte real = %lf parte imag. %lf\n" ,
w.pReal, w.plmag);
return O;
}
11================================================
complejo prodCompl( complejo zl, complejo z2)
{
II producto de dos complejos

complejo z3;

z3.pReal zl.pReal*z2.pReal - zl.plmag*z2.plmag;


z3.plmag zl.pReal*z2.plmag + zl.plmag*z2.pReal;

178
9.1. UN EJEMPLO CON COMPLEJOS

return z3;
}
11------------------------------------------------
int flectXCompl(FILE *arch, complejo *x, int n)
{
II Lectura en un archivo de los primeros n
II elementos de un arreglo complejo x.

II Devuelve 1 si se efectuo la lectura normalmente,


II O si se encontro fin de archivo antes
II de acabar la lectura,
II -1 si hubo un error durante la lectura
II con fscanf.

int i, res;

for(i=O; i< n; i++){


res = fscanf(arch, "%lf", &x[i] .pReal);
if( feof(arch) ) return O;
if( res <= O ) return -1;
res = fscanf(arch, "%lf", &x[i] .plmag);
if( feof(arch) ) return O;
if( res <= O ) return -1;
}
return 1;
}
11------------------------------------------------
complejo complMaxNorma(complejo *x, int n)
{
II Devuelve el complejo de maxima norma
II en el arreglo de complejos x.

double normaMax = 0.0, normai;


int i, imax -1;

for( i=O; i < n; i++){


normai = normaCompl( x[i] );
i f ( normai > normaMax ) {

179
9. ESTRUCTURAS

imax i;
normaMax = normai;
}
}
return x[imax];
}
11------------------------------------------------
double normaCompl(complejo X)
{
II Norma del complejo x

return sqrt(x.pReal*x.pReal + x.plmag*x.plmag);


}

Una vez definida la estructura complejo, sta se puede usar de varias


maneras. En el programa anterior se observa:

Los parmetros de las funciones pueden ser del tipo complejo:


funciones flectXCompl, normaCompl, complMaxNorma, prodCompl.

Las funciones pueden devolver un complejo: funciones prodCompl,


complMaxN orma.

La variable z en la funcin main es un apuntador a complejo. Un


parmetro de la funcin flectXCompl es un apuntador a complejo.

En la funcin main, utilizando z, apuntador a complejo, se ha-


ce una asignacin dinmica de memoria para n elementos tipo
complejo.

En la funcin flectXCompl el segundo parmetro, x, es un "vec-


tor" de elementos tipo complejo. Para el i-simo elemento, el
complejo x[i], su parte real es x[i] .pReal y su parte imaginaria
es x [i] . plmag.

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 funcin normaCompl anterior, se reescribe a
continuacin utilizando -> .

180
9.2. UN EJEMPLO TPICO

double normaComplb(complejo X)
{
II Norma del complejo x

complejo *w;

w = &x;
return sqrt(w->pReal*w->pReal + w->plmag*w->plmag);
}

9.2 Un ejemplo tpico


En muchos libros de e el ejemplo tpico de estructura es semejan-
te al siguiente. Corresponde a la informacin de un empleado de una
compaa.
struct empleado{
char nombres[20];
char apell[20]; II apellidos
char docldent; II clase de documento de identidad
int numldent; II numero de doc. identidad
char dirLinl[30]; II primera linea de la direccion
char dirLin2[30]; II segunda linea de la direccion
char CiudDept[30]; II ciudad y departamento
char tel[10]; II numero de telefono
char dirElec[30]; II direccion electronica: e-mail
float sueldo;
char fechaNac[8]; II fecha de nacimiento
char fechalng[8] ; II fecha de ingreso
char cargo [20] ;
};

Ejercicios
Los ejercicios de este captulo se pueden hacer definiendo explci-
tamente una estructura por medio de struct, o sin su uso. Haga o
estudie las dos alternativas y detecte ventajas y desventajas.

181
9. ESTRUCTURAS

9.1 Defina una estructura para el manejo de nmeros fraccionarios y


haga funciones para:
simplificar,
sumar,
multiplicar,
restar,
dividir,
suma de las coordenadas (fraccionarias) de un vector,
producto de las coordenadas (fraccionarias) de un vector,
En todos los casos controle que numerador y denominador perma-
necen dentro de los rangos permitidos.

9.2 Un grafo se puede representar por una lista de vrtices y una lista
de arcos. U na 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,
quitar un vrtice de la lista de arcos,
quitar un vrtice de la lista de arcos y de la lista de vrtices,
modificar un costo,
buscar si un arco existe,
dada una sublista de vrtices, averiguar si es un camino,
calcular su costo.

182
10

Algunas funciones
elementales

En este captulo hay algunas funciones elementales que sern tiles


especialmente para el manejo de matrices, en particular para la solucin
de sistemas de ecuaciones. Sean x, y vectores (cuando sea necesario se
consideran como matrices columna), a, k escalares. La tabla siguiente
muestra el nombre de la funcin y su efecto. Se usa la misma convencin
de C, el signo igual indica asignacin.
prodXY producto xTy
1
dist2 Ilx - yl12 = (~=1 (Xi - Yi)2) "2
alfaX X = ax
xMasAlfaY x=x+ay
xIgIY x=y
xIglAlfY X = ay
xIgIK X = k, es decir, Xi = k Vi
intercXY intercambio de x, Y
maxX maxi{Xi}
maxXPos maxi { Xi} e indica la posicin
maxAbsX maxi{lxil}
maxAbsXPos maxi{lxil} e indica la posicin
ordBurb ordenar, de menor a mayor, los Xi

Para cada una de ellas, est la versin sin saltos y la versin con
saltos. Utilizando la sobrecarga de funciones permitida por C++, las
dos versiones tienen el mismo nombre.

183
10. ALGUNAS FUNCIONES ELEMENTALES

10.1 Cdigo de algunas funciones

A continuacin se presenta el cdigo en C (y algo de C++) de las


funciones para vectores almacenados de manera consecutiva (sin sal-
to). Para vectores almacenados con salto, es decir, en x[O], x[salto] ,
x [2*salto], ... , x [Cn-l) *salto], est el cdigo completo de algunas de
ellas. El cdigo de las dems se puede obtener en la pgina del autor.
Actualmente la direccin es: www.matematicas.unal.edu.co/-hmora/.
Si hay reorganizacin de las pginas de la Universidad, ser necesario
entrar a la pgina de la Universidad www . unal. edu. co ir a Sede de Bo-
got, Facultad de Ciencias, Departamento de Matemticas y pgina del
autor.

double prodXYCdouble *x, double *y, int n);


double prodXYCdouble *x, int saltox, double *y, int saltoy,
int n);

double dist2Cdouble *x, double *y, int n);


double dist2Cdouble *x, int saltox, double *y, int saltoy,
int n);

void alfaXCdouble alfa, double *x, int n);


void alfaXCdouble alfa, double *x, int salto, int n);

void xMasAlfaYCdouble *x, double alfa, double *y, int n);


void xMasAlfaYCdouble *x, int saltox, double alfa,
double *y, int saltoy, int n);

void xIgIKCdouble *x, int n, double k);


void xIgIKCdouble *x, int salto, int n, double k);

void xIgIYCdouble *x, double *y, int n);


void xIgIYCdouble *x, int saltox, double *y, int saltoy,
int n);

void xIgIAlfYCdouble *x, double alfa, double *y, int n);


void xIgIAlfYCdouble *x, int saltox, double alfa,
double *y, int saltoy, int n);

184
10.1. CDIGO DE ALGUNAS FUNCIONES

void intercXY(double *x, double *y, int n);


void intercXY(double *x, int saltox, double *y, int saltoy,
int n);

double maxX(double *x, int n);


double maxX(double *x, int salto, int n);

double maxXPos(double *x, int n, int &posi);


double maxXPos(double *x, int salto, int n, int &posi);

double maxAbsX(double *x, int n);


double maxAbsX(double *x, int salto, int n);

double maxAbsXPos(double *x, int n, int &posi);


double maxAbsXPos(double *x, int salto, int n, int &posi);

void ordBurb(double *x, int n);


void ordBurb(double *x, int salto, int n);

11------------------------------------------------
double prodXY(double *x, double *y, int n)
{
II producto "interno" x.y

double s = 0.0;
double *pxi, *pyi, *pxn;

pxi x,
pyi y;
pxn x + n;
while( pxi < pxn ) s += (*pxi++)*(*pyi++);
return s;
}
11------------------------------------------------
double dist2(double *x, double *y, int n)
{
II distancia euclideana (Holder, orden 2) entre x y

double s = 0.0;

185
10. ALGUNAS FUNCIONES ELEMENTALES

double *pxi, *pyi, *pxn, xiyi;

pxi X;
pyi y;
pxn X + n;
whileC pxi < pxn ){
xiyi = C*pxi++) - C*pyi++);
S += xiyi*xiyi;
}
return sqrt(s);
}
11---------------------------------------------------------
void alfaXCdouble alfa, double *x, int n)
{
II X alfa * x

double *pxi, *pxn;

pxi = x;
pxn = x + n;
whileC pxi < pxn ) *pxi++ *= alfa;
}
11---------------------------------------------------------
void xMasAlfaYCdouble *x, double alfa, double *y, int n)
{
II x x + alfa * y

double *pxi, *pxn, *pyi;

pxi x;
pyi y;
pxn x + n;
whileC pxi < pxn ) *pxi++ += alfa*C*pyi++);
}
11---------------------------------------------------------
void xIglKCdouble *x, int n, double k)
{
II x = k

186
10.1. CDIGO DE ALGUNAS FUNCIONES

double *pxi, *pxn;

pxi = X;
pxn = X + n;
while( pxi < pxn ) *pxi++ = k;
}
11---------------------------------------------------------
void xIglY(double *x, double *y, int n)
{
II X = Y

double *pxi, *pxn, *pyi;

pxi x;
pyi y;
pxn X + n;
while( pxi < pxn ) *pxi++ = *pyi++;
}
11---------------------------------------------------------
void xIglAlfY(double *x, double alfa, double *y, int n)
{
II X = alfa * y

double *pxi, *pxn, *pyi;

pxi x;
pyi y;
pxn X + n;
while( pxi < pxn ) *pxi++ = alfa*(*pyi++);
}
11---------------------------------------------------------
void intercXY(double *x, double *y, int n)
{
II intercambiar x y

double *pxi, *pxn, *pyi, t;

187
10. ALGUNAS FUNCIONES ELEMENTALES

pxi x;
pyi y;
pxn = x + n;
while( pxi < pxn ){
t = *pxi;
*pxi++ *pyi;
*pyi++ = t;
}
}
11---------------------------------------------------------
double maxX(double *x, int n)
{
II maximo xi

double *pxi, *pxn, maxi -1. OE100, xi;

pxi = x;
pxn = x + n;
while( pxi < pxn ){
xi = *pxi++;
if( xi > maxi ) maxi xi;
}
return maxi;
}
11---------------------------------------------------------
double maxXPos(double *x, int n, int &posi)
{
II maximo xi
II posi contendra la posicion del maximo

double *pxi, *pxn, maxi -1.0E100, xi;


int i;

posi = -1;
pxi = x;
pxn = x + n;
i = O;
while( pxi < pxn ){

188
10.1. CDIGO DE ALGUNAS FUNCIONES

xi = *pxi++;
if ( xi > maxi ){
maxi xi;
posi = i;
}
i++;
}
return maxi;
}
11---------------------------------------------------------
double maxAbsX(double *x, int n)
{
II maximo Ixil

double *pxi, *pxn, maxi 0.0, axi;

pxi = x;
pxn = x + n;
while( pxi < pxn ){
axi = fabs(*pxi++);
if( axi > maxi ) maxi axi;
}
return maxi;
}
11---------------------------------------------------------
double maxAbsXPos(double *x, int n, int &posi)
{
II maximo Ixil
II posi contendra la posicion del maximo valor abs.

double *pxi, *pxn, maxi = 0.0, axi;


int i;

posi = -1;
pxi = x;
pxn = x + n;
i = O;
while( pxi < pxn ){

189
10. ALGUNAS FUNCIONES ELEMENTALES

axi = fabs(*pxi++);
if( axi > maxi ){
maxi axi;
posi = i;
}
i++;
}
return maxi;
}

10.2 Versiones con saltos


double dist2(double *x, int saltox, double *y, int saltoy,
int n)
{
II distancia euclideana (Holder, orden 2 ) entre x, y
II
II x[O], x [saltox], x [2*saltox], ... , x [(n-1) *saltox]
II y[O], y [saltoy], y [2*saltoy], ... , y [(n-1) *saltoy]
double s = 0.0;
double *pxi, *pyi, *pxn, *pyn, xiyi;

if( n < O ){
printf("dist2: n negativo\n");
return 0.0;
}
if( n==O ) return 0.0;

if( saltox == 1 ){
if( saltoy == 1 ){
II saltox = saltoy 1
pxi = x;
pxn = x + n;
pyi = y;
while( pxi < pxn ){
xiyi = (*pxi++) - (*pyi++);
s += xiyi*xiyi;

190
10.2. VERSIONES CON SALTOS

}
}
else{
II 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 ){
II saltox > 1; saltoy 1
pyi y;
pyn y + n;
pxi x;
while( pyi < pyn ){
xiyi = (*pxi) - (*pyi++);
s += xiyi*xiyi;
pxi += saltox;
}
}
else{
II 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. ALGUNAS FUNCIONES ELEMENTALES

}
return sqrt(s);
}
11---------------------------------------------------------
void alfaX(double alfa. double *x. int salto. int n)
{
II x = alfa * x
II x en x[O]. x[salto]. x[2*salto] ... x[(n-l)*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;
}
}
}
11------------------------------------------------
void xMasAlfaY(double *x. int saltox. double alfa.
double *Y. int saltoy. int n)
{
II x = x + alfa y
II x[O]. x[saltox]. x[2*saltox]. ... , x [(n-1) *saltox]
II y[O]. y[saltoy]. y[2*saltoy]. ... , y[(n-l)*saltoy]

II uso de apuntadores

double *pxi. *pyi. *pxn. *pyn;

if( n < O ){

192
10.2. VERSIONES CON SALTOS

printf("xMasAlfaY: n negativo\n");
return;
}
if( n==O ) return;

if( saltox -- 1 ){
if( saltoy == 1 ){
II saltox = saltoy 1
pxi x;
pxn x + n;
pyi y;
while( pxi < pxn ) *pxi++ += alfa*(*pyi++);
}
else{
II saltox = 1; saltoy != 1
pxi x;
pxn = x + n;
pyi = y;
while( pxi < pxn ){
*pxi++ += alfa*(*pyi);
pyi += saltoy;
}
}
}
else{
if( saltoy == 1 ){
II saltox > 1; saltoy 1
pyi y;
pyn y + n;
pxi x;
while( pyi < pyn ){
*pxi += alfa*(*pyi++);
pxi += saltox;
}
}
else{
II saltox != 1; saltoy != 1
pxi = x;

193
10. ALGUNAS FUNCIONES ELEMENTALES

pxn = X + n*saltox;
pyi = y;
while( pxi < pxn ){
*pxi += alfa*(*pyi);
pxi += saltox;
pyi += saltoy;
}
}
}
}

10.3 Mtodo burbuja

Para ordenar un arreglo, supongamos en orden creciente, existen


numerosos mtodos. Uno de ellos es el mtodo burbuja, el cual cuenta
con una buena combinacin de sencillez y eficiencia para arreglos no
muy grandes.
Supongamos que se tiene un vector x E ]Rn. En una primera itera-
cin (primera pasada) se mira si Xl, x2 estn ordenados; si no lo estn
se intercambian. Despus se mira X2 Y X3; si no estn ordenados se
intercambian. Despus se mira X3 Y X4; si no estn ordenados se inter-
cambian. Finalmente, si Xn-l Y X n no estn ordenados, se intercambian.
Por convencin, Xi indica el i-simo elemento de X despus de la ltima
modificacin. Despus de esta primera pasada el mayor elemento queda
en la ltima posicin.
En una segunda pasada se hace un proceso semejante, pero la ltima
pareja que se compara es X n -2, Xn-l. Al final de esta segunda pasada
los dos ltimos elementos estn bien ordenados (en sus posiciones defi-
nitivas).
En una tercera pasada se repite el proceso, pero la ltima pareja que
se compara es X n -3, X n -2. Al final de esta tercera pasada los tres ltimos
elementos estn bien ordenados.
Si en una pasada no hay intercambios, el vector est ordenado.

Considere

X = (6, -1, 14,0,1,2)

194
10.3. MTODO BURBUJA

Como 6 Y -1 no estn ordenados, se intercambian.

x = (-1,6,14,0,1,2)

Como 6 Y 14 estn ordenados, no se hace nada.

x = (-1,6,14,0,1,2)

Como 14 Y no estn ordenados, se intercambian.

x = (-1,6,0, 14, 1,2)

Como 14 Y 1 no estn ordenados, se intercambian.

x = (-1,6,0,1,14,2)

Como 14 Y 2 no estn ordenados, se intercambian.

x = (-1,6,0,1,2,14)

Al final de esta primera pasada el elemento mayor qued en la ltima


posicin.

Segunda pasada. Como -1 y 6 estn ordenados, no se hace nada.

x = (-1,6,0,1,2,14)

Como 6 y no estn ordenados, se intercambian.

x = (-1,0,6,1,2,14)

Como 6 y 1 no estn ordenados, se intercambian.

x = (-1,0,1,6,2,14)

Como 6 y 2 no estn ordenados, se intercambian.

x= (-1,0,1,2,6,14)

Finalizada esta segunda pasada, 6 y 14 estn en sus posiciones definiti-


vas.

Tercera pasada. Como -1 y estn ordenados, no se hace nada.

x = (-1,0,1,2,6,14)

195
10 ALGUNAS FUNCIONES ELEMENTALES

Como
y 1 estn ordenados, no se hace nada.

x = (-1,0,1,2,6,14)

Como 1 Y 2 estn ordenados, no se hace nada.

x = (-1,0,1,2,6,14)

En esta tercera etapa no hubo cambios, luego el vector est ordenado.

void ordBurb(double *x, int n)


{
II ordena, de manera creciente, el vector x
II por el metodo burbuja

int nCamb, m;
double *pxi, *pxi1, *pxm, t;

for( m = n-1; m >= O; m--){


nCamb = O;
pxi = x;
pxil = x + 1;
pxm = x + m;
while( pxi < pxm ){
if( *pxi > *pxi1 ){
t = *pxi;
*pxi++ = *pxil;
*pxi1++ = t;
nCamb++;
}
else{
pxi++;
pxil++;
}
}
if( nCamb O ) return;
}
}

196
10.3. MTODO BURBUJA

Ejercicios
Los ejercicios de este captulo no estn enfocados directamente a los
temas tratados en l; ms bien, corresponden a varios temas y aparecen
aqu por tratarse del ltimo captulo sobre C.

10.1 Haga un programa que escriba en un archivo todas las combina-


ciones de enteros entre 1 y n.

10.2 Elabore un programa que escriba en un archivo todas las permu-


taciones de los enteros entre 1 y n.

10.3 Dado un entero n > O Y 2n enteros UI :S VI, U2 :S V2, ... , Un :S V n ,


escriba todas la n-uplas (il, i2, ... , in) tales que Uk :S ik :S Vk para
todo k.

10.4 Utilice el ejercicio anterior para resolver por la "fuerza bruta" (es-
tudio de todas las posibilidades) el problema del morral con cotas
inferiores y superiores. Sean n un entero positivo; e, PI, P2, ... ,
Pn, bl, b 2 , ... , bn nmeros positivos; UI :S VI, U2 :S V2, ... , Un :S V n
enteros positivos. Encontrar enteros Xl, X2, ... , X n para resolver el
siguiente problema de maximizacin con restricciones:

max blXI+ b2X2 + ... + bnxn


PIXI + P2 X 2 + ... + PnXn :S e

Ui:S Xi:S Vi, i = 1,2, ... ,n.

197
10.3. MTODO BURBUJA

Ejercicios
Los ejercicios de este captulo no estn enfocados directamente a los
temas tratados en l; ms bien, corresponden a varios temas y aparecen
aqu por tratarse del ltimo captulo sobre C.

10.1 Haga un programa que escriba en un archivo todas las combina-


ciones de enteros entre 1 y n.

10.2 Elabore un programa que escriba en un archivo todas las permu-


taciones de los enteros entre 1 y n.

10.3 Dado un entero n > O Y 2n enteros UI :S VI, U2 :S V2, ... , Un :S V n ,


escriba todas la n-uplas (il, i2, ... , in) tales que Uk :S ik :S Vk para
todo k.

10.4 Utilice el ejercicio anterior para resolver por la "fuerza bruta" (es-
tudio de todas las posibilidades) el problema del morral con cotas
inferiores y superiores. Sean n un entero positivo; e, PI, P2, ... ,
Pn, bl, b 2 , ... , bn nmeros positivos; UI :S VI, U2 :S V2, ... , Un :S V n
enteros positivos. Encontrar enteros Xl, X2, ... , X n para resolver el
siguiente problema de maximizacin con restricciones:

max blXI+ b2X2 + ... + bnxn


PIXI + P2 X 2 + ... + PnXn :S e

Ui:S Xi:S Vi, i = 1,2, ... ,n.

197
11

Solucin de sistemas
lineales

Uno de los problemas numricos ms frecuentes, o tal vez el ms


frecuente, consiste en resolver un sistema de ecuaciones de la forma

Ax=b (11.1)

donde A es una matriz cuadrada, de tamao n x n, invertible. Esto quiere


decir que el sistema tiene una nica solucin.
Se trata de resolver un sistema de ecuaciones de orden mucho mayor
que 2. En la prctica se pueden encontrar sistemas de tamao 20, 100,
1000 o mucho ms grandes. Puesto que se trata de resolver el sistema
con la ayuda de un computador, entonces las operaciones realizadas
involucran errores de redondeo o truncamiento. La solucin obtenida no
es absolutamente exacta, pero se desea que la acumulacin de los errores
sea relativamente pequea o casi despreciable.

11.1 Notacin

Sean A una matriz m x n, con elementos aij, i = 1, ... m, j = 1, ... , n


yx = (X,X2, ... ,xn ). Para denotar filas o columnas, o partes de ellas, se

199
11. SOLUCIN DE SISTEMAS LINEALES

usar la notacin de Matlab y Scilab.

parte de un vector: x(5 : 7) = (X5, X6, X7),


fila i-sima: A. = A(i, :),
columna j-sima: A. j = A(:,j),
parte de la fila i-sima: A(i,l : 4) = [ail ai2 ai3 ai4]
parte de la columna j-sima: A(2 : 4, j) = [a2j a3j a4j]T
submatriz: A(3 : 6,2 : 5) .

Supongamos que se tiene una funcin, llamada prodEsc, que calcula el


producto escalar entre dos vectores (del mismo tamao), o entre dos filas
de una matriz, o entre dos columnas, o entre una fila y una columna.
Supongamos que se tiene una funcin, llamada xMasAlfaY, que a
un vector le suma a veces otro vector. Los valores del primer vector
desaparecen y quedan los correspondientes al resultado

xMasAlfaY(u, 3.5, v) U f- U + 3.5v


Esta funcin tambin trabaja para filas o columnas de una matriz.

11.2 Mtodos ingenuos


Tericamente, resolver el sistema Ax = b es equivalente a la expresin

x = A-lb.

Es claro que calcular la inversa de una matriz es mucho ms dispendioso


que resolver un sistema de ecuaciones; entonces, este camino slo se
utiliza en deducciones tericas o, en muy raros casos, cuando A- l se
calcula muy fcilmente.
Otro mtodo que podra utilizarse para resolver Ax = b es la regla
de Cramer. Para un sistema de orden 3 las frmulas son:

a12 13 bl 13
[ bl
det b2 a22 aa23 ] [ a11
b2 a ]
det a21 a23
b3 a32 a33 a31 b3 a33
Xl =
det(A)
X2 = det(A)

200
11.2. MTODOS INGENUOS

det [:~~ :~~ :~ 1


a31 a32 b3
X3 = _ _ _ _--,---,----_ _0-
det(A)
Supongamos ahora que cada determinante se calcula por medio de co-
factores. Este clculo se puede hacer utilizando cualquier fila o cualquier
columna; por ejemplo, si A es 3 x 3, utilizando la primera fila,

En general, sea M ij la matriz (n - 1) x (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) = au det(Mu ) - a12 det(M12) + . " + (-l)(1+ n )al n det(M1n ).


Sea J.Ln el nmero de multiplicaciones necesarias para calcular, por co-
factores, el determinante de una matriz de orden n. La frmula anterior
nos indica que
J.Ln > nJ.Ln-l
Como a su vez J.Ln-l > (n -1)J.Ln-2 Y J.Ln-2 > (n - 2)J.Ln-3, ... , entonces

J.Ln > n(n - l)(n - 2) ... J.L2 = n(n - l)(n - 2) ... 2,


J.Ln > n!.

Para resolver un sistema de ecuaciones por la regla de Cramer, hay que


calcular n + 1 determinantes, luego el nmero total de multiplicaciones
necesarias para resolver un sistema de ecuaciones por la regla de Cramer,
calculando los determinantes por cofactores, es superior a (n + 1)!.

Tomemos un sistema, relativamente pequeo, n = 20,

21! = 5.1091E19.

Siendo muy optimistas (sin tener en cuenta las sumas y otras operacio-
nes concomitantes), supongamos que un computador del ao 2000 hace
1000 millones de multiplicaciones por segundo. Entonces, el tiempo ne-
cesario para resolver un sistema de ecuaciones de orden 20 por la regla
de Cramer y el mtodo de cofactores es francamente inmanejable:

tiempo > 5.1091ElO segundos = 16.2 siglos.


,'' '
201
11. SOLUCIN DE SISTEMAS LINEALES

11.3 Sistema diagonal


El caso ms sencillo de (11.1) corresponde a una matriz diagonal.
Para matrices triangulares, en particular para las diagonales, el determi-
nante 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 solucin de un sistema diagonal se obtiene mediante


b . = 1, ... , n.
Xi = -~ , '1, (11.2)
aii

Como los elementos diagonales son no nulos, no hay ningn problema


para efectuar las divisiones.

11.4 Sistema triangular superior


Resolver un sistema triangular superior (A es triangular superior) es
muy sencillo. Antes de ver el algoritmo en el caso general, veamos, por
medio de un ejemplo, cmo se resuelve un sistema de orden 4.
Ejemplo 11.1. Resolver el siguiente sistema:

4x + 3X2 - 2X3 + X4 4
-0.25x2 + 2.5x3 + 4.25x4 -11
45x3 + 79x4 - 203
2.8x4 -5.6
De la cuarta ecuacin, se deduce que X4 = -5.6/2.8 = -2. A partir de
la tercera ecuacin

45x3 -203 - (79x4)


-203 - (79x4)
X3
45
Reemplazando X4 por su valor, se obtiene X3 -1. A partir de la
segunda ecuacin

-0. 25x2 -11 - (2.5x3 + 4.25x4)

~ X3
-11 - (2.5x3 + 4.25x4)
-0.25

" 202
11.4. SISTEMA TRIANGULAR SUPERIOR

Reemplazando X3 Y X4 por sus valores, se obtiene X2 = O. Finalmente,


utilizando la primera ecuacin,

4 - (3X2 - 2X3 + X4)


4 - (3X2 - 2X3 + X4)
4
Reemplazando X2, X3 Y X4 por sus valores, se obtiene Xl = 1. <>

En general, para resolver un sistema triangular, primero se calcula


Xn = bnjann Con este valor se puede calcular Xn-l, Y as sucesivamente.
Conocidos los valores Xi+l, Xi+2, ... , Xn , la ecuacin i-sima es

+ ai,i+lxi+l + ai,i+2 x i+2 + ... + ainXn = bi ,


aiixi
+ prodEsc(A(i, i + 1 : n), x(i + 1 : n)) = bi ,
aiixi
b - prodEsc(A(i, i + 1 : n), x(i + 1 : n))
Xi= i --~~----~~~----~~~------~
aii
Como se supone que A es regular (invertible o no singular), los elemen-
tos diagonales son no nulos y no se presentan problemas al efectuar la
divisin.

El esquema del algoritmo es el siguiente:

Xn = bnjann
para i = n - 1, ... , 1
Xi = (b i - prodEsc(A(i,i + 1: n),x(i + 1: n)))jaii
fin-para

Si los subndices de A y de X van desde O hasta n-1, entonces el esquema


del algoritmo queda as:

Xn-l = bn-Ijan-l,n-l
para i=n-2, ... ,0
Xi = (bi - prodEsc(A(i,i + 1: n -l),x(i + 1: n -l)))jaii
fin-para

11.4.1 N mero de operaciones


U na de las maneras de medir la rapidez o lentitud de un mtodo
es mediante el conteo del nmero de operaciones. Usualmente se tienen

203
11. SOLUCIN DE SISTEMAS LINEALES

en cuenta las sumas, restas, multiplicaciones y divisiones entre nmeros


de punto flotante, aunque hay ms operaciones fuera de las anteriores,
por ejemplo las comparaciones y las operaciones entre enteros. Las cua-
tro operaciones se conocen con el nombre genrico de operaciones de
.. punto flotante fiaps (floating point operations). Algunas veces se hacen
dos grupos: por un lado sumas y restas, y por otro multiplicaciones y
divisiones. Si se supone que el tiempo necesario para efectuar una mul-
tiplicacin es bastante mayor que el tiempo de una suma, entonces se
acostumbra a dar el nmero de multiplicaciones (o divisiones). El diseo
de los procesadores actuales muestra tendencia al hecho de que los dos
tiempos sean comparables. Entonces se acostumbra a evaluar el nmero
de fiaps.

S urnas y restas Multiplicaciones


y divisiones
clculo de Xn O 1
clculo de Xn-l 1 2
clculo de X n -2 2 3
.. ,
clculo de X2 n-2 n-l
clculo de Xl n-l n
2
1 Total n /2-n/2 n 2 /2 + n/2
Nmero total de operaciones de punto flotante: n 2 .

11.4.2 Implementacin en e
Para la siguiente implementacin en e es necesario tener en cuenta
estos aspectos:

La matriz est almacenada en un arreglo unidimensional. Por tan-


to, la informacin referente a la matriz A se pasa a la funcin por
medio de la direccin del primer elemento de la matriz .
Se usa la funcin prodXY, definida en el captulo 10, que calcula el
producto escalar de dos vectores. Su prototipo es
double prodXY(double *x, double *Y, int n);

204
11.4. SISTEMA TRIANGULAR SUPERIOR

Para utilizarla se requiere pasar las direcciones de cada uno de los


primeros elementos de los vectores en consideracin, o sea, las di-
recciones de ai,i+l Y de Xi+l El elemento ai,i+l es exactamente
a[i*n + i+1], o sea, con a[i*(n+l) + 1].

El nmero de elementos de x(i + 1 : n - 1) es n - 1 - i

Como prodXY devuelve O cuando n es menor o igual que cero,


entonces el clculo de Xn-l se puede incluir dentro del ciclo f or.

Para ahorrar memoria, la solucin del sistema, es decir el vector


x, estar a la salida de la funcin, en el arreglo b, que contena
inicialmente los trminos independientes.

int solTrSup(double *a, double *b, int n, double eps)


{
II Solucion del sistema triangular superior
II A x = b.

II A almacenada en un arreglo unidimensional,


II Aij esta en a[i*n+j].

II Devuelve 1 si se resolvio el sistema.


II O si la matriz es singular o casi.
II -1 si n es inadecuado
II
II Cuando hay solucion, esta quedara en b.

II A se considera singular si
II I Aii I <= eps para algun i.

int i, ii, ni, n_l;

if( n <= O ) return -1;

ni = n+l;
n_l = n-l;
for( i = n_l; i >= O; i--){
ii = i*nl;
if( fabs( a[ii] ) <= eps ) return O;

205
11. SOLUCIN DE SISTEMAS LINEALES

b[i] (b[i]-prodXY(&a[ii+1], &b[i+1],n_1-i))/a[ii];


}
return 1;
}

11.5 Sistema triangular inferior


La solucin de un sistema triangular inferior Ax = b, A triangular
inferior, es anloga al caso de un sistema triangular superior. Primero
se calcula Xl, despus X2, enseguida X3 Y as sucesivamente hasta X n .
i-l

bi - L aijXj
j=l
Xi = (11.3)
aii

El esquema del algoritmo es el siguiente:

para i = 1, ... , n
Xi = (b i - prodEsc(A(i, 1 : i - 1), x(l : i - l)))/aii
fin-para

El nmero de operaciones es exactamente el mismo del caso trian-


gular superior.

11.6 Mtodo de Gauss

El mtodo de Gauss para resolver el sistema Ax = b tiene dos partes;


la primera es la triangularizacin del sistema, es decir, por medio de
operaciones elementales, se construye un sistema

A' X = b' , (11.4)

equivalente al primero, tal que A' sea triangular superior. Que los siste-
mas sean equivalentes quiere decir que la solucin de Ax = b es exacta-
mente la misma solucin de A' X = b' . La segunda parte es simplemente
la solucin del sistema triangular superior.
Para una matriz, con ndices entre 1 y n, el esquema de triangulari-
zacin se puede escribir as:

206
11.6. MTODO DE GAUSS

para k = 1, ... ,n-1


buscar ceros en la columna k, por debajo de la diagonal.
fin-para k

Afinando un poco ms:

para k = 1, ... , n - 1
para i = k + 1, ... , n
buscar ceros en la posicin de aik.
fin-para
fin-para k

Ejemplo 11.2. Consideremos el siguiente sistema de ecuaciones:

+ 3X2 - 2X3 + X4
4Xl 4
3Xl + 2X2 + X3 + 5X4 -8
-2Xl + 3X2 + X3 + 2X4 -7
-8

En forma matricial se puede escribir:

3 -2

[J-5
2
3
O
1
1
1
Es usual trabajar nicamente con los nmeros, olvidando temporalmen-
te los Xi. Ms an, se acostumbra trabajar con una matriz ampliada,
resultado de pegar a la derecha de A el vector b.

3 -2

[J
1
2
3
1
1
5
2 -!-7 1
-5 O 1 1 -8

Inicialmente hay que buscar ceros en la primera columna. Para bus-


car cero en la posicin (2, 1), fila 2 y columna 1, se hace la siguiente
operacin:
fila2nueva <- fila2 vieja - (3/4) *fila1

207
11. SOLUCIN DE SISTEMAS LINEALES

Para hacer ms sencilla la escritura la expresin anterior se escribir sim-


plemente:
fila2 f - fila2 - (3/4)*filal
4 3 -2 1 4
O -0.25 2.5 4.25 -11
[ -2
-5
3
O
1
1
2
1
-7
-8 1
Para buscar cero en la posicin (3,1) se hace la siguiente operacin:
fila3 f- fila3 - (- 2/4) *filal
4 3 -2 1 4
O -0.25 2.5 4.25 -11
[ O
-5
4.5
O
O
1
2.5
1
-5
-8 1
Para buscar cero en la posicin (4, 1) se hace la siguiente operacin:

fila4 f- fila4 - (-5 /4) *filal


4 3 -2 1 4
O -0.25 2.5 4.25 -11
[ O
O
4.5
3.75
O
-1.5
2.5
2.25
-5
-3 1
Ahora hay que buscar ceros en la segunda columna. Para buscar cero en
la posicin (3,2) se hace la siguiente operacin:

fila3 f- fila3 - (4.5/( -0.25))*fila2

[~
3 -2 1
-0.25 2.5 4.25 -114 ]
O 45 79 -203
3.75 -1.5 2.25 -3
Para buscar cero en la posicin (4,2) se hace siguiente operacin:
fila4 f- fila4 - (3.75/( -0.25))*fila2

[~
3 -2 1
-0.25 2.5 4.25 -114 ]
O 45 79 -203
O 36 66 -168

208
11.6. MTODO DE GAUSS

Para buscar cero en la posicin (4, 3) se hace la siguiente operacin:

fila4 +- fila4 - (36/45) *fila3

[~
3 -2 1 4
-0.25 2.5 4.25
-11 ]
O 45 79 -203
O O 2.8 -5.6
El sistema resultante ya es triangular superior. Entonces se calcula pri-
mero X4 = -5.6/2.8 = -2. Con este valor, utilizando la tercera ecuacin
resultante, se calcula X3, despus X2 Y Xl

X = (1, O, -1, -2). <>

De manera general, cuando ya hay ceros por debajo de la diagonal,


en las columnas 1, 2, ... , k - 1, para obtener cero en la posicin (i, k) se
hace la operacin

Lo anterior se puede reescribir as:

lik = aik/akk
A(i,:) = A(i,:) -lik * A(k,:)
bi = bi - lik * bk
Como en las columnas 1, 2, ... , k - 1 hay ceros, tanto en la fila k como
en la fila i, entonces ail, ai2, ... , ai,k-l seguirn siendo cero. Adems, las
operaciones se hacen de tal manera que aik se vuelva cero. Entonces aik
no se calcula puesto que dar O. Luego los clculos se hacen en la fila i
a partir de la columna k + 1.

lik = aik / akk


aik = O
A(i, k + 1 : n) = A(i, k + 1 : n) - lik * A(k, k + 1 : n)
bi = bi - lik * bk

En resumen, el esquema de la triangularizacin es:

209
11. SOLUCIN DE SISTEMAS LINEALES

para k = 1, ... , n - 1
para i = k + 1, ... , n
lik = aik/akk, aik = O
A(i, k + 1 : n) = A(i, k + 1 : n)-lik*A(k, k + 1 : n)
bi = bi-lik*bk
fin-para i
fin-para k

Este esquema funciona, siempre y cuando no aparezca un pivote,


akk, nulo o casi nulo. Cuando aparezca es necesario buscar un elemento
no nulo en el resto de la columna. Si, en el proceso de triangularizacin,
toda la columna A(k : n, k) es nula o casi nula, entonces A es singular.

para k = 1, ... , n - 1
para i = k + 1, ... , n
si lakkl ~ ent
buscar m, k + 1 ~ m ~ n, tal que lamkl >
si no fue posible ent salir
intercambiar(A(k, k : n), A(m, k: n))
intercambiar(bk, bm )
fin-si
lik = aik/akk, aik = O
A(i, k + 1 : n) = A(i, k + 1 : n)-lik*A(k, k + 1 : n)
bi = bi-lik*bk
fin-para i
fin-para k
si Ia nn I ~ ent salir

Cuando en un proceso una variable toma valores enteros desde un


lmite inferior hasta un lmite superior, y el lmite inferior es mayor que
el lmite superior, el proceso no se efecta.
As, en el algoritmo anterior se puede hacer variar k, en el bucle
externo, entre 1 y n, y entonces no es necesario controlar si ann ~ O ya
que, cuando k = n, no es posible buscar m entre n + 1 y n.

210
11.6. MTODO DE GAUSS

para k = 1, .oo, n
para i = k + 1, oo., n
si lakkl ~ ent
buscar m, k + 1 ~ m ~ n, tal que lamkl >
si no fue posible ent salir
intercambiar(A(k, k : n), A(m, k : n))
intercambiar(bk,bm )
fin-si
lik = aik/ akk. aik = O
A(i, k + 1 : n) = A(i, k + 1 : n)-lik*A(k, k + 1 : n)
bi = bi-lik*bk
fin-para i
fin-para k

El anterior algoritmo se adapta fcilmente al caso de, los subndices,


variando entre O y n - 1.
para k = O, oo., n - 1
para i = k + 1, ... , n - 1
si lakkl ~ ent
buscar m, k + 1 ~ m ~ n - 1, tal que lamkl >
si no fue posible ent salir
intercambiar(A(k, k : n - 1), A(m, k : n - 1))
intercambiar(bk,brn )
fin-si
lik = aik/akk, aik = O
A(i, k + 1 : n - 1) = A(i, k + 1 : n - 1)-lik*A(k, k +1:n - 1)
bi = bi -lik*bk
fin-para i
fin-para k

11.6.1 Nmero de operaciones

En el mtodo de Gauss hay que tener en cuenta el nmero de opera-


ciones de cada uno de los dos procesos: triangularizacin y solucin del
sistema triangular.

Triangularizacin
Consideremos inicialmente la bsqueda de cero en la posicin (2,1). Para
efectuar A(2,2 : n) = A(2,2 : n) - lik * A(1, 2 : n) es necesario hacer

211
11. SOLUCIN DE SISTEMAS LINEALES

n - 1 sumas y restas. Para b2 = b2-1ik*bl es necesario una resta. En


resumen n sumas (o restas). Multiplicaciones y divisiones: una divisin
para calcular lik; n - 1 multiplicaciones para lik * A(l, 2 : n) y una
para lik*bl. En resumen, n + 1 multiplicaciones (o divisiones).
Para obtener un cero en la posicin (3,1) se necesita exactamente
el mismo nmero de operaciones. Entonces para la obtener ceros en la
primera columna:

Sumas y restas Multiplicaciones


y divisiones
cero en la posicin de a21 n n+1
cero en la posicin de a31 n n+1
...
cero en la posicin de anl n n+1
l Total para la columna 1 (n - l)n (n - l)(n + 1) l
Un conteo semejante permite ver que se requieren n - 1 sumas y n
multiplicaciones para obtener un cero en la posicin de a32. Para buscar
ceros en la columna 2 se van a necesitar (n - 2)(n -1) sumas y (n - 2)n
multiplicaciones.

Sumas y restas Multiplicaciones


y divisiones
ceros en la columna 1 (n - l)n (n - l)(n + 1)
ceros en la columna 2 (n - 2)(n - 1) (n - 2)n
ceros en la columna 3 (n - 3)(n - 2) (n - 3)(n - 1)
...
ceros en la columna n - 2 2(3) 2(4)
ceros en la columna n - 1 1(2) . 1(3)

Es necesario utilizar el resultado

i
m
2 = m(m + 1)(2m + 1) .
i=l 6
Nmero de sumas y restas:
n-l n-l n3 n n3
i(i + 1) = (i2 + i) = 3 - "3 ~ 3
i=l i=l

212
11.6. MTODO DE GAUSS

Nmero de multiplicaciones y divisiones:

L . L(2
n-l n-l 3 2 3
2( 2 + 2) = 2
+ 22). = -n + -n - -5n ~
n
-.
3 2 6 3
i=l i=l

Nmero de operaciones:

n3 n n3 n2 5n 2n 3 n2 7n 2n 3
3 - 3+3 +2 - 6 = 3 +2 - 6 ~ 3'
Proceso completo
El nmero de operaciones para las dos partes, triangularizacin y solu-
cin del sistema triangular, es

2n 3 3n2 7n 2n 3
-+---~_.
3 2 6 3
Para valores grandes de n el nmero de operaciones de la solucin del
sistema triangular es despreciable con respecto al nmero de operaciones
de la triangularizacin.

11.6.2 Implementacin en e
La implementacin hace uso de la funcin xMasAlfaY, definida en el
captulo 10, que adiciona a un vector un mltiplo de otro vector:

U f-- U + 3.5v
Su prototipo es:

void xMasAlfaY(double *x, double alfa, double *y, int n);

La siguiente implementacin en e es casi la traduccin a e del algoritmo


presentado. Hay algunas variables adicionales para no tener que efectuar
varias veces la misma operacin, por ejemplo, n + 1.

int gaussl( double *a, double *b, double *x, int n,


double eps)
{
II Metodo de Gauss SIN PIVOTEO parcial
II para resolver A x = b

213
11. SOLUCIN DE SISTEMAS LINEALES

II Intercambio de filas solo si el pivote es casi nulo.

II A almacenada en un arreglo unidimensional


II Aij esta en a[i*n+j]

II Devuelve 1 si se resolvio el sistema.


II O si la matriz es singular o casi.
II -1 si n es inadecuado

int k, i, nl, ik, n_l, kk, in, j, ii, m;


double lik, s;

if( n <= O ) return -1;

nl = n+l;
n_l = n-l;

II triangularizacion

for( k = O; k < n; k++){


kk = k*nl;
if( fabs( a[kk] ) <= eps ){
for(m = k+l; m<n; m++)if(fabs(a[m*n+k]) >= eps)
break;
if( m >= n ) return O;
intercXY(&a[kk], &a[m*n+k], n-k);
interc( b[k] , b[m] );
}
for( i = k+l; i < n; i++){
II anular Aik
ik = i*n + k;
lik = a[ik]/a[kk];
xMasAlfaY( &a[ik+l], -lik, &a[kk+l] , n_l-k);
b[i] -= lik*b[k];
a[ik] = 0.0;
}
}
solTrSup(a, b, x, n, eps);

214
11.7. FACTORIZACIN LU

return 1;
}

11.7 Factorizacin L U
Si durante el proceso del mtodo de Gauss no fue necesario inter-
cambiar filas, entonces se puede demostrar que se obtiene fcilmente
la factorizacin A = LU, donde L es una matriz triangular inferior con
unos en la diagonal y U es una matriz triangular superior. La matriz U es
simplemente la matriz triangular superior obtenida al final del proceso.

Para el ejemplo anterior:


4 3 -2 1
O -0.25 2.5 4.25
u=[ O O 45 79
O O O 2.8 1
La matriz L, con unos en la diagonal, va a estar formada simplemente
por los coeficientes lik= lik = aik / akk.
1 O O O
b 1 O O
L = hl h2 1 O

Siguiendo con el ejemplo:

.~.
O O
L = [ 75 1 O
-0.5 -18 1
-1.25 -15 0.8
En este ejemplo, fcilmente se comprueba que LU = A. Esta factoriza-
cin es til para resolver otro sistema Ax = b, exactamente con la misma
matriz de coeficientes, pero con diferentes trminos independientes.
Ax b,
LUx b,
Ly b,
donde Ux y.

215
11. SOLUCIN DE SISTEMAS LINEALES

En resumen:

Resolver Ly = b para obtener y .

Resolver U x = y para obtener x.

Ejemplo 11.3. Resolver

+ 3X2 - 2X3 + X4
4Xl 8
3Xl + 2X2 + X3 + 5X4 30

-2Xl + 3X2 + X3 + 2X4 15


- 5X l + X3 + X4 2

Al resolver
o

~ ][~~l ~ [~~l
1 O
0.75 1 o
[ -0.5
-1.25
-18
-15
1
0.8

se obtiene y = [ 8 24 451 11.2 f. Al resolver

[~~
4 3 -2 1
O -0.25 2.5 4.25 24.0
1
[ O
O
O
O
45
O
79
2.8 1 1
[ 80
451.0
11.2

se obtiene la solucin final x = I 1 2 3 4 f. <>


Resolver un sistema triangular, con unos en la diagonal, requiere n 2 -
n ~ n 2 operaciones. Entonces, para resolver un sistema adicional, con la
misma matriz A, se requiere efectuar aproximadamente 2n 2 operaciones,
en lugar de 2n3 /3 que se requeriran si se volviera a empezar el proceso.
La factorizacin A = LU es un subproducto gratuito del mtodo
de Gauss; gratuito en tiempo y en requerimientos de memoria. No se
requiere tiempo adicional puesto que el clculo de los lik se hace dentro
del mtodo 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 nicamente un pequeo cambio:

216
11.8. MTODO DE GAUSS CON PIVOTEO PARCIAL

lik = aik / akk


aik = lik
A(i, k + 1 : n - 1) = A(i, k +1 :n - l)-lik*A(k, k +1 :n - 1)
bi = bi -lik*bk

En la matriz final A estar la informacin indispensable de L y de U.

Un UI2 UI3 UI n
b U22 U23 U2n
L= lsl l32 U3I U3n'

lnl ln2 ln3 U nn

En el ejemplo anterior, la: matriz final con informacin de L y de U es:

~. 75
3 -2
-0.25 2.5
/25]
[ -0.5 -18 45 79
-1.25 -15 0.8 2.8

11.8 Mtodo de Gauss con pivoteo parcial


En el mtodo de Gauss clsico, nicamente se intercambian filas .
cuando el pivote, akk, es nulo o casi nulo. Como el pivote (el elemento
akk en la iteracin k) va a ser divisor para el clculo 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 valor absoluto. Es decir, hay que evitar los pivotes que sin ser
nulos son cercanos a cero.
En el mtodo 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 lakkl, lak+1,kl, lak+2,kl,
... , laknl, y se intercambian la fila k y la fila del valor dominante. Esto
mejora notablemente, en muchos casos, la precisin de la solucin final
obtenida.

217
11. SOLUCIN DE SISTEMAS LINEALES

Se dice que el pivoteo es total si en la iteracin k se busca el mayor


valor de {I aij I : k :::; i, j :S. n}. En este caso es necesario intercambiar
dos filas y dos columnas. As se consigue mejorar un poco la precisin
con respecto al mtodo de pivoteo parcial, pero a un costo nada despre-
ciable. En el mtodo 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 mximo entre p elementos, enton-
ces hay que hacer, adems de operaciones de asignacin, por lo menos
p - 1 comparaciones. Estas operaciones no son de punto flotante y son
ms rpidas que ellas, pero para n grande, el tiempo utilizado no es des-
preciable. En el mtodo de pivoteo parcial hay aproximadamente n 2 /2
comparaciones, en el pivoteo total aproximadamente n 3 /6. En resumen,
con el pivoteo total se gana un poco de precisin, pero se gasta bastante
ms tiempo. El balance aconseja preferir el pivoteo parcial.

Ejemplo 11.4. Resolver por el mtodo de Gauss con pivoteo parcial el


siguiente sistema de ecuaciones.

4Xl + 3X2 - 2X3 + X4 4


3Xl + 2X2 + X3 + 5X4 -8
-2Xl + 3X2 + X3 + 2X4 -7
- 5X l +X3 + X4 -8

La matriz aumentada es:

4 3 -2 1

[
3
-2
2
3
1
1
5
2
-! ]
-7
-5 O 1 1 -8

El valor dominante de A(l : 4,1) es -5 y est en la fila 4. Entonces se


intercambian las filas 1 y 4.

-~ O
2
1
1
1
5 -8]
-8
[ -2
4
3
3
1
-2
2
1
-7
4

Buscar ceros en las posiciones de a21, a31, a41 se hace de la manera


habitual usando los valores de lik= 3/(-5) = -0.6, 0.4 y -0.8. Se

218
11.8. MTODO DE GAUSS CON PIVOTE O PARCIAL

.~
obtiene
-5 O 1 1 -8
O 2 1.6 5.6 "'C" 12.8
[ O
O
3
3
0.6
-1.2
1.6
1.8
-3.8
-2.4 1
El valor dominante de A(2 : 4,2) es 3 y est en la fila 3 (o en la fila 4).
Entonces se intercambian las filas 2 y 3.

-5 O 1 1 -8

[
O
O
O
3
2
3
0.6
1.6
-1.2
1.6
5.6
1.8
-3.8
-.12.8
-2.4 1
X
Buscar ceros en las posiciones de a32, a42 se hace usando los valores de
lik= 2/3 = 0.6666 Y 1. Se obtiene

-5 O 1 1
O 3 0.6 1.6 -3.8
-8 1
[ O
O
O
O
1.2
-1.8
4.5333
0.2
-10.2667
1.4

Hay que intercambiar las filas 3 y 4.

-5 1 1
O
O
3 0.6 1.6 -3.8
-8 1
[ O
O
O
O
-1.8
1.2
0.2
4.5333
1.4
-10.2667

El valor de lik es 1.2/(-1.8) = -0.6667. Se obtiene

-5 O 1 1 -8

[ O
O
O
3
O
O
0.6
-1.8
O
1.6
0.2
4.6667
-3.8
1.4
-9.3333 1
Al resolver el sistema triangular superior, se encuentra la solucin:

x = (1, 0, -1, -2). <>

El ejemplo anterior sirve simplemente para mostrar el desarrollo del


mtodo de Gauss con pivoteo parcial, pero no muestra sus ventajas. El

219
11. SOLUCIN DE SISTEMAS LINEALES

ejemplo siguiente, tomado de [Atk78], se resuelve inicialmente por el


mtodo de Gauss sin pivoteo y despus con pivoteo parcial. Los clculos
se hacen con cuatro cifras decimales.

0.729xI + 0.81x2 + 0. 9X3 0.6867


Xl + x2 + x3 .8338
1.331xI + 1.21x2 + 1. 1x3 1

Con la solucin exacta, tomada con cuatro cifras decimales, es

X = (0.2245, 0.2814, 0.3279).

Al resolver el sistema por el mtodo de Gauss, con cuatro cifras decimales


y sin pivoteo, resultan los siguientes pasos:

0.7290 0.8100 0.9000 0.6867

[ 1.0000
1.3310
1.0000
1. 2100
1.0000
1.1000
0.8338
1.0000 ]
Con lik = 1.3717 Y con lik = 1. 8258 se obtiene

0.7290 0.8100 0.9000 0.6867

[ 0.0000
0.0000
-0.1111
-0.2689
-0.2345
-0.5432
-0.1081
-0.2538 ]
Con lik = 2.4203 se obtiene
0.7290 0.8100 0.9000 0.6867

[ 0.0000
0.0000
-O .1111
0.0000
-0.2345
0.0244
-0.1081
0.0078 ]
La solucin del sistema triangular da:

X = (0.2163, 0.2979, 0.3197).

Sea x* la solucin exacta del sistema Ax = b. Para comparar xl y x 2,


dos aproximaciones de la solucin, se miran sus distancias a x*:

/lxl - x*/I, /lx 2 - x*/I.

Si Ilxl - x* 11 < IIx2 - x* 11, entonces xl es, entre xl y x 2, la mejor aproxi-


macin de x*. Cuando no se conoce x*, entonces se utiliza la norma del

220
11.8. MTODO DE GAUSS CON PIVOTEO PARCIAL

vector residuo o resto, r = Ax - b. Si x es la solucin exacta, entonces


la norma de su resto vale cero. Entonces hay que comparar
1 2
IIAx - bll, IIAx - bll
Para la solucin obtenida por el mtodo de Gauss, sin pivoteo,

IIAx - bll = 1. 0357e-004 , Ilx - x* II = 0.0202 .

En seguida est el mtodo de Gauss con pivoteo parcial, haciendo clcu-


los con 4 cifras decimales.
0.7290 0.8100 0.9000 0.6867

[ 1.0000
1.3310
1.0000
1.2100
1.0000
1.1000
0.8338
1.0000 1
Intercambio de las filas 1 y 3.

1. 3310 1. 2100 1.1000 1.0000

[ 1.0000
0.7290
1.0000
0.8100
1.0000
0.9000
0.8338
0.6867 1
Con lik = 0.7513 Y con lik= 0.5477 se obtiene

1.3310 1. 2100 1.1000 1.0000

[ 0.0000
0.0000
0.0909
0.1473
0.1736
0.2975
0.0825
0.1390 1
Intercambio de las filas 2 y 3.

1.3310 1. 2100 1.1000 1.0000

[ 0.0000
0.0000
0.1473
0.0909
0.2975
0.1736
0.1390
0.0825 1
Con lik= 0.6171 se obtiene
1.3310 1. 2100 1.1000 1.0000

[ 0.0000
0.0000
0.1473
0.0000
0.2975
-0.0100
0.1390
-0.0033 1
La solucin del sistema triangular da:

x = (0.2267, 0.2770, 0.3300).

221
11. SOLUCIN DE SISTEMAS LINEALES

El clculo del residuo y la comparacin con la solucin exacta da:

IIAx - bll = 1. 5112e-004, Ilx - x* II = 0.0053 .

Se observa que para este ejemplo la norma del residuo es del mismo or-
den de magnitud que la norma del residuo correspondiente a la solucin
obtenida sin pivoteo, aunque algo mayor. La comparacin directa con
la solucin exacta favorece notablemente al mtodo de pivoteo parcial:
0.0053 y 0.0202, relacin de 1 a 4 aproximadamente. Adems, "visual-
mente" se observa la mejor calidad de la solucin obtenida con pivoteo.
A continuacin aparece una versin de la funcin que implementa el
mtodo de Gauss con pivoteo parcial.

int gausspp( double *a, double *b, int n, double eps)


{
II Metodo de Gauss CON PIVOTEO parcial
II para resolver A x = b.

II Intercambio real de las filas.

II A almacenada en un arreglo unidimensional,


II Aij esta en a[i*n+j].

II Devuelve 1 si se resolvio el sistema.


II O si la matriz es singular o casi.
II -1 si n es inadecuado

II Cuando hay solucion, esta quedara en b.

int k, i, nl, ik, n_l, kk, in, j, ii, m, mO;


double lik, s, aamk, t;

if( n <= O ) return -1;

nl = n+l;
n_l = n-l;

II triangularizacion

222
11.9. FACTORIZACIN LU=PA

for( k = O; k < n_1; k++){


kk = k*n1;
aamk = maxAbsXPos( &a[kk], n, n-k, mO);
if( aamk <= eps ) return O;
i f ( mO != O ){
m = k+mO;
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 O;

solTrSup(a, b, n, eps);
return 1;
}

11.9 Factorizacin LU=PA


Si se aplica el mtodo de Gauss con pivoteo parcial muy probable-
mente se hace por lo menos un intercambio de filas y no se puede obtener
la factorizacin A = LU, pero s se puede obtener la factorizacin

LU=PA.

Las matrices L y U tienen el mismo significado de la factorizacin LU. P


es una matriz de permutacin, es decir, se obtiene mediante permutacin
de filas de la matriz identidad 1.

Si P y Q son matrices de permutacin, entonces:

223
11. SOLUCIN DE SISTEMAS LINEALES

PQ es una matriz de permutacin.


p- 1 = p T (P es ortogonal).

P A es una permutacin de las filas de A.

AP es una permutacin de las columnas de A.


Una matriz de permutacin P se puede representar de manera ms
compacta por medio de un vector P E ]Rn con la siguiente convencin:

Pi. = Jpi
En palabras, la fila i de P es simplemente la fila Pi de J. Obviamente P
debe cumplir:
Pi E {1, 2, 3, ... , n} Vi
Pi =1= Pj Vi =1= j.
Por ejemplo, P = (2,4,3,1) representa la matriz
o
p~ ~ ~ ].
1
O O
[ O 1
O O

De la misma forma que en la factorizacin LU, los valores lik se alma-


cenan 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 factorizacin LU = P A, donde

A~[
4 3 -2 1
3
-2
-5
2
3
O
1
1
1
5
2
1
]
Inicialmente P = (1,2,3,4). Para buscar el mejor pivote, se intercambian
las filas 1 y 4.

[ -~
~]
O 1
2 1
p=(4,2,3,1),
-2 3 1
4 3 -2

224
11.9. FACTORIZACIN LU=PA

Buscando ceros en la primera columna y almacenando all los valores


se obtiene:
lik

o
~.6l
-5 1
-0.6 2 1.6
0.4 3 0.6 1.6
[
-0.8 3 -1.2 1.8
Para buscar el mejor pivote, se intercambian las filas 2 y 3.
-5 O 1 1

p=(4,3,2,1),
[ 0.4
-0.6
-0.8
3
2
3
0.6
1.6
-1.2
1.6
5.6
1.8 1
Buscando ceros en la segunda columna y almacenando all los valores
lik se obtiene:

-5 O 1 1
0.4 3 0.6 1.6
[ -0.6
-0.8
0.6667
1
1.2
-1.8
4.5333
0.2 1
Para buscar el mejor pivote, se intercambian las filas 3 y 4.
-5 o 1
0.4 3 0.6
p= (4,3,1,2),
-0.8 1 -1.8
[
-0.6 0.6667 1. 2
Buscando ceros en la tercera columna y almacenando all los valores lik
se obtiene:
o
~.6 1
-5 1
0.4 3 0.6
-0.8 1 -1.8 0.2 .
[
-0.6 0.6667 -0.6667 4.6667
En esta ltima matriz y en el arreglo p est toda la informacin necesaria
para obtener L, U, P. Entonces:

~1
1 O O
0.4 1 O
L= [ -0.8 1 1 O .
-0.6 0.6667 -0.6667 1

225
11. SOLUCIN DE SISTEMAS LINEALES

-5 O 1 1
O 3 0.6 1.6
u=[ O
O
O
O
-1.8
O
0.2
4.6667
]
O O O 1
O O 1 O
P=[ 1
O
O
1
O
O
O
O
] O

Si se desea resolver el sistema Ax = b a partir de la descomposicin


PA = LU, se considera el sistema p-l LU x = b, o sea, pT LU x = b.
Sean z = LU x y y = U x. La solucin de Ax = b tiene tres pasos:

Resolver pT z = b, o sea, z = Pb.

Resolver Ly = z.

Resolver U x = y.

Ejemplo 11.6. Para la matriz A del ejemplo anterior, resolver Ax = b


con b = [4 - 8 - 7 - 8]T.

z = Pb = [ ~~ ]

-8
-3.8 ]
Ly = z ,entonces y =
1.4
[
-9.3333

Ux = y ,entonces x =
U] O

226
11.10. MTODO DE CHOLESKY

11.10 Mtodo de Cholesky


Este mtodo sirve para resolver el sistema Ax = b cuando la matriz A
es definida positiva (tambin llamada positivamente definida). Este
tipo de matrices se presenta en problemas especficos de ingeniera y
fsica, principalmente.

11.10.1 Matrices definidas positivas

Una matriz simtrica es definida positiva si

X T Ax > O, Vx E ]Rn, X =f. O. (11.5)

Para una matriz cuadrada cualquiera,

:~~ :~~
xTAx xn ]
[ anl an2

allXl
a21xl
+ a12 X 2 + ... + alnX n
+ a22 x 2 + ... + a2n X n
1
[ Xl xn ]
[
anlXl + a n 2X 2 + ... + annXn
n n
LLaijXiXj.
i=l j=i

Si A es simtrica,

n n-l n
x
T
Ax =L aii X ; +2L L aijXiXj.
i=l i=l j=i+l

Ejemplo 11.7. Sea 1 la matriz identidad de orden n. Entonces x TI x =


xTx = Ilx112. Luego la matriz 1 es definida positiva. <>

Ejemplo 11.8. Sea A la matriz nula de orden n. Entonces xTO x = O.


Luego la matriz nula no es definida positiva. <>

227
11. SOLUCIN DE SISTEMAS LINEALES

Ejemplo 11.9. Sea

A [; ;].
xTAx xi + 5x~ + 4XlX2
Xl2 + 4XlX2 + 4X22 + X22
(Xl + 2X2)2 + X~.
Obviamente x TAx 2: O. Adems x TAx = O si y solamente si los dos
sumandos son nulos, es decir, si y solamente si X2 = O Y Xl = O, o sea,
cuando X = O. Luego A es definida positiva. O

Ejemplo 11.10. Sea

A [; ~].
xTAx xi + 4x~ + 4XlX2
(Xl + 2X2)2.
Obviamente x TAx 2: O. Pero si X = (6, -3), entonces x TAx = O. Luego
A no es definida positiva. O

Ejemplo 11.11. Sea

A [; ~].
xTAx xi + 3x~ + 4XlX2
(Xl + 2X2)2 - x~.

Si X = (6, -3), entonces x TAx = -9. Luego A no es definida positiva. O

Ejemplo 11.12. Sea

A [! ~].
Como A no es simtrica, entonces no es definida positiva. O

Sean Al, A2,' .. ,An los valores propios de A. Si A es simtrica, en-


tonces todos sus valores propios son reales.

228
11.10. MTODO DE CHOLESKY

Sea tSi el determinante de la submatriz de A, de tamao ix i, obtenida


al quitar de A las filas i + 1, i + 2, ... , n y las columnas i + 1, i + 2, ... ,
n. O sea,

det([a11]) = a11,

det [ a11 a12 ] ,


a21 a22

det
[ al!
a21
a31
a12
a22
a32
a13
a13
a33
],

det(A).

La definicin 11.5 tiene relacin directa con el nombre matriz defini-


da positiva. Sin embargo, no es una manera fcil o prctica de saber
cundo una matriz simtrica es definida positiva, sobre todo si A es
grande. El teorema siguiente presenta algunas de las caracterizaciones
de las matrices definidas positivas. Para matrices pequeas (n :S 4) la
caracterizacin por medio de los tSi puede ser la de aplicacin ms senci-
lla. La ltima caracterizacin, llamada factorizacin de Cholesky, es la
ms adecuada para matrices grandes. En [Str86], [NoD88] y [MorOl] hay
demostraciones y ejemplos.

Teorema 11.1. Sea A simtrica. Las siguientes afirmaciones son equi-


valentes.

A es definida positiva.

'xi > 0, Vi.

tSi > 0, Vi.

Existe U matriz triangular superior e invertible tal que A = UTU.

11.10.2 Factorizacin de Cholesky


Antes de estudiar el caso general, veamos la posible factorizacin
para los ejemplos de la seccin anterior.

229
11. SOLUCIN DE SISTEMAS LINEALES

La matriz identidad se puede escribir como 1 = F 1, siendo 1 trian-


gular superior invertible. Luego existe la factorizacin de Cholesky para
la matriz identidad.
Si existe la factorizacin de Cholesky de una matriz, al ser U y U T
invertibles, entonces A debe ser invertible. Luego la matriz nula no tiene
factorizacin de Cholesky.

Sea

A=[12]
2 5 .

Entonces

[ Un
U12
O ] [
U22
Un
O
U12 ]
U22
2
[~ ~ ]
un 1
Un U 12 2,
2 2
u12 + u22 5

Se deduce que

Un 1
U12 2,
U22 1,

U
[~ ~ ] .
Entonces existe la factorizacin de Cholesky de A.
Cuando se calcul Un se hubiera podido tomar Un = -1 Y se hubiera
podido obtener otra matriz U. Se puede demostrar que si se escogen
los elementos diagonales Uii positivos, entonces la factorizacin, cuando
existe, es nica.

Sea

A=[12]
2 4 .

230
11.10. MTODO DE CHOLESKY

Entonces

[ Un
U12
O ] [ Un
U22 O
U12 ]
U22 [~ ~]
2 1
un
Un U 12 2,
2 2 4
u12 + u22

Se deduce que

Un 1
U12 2,
U22 O,

U [~ ~].
Entonces, aunque existe U tal que A = UTU, sin embargo no existe la
factorizacin de Cholesky de A ya que U no es invertible.

Sea
A=[~ ~].
Entonces

[ Un
U12
O
U22 ][ Un
O
U12 ]
U22 [~ ~]
2 1
un
Un U 12 2,
2 2 3
U12 + u22

Se deduce que

Un 1
U12 2,
U~2 -1.

Entonces no existe la factorizacin de Cholesky de A.

231
11. SOLUCIN DE SISTEMAS LINEALES

En el caso general,

U11 U11 ... Ulk ... Ulj ... Ul n

Ulk ... Ukk Ukk ... Ukj ... Ukn

Ulj Ukj ... Ujj Ujj ... Ujn

Ul n ... Ukn ... Ujn ... U nn Unn

El producto de la fila 1 de U T por la columna 1 de U da:


2 _
u11 - a11

Luego
U11 = Vall' (11.6)
El producto de la fila 1 de U T por la columna j de U da:

U11 Ulj = alj.

Luego
al'
Ulj = _J , 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 clculo 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:
k

U;k akk
i=l
k-l
"2 2
L-t Uik + Ukk akk
i=l

Luego
k-l
Ukk = 1 I akk - U;k ' k = 2, ... ,n. (11.8)
i=l

232
11.10. MTODO DE CHOLESKY

El producto de la fila k de U T por la columna j de U da:

k
L UikUij = akj
i=l

Luego
k-l
akj - L UikUij
i=l
Ukj=------ k = 2, ... , n, j = k + 1, ... , n. (11.9)
Ukk

Si consideramos que el valor de la sumatoria es O cuando el lmite inferior


es ms grande que el lmite superior, entonces las frmulas 11.8 y 11.9
pueden ser usadas para k = 1, ... , n.
Ejemplo 11.13. Sea

-12 8
A
[ 16
-1~ 18 -6 -1! 1.
-6 5 -10
-16 9 -10 46

Ull = Jl6 = 4
-12
U12 =-3
4
8
U13 =2
4
-16
= -4
4
U22 = J18 - (-3)2 = 3
-6 - (-3)(2)
=0
3
9 - (-3)(-4)
U24 = = -1
3
U33 = J5 - (2 2 + 02 ) = 1
-10 - ( 2(-4) + O( -1) )
U34 = =-2
1

233
ll. SOLUCIN DE SISTEMAS LINEALES

U44 = J46 - ( (-4)2 + (-1)2 + (-2)2) = 5.


Entonces,

4 -3 2 -4]
O 3 O -1
U
[ O
O
O 1 -2
O O 5
. <>

La factorizacin de Cholesky no existe cuando en la frmula 11.8 la


cantidad dentro del radical es negativa o nula. Utilizando el producto
escalar, las frmulas 11.8 y 11.9 se pueden reescribir as:

t akk - prodEsc( U(1 : k - 1, k) , U(1 : k - 1, k) ),


Ukk vi,
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 al-
macenar 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 supe-
rior del espacio ocupado por A estar U.

t akk - prodEsc( A(1 : k - 1, k) , A(1 : k - 1, k) ),(11.10)


akk vi, (11.11)
= akj - prodEsc( A(1 : k - 1, k) , A(1 : k - 1,j) ) (11.12)
akj
akk

El siguiente es el esquema del algoritmo para la factorizacin de Cho-


lesky. Si acaba normalmente, la matriz A es definida positiva. Si en algn
momento t ~ E, entonces A no es definida positiva.

datos: A, E
para k = 1, oo.,n
clculo de t segn (11.10)
si t ~ E ent salir
akk = vi
para j = k + 1, oo., n
clculo de akj segn (11.12)
fin-para j
fin-para k

234
11.10. MTODO DE CHOLESKY

La siguiente es la implementacin en e, casi la traduccin literal,


del algoritmo anterior. Obviamente los subndices de A varan entre O y
n-l.

int factChol(double *a, int n, double eps)


{
II Factorizacion de Cholesky de la matriz simetrica A
II almacenada por filas en el arreglo a.
II A = Ut U, U es triangular sup., invertible.
II Devuelve O si A no es definida positiva.
II 1 si A es definida positiva
II en este caso U estara en
II la parte triangular superior de A.
II Solamente se trabaja con la parte superior de A.

int j, k, n1, kk, kj;


double t;

n1 = n+1;
for( k = O; k < n; k++){
kk = k*n1;
t = a[kk] - prodXY( &a[k] , n, &a[k] , n, k);
if( t <= eps ) return O;
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))1
a [kk] ;
}
}
return 1;
}

11.10.3 N mero de operaciones de la factorizacin

Para el clculo del nmero de operaciones supongamos que el tiem-


po necesario para calcular una raz cuadrada es del mismo orden de
magnitud que el tiempo de una multiplicacin.

235
11. SOLUCIN DE SISTEMAS LINEALES

Sumas y restas Multiplicaciones,


divisiones y races
clculo de Un O 1
clculo de U12 O 1
clculo de Ul n O 1
clculo de U22 1 2
clculo de U23 1 2
clculo de U2n 1 2

clculo de U nn n-1 n

Agrupando por filas:

Sumas y restas Multiplicaciones,


divisiones y races
clculo de U1- n(O) n(1)
clculo de U2- (n - 1)1 (n- 1)2
clculo de U3- (n - 2)2 (n- 2)3
- _.
,clculo de Un- l(n - 1) l(n)

Nmero de sumas y restas:

n-l
~
3 3
L(n-i)i= n -n n
i=l 6 6.

Nmero de multiplicaciones, divisiones y races:

n n3 n2 n n3
L(n + 1 - i)i = 6 + 2" + 3" ~ 6-
i=l

Nmero total de operaciones:

n3 n2 n n3
-+-+-~-
3 2 6 3 -

236
11.10. MTODO DE CHOLESKY

11.10.4 Solucin del sistema

Una vez obtenida la factorizacin de Cholesky, resolver Ax = b es lo


mismo que resolver UTU x = b. Al hacer el cambio de variable U x = y,
la solucin del sistema Ax = b se convierte en

resolver (11.13)
resolver (11.14)

Resolver cada uno de los dos sistemas es muy fcil. El primero es trian-
gular inferior, el segundo triangular superior. El nmero total de ope-
raciones para resolver el sistema est dado por la factorizacin ms la
solucin de dos sistemas triangulares.

n3 n3
Nmero de operaciones ~ - + 2n 2 ~ -.
3 3
Esto quiere decir que para valores grandes de n, resolver un sistema,
con A definida positiva, por el mtodo de Cholesky, gasta la mitad del
tiempo requerido por el mtodo de Gauss.
El mtodo de Cholesky se utiliza para matrices definidas positivas.
Pero no es necesario tratar de averiguar por otro criterio si la matriz
es definida positiva. Simplemente se trata de obtener la factorizacin de
Cholesky de A simtrica. Si fue posible, entonces A es definida positiva
y se contina con la solucin de los dos sistemas triangulares. Si no fue
posible obtener la factorizacin de Cholesky, entonces A no es definida
positiva y no se puede aplicar el mtodo de Cholesky para resolver Ax =
b.

Ejemplo 11.14. Resolver

La factorizacin de Cholesky es posible (A es definida positiva):

u ~ [~ -~ ~]
237
11. SOLUCIN DE SISTEMAS LINEALES

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 implementacin en e ya estn todos los elementos, solamente


basta ensamblarlos y tener en cuenta que no es necesario construir U T
En la solucin del sistema triangular inferior UT 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)


{
II Solucion por el metodo de Cholesky
II del sistema A x = b.

II A debe ser simetrica.

II Devuelve O si A no es definida positiva.


II 1 si A es definida positiva.
II En este caso la solucion estara en b.
II La parte superior de A queda modificada.
II Alli quedara U tal que U' U = A.

II Solamente se trabaja con la parte superior de A.

if( factChol(a, n, eps) o ) return O;


solUTy(a, b, n);
solTrSup(a, b, n, eps);
return 1;
}
11---------------------------------------------------------
void solUTy(double *u, double *b, int n)
{
II Solucion del sistema triangular inferior
II U' Y = b,

238
ll.ll. MTODO DE GAUSS-SEIDEL

II donde U es triangular superior y esta


II en el arreglo u.
II Los elementos diagonales deben ser no nulos.

II Uij esta en u[i*n+j].

II La solucion quedara en b.

int i, nl;

nl = n+l;
for( i = O; i < n; i++){
b[i] = (b[i] - prodXY( &u[i] , n, b, 1, i))/u[i*nl];
}
}

11.11 Mtodo de Gauss-Seidel


Los mtodos de Gauss y Cholesky hacen parte de los mtodos direc-
tos o finitos. Al cabo de un nmero finito de operaciones, en ausencia
de errores de redondeo, se obtiene x* solucin del sistema Ax = b.
El mtodo de Gauss-Seidel hace parte de los mtodos llamados in-
directos o iterativos. En ellos se comienza con xO = (x~, xg, ... , x~), una
aproximacin inicial de la solucin. A partir de xO se construye una nue-
va aproximacin de la solucin, xl = (xL x~, ... , x~). A partir de xl se
construye x2 (aqu el superndice indica la iteracin y no indica una po-
tencia). As sucesivamente se construye una sucesin de vectores {x k },
con el objetivo, no siempre garantizado, de que

lim xk = x*.
k-4OO

Generalmente los mtodos indirectos son una buena opcin cuando la


matriz es muy grande y dispersa o rala (sparse) , es decir, cuando el
nmero de elementos no nulos es pequeo comparado con n 2 , nmero
total de elementos de A. En estos casos se debe utilizar una estructura
de datos adecuada que permita almacenar nicamente los elementos no
nulos.

239
11. SOLUCIN DE SISTEMAS LINEALES

En cada iteracin del mtodo de Gauss-Seidel, hay n subiteraciones.


En la primera subiteracin se modifica nicamente Xl. Las dems coor-
denadas X2, X3, ... , X n no se modifican. El clculo de Xl se hace de tal
manera que se satisfaga la primera ecuacin.

l bl - (al2xg + al3xg + ... + alnX~)


Xl
an
lO
Xi Xi' Z=
2, ... , n.

En la segunda subiteracin se modifica nicamente X2. Las dems coor-


denadas Xl, X3, ... , X n no se modifican. El clculo de X2 se hace de tal
manera que se satisfaga la segunda ecuacin.

2 b2 - (a2lxl + a23X~ + ... + a2nX~)


X2
a22
Xi2 l Z =
Xi' 1, 3 , ... , n.

As sucesivamente, en la n-sima subiteracin se modifica nicamente


Xn .Las dems coordenadas Xl, X2, ... , Xn-l no se modifican. El clculo
de X n se hace de tal manera que se satisfaga la n-sima ecuacin.

bn - (anlxn-l + a n 3x n-l + . . . + annxn-l)


n
x nn l 3
a nn

Xin ni-
X ' l Z = 1, 2, ... , n - 1.

Ejemplo 11.15. Resolver

[ ~~ 1~ [ -;~ 1
1~ -1
20 -2 3O
2
1
[ -2 1 30 O
1 2 3 20

240
11.11. MTODO DE GAUSS-SEIDEL

partiendo de xO = (1, 2, 3, 4)_

l 26 - (2 x 2 + ( -1) x 3 + O x 4)
Xl = 10 = 2.5,

xl = (2.5, 2, 3, 4).
2 _ -15 - (1 x 2.5 + (-2) x 3 + 3 x 4) _ 7
X2 - 20 - -1.1 5,
x2 = (2.5, -1.175, 3, 4).
3 53 - (-2 x 2.5 + 1 x (-1.175) + O x 4)
x3 = 30 = 1.9725,
x3 = (2.5, -1.175, 1.9725, 4).
4 47- (1 x 2.5+2 x (-1.175) +3 x 1.9725)
x4 = 20 = 2.0466,
x4 = (2.5, -1.175, 1.9725, 2.0466).
Una vez que se ha hecho una iteracin completa (n sub iteraciones) ,
se utiliza el ltimo X obtenido como aproximacin inicial y se vuelve a
empezar; se calcula Xl de tal manera que se satisfaga la primera ecuacin,
luego se calcula X2 ... A continuacin estn las iteraciones siguientes para
el ejemplo anterior.

3.0323 -1.1750 1.9725 2.0466


3.0323 -1.0114 1.9725 2.0466
3.0323 -1.0114 2.0025 2.0466
3.0323 -1.0114 2.0025 1.9991

3.0025 -1.0114 2.0025 1.9991


3.0025 -0.9997 2.0025 1.9991
3.0025 -0.9997 2.0002 1.9991
3.0025 -0.9997 2.0002 1.9998

3.0000 -0.9997 2.0002 1.9998


3.0000 -1.0000 2.0002 1.9998
3.0000 -1.0000 2.0000 1.9998
3.0000 -1.0000 2.0000 2.0000

3.0000 -1.0000 2.0000 2.0000


3.0000 -1.0000 2.0000 2.0000
3.0000 -1.0000 2.0000 2.0000
3.0000 -1.0000 2.0000 2.0000

241
11. SOLUCIN DE SISTEMAS LINEALES

Tericamente, el mtodo de Gauss-Seidel puede ser un proceso infi-


nito. En la prctica el proceso se acaba cuando de xk a xk+n los cambios
son muy pequeos. Esto quiere decir que el x actual es casi la solucin
x*.
Como el mtodo no siempre converge, entonces otra detencin del
proceso, no deseada pero posible, est determinada cuando el nmero
de iteraciones realizadas es igual a un nmero mximo de iteraciones
previsto.
El siguiente ejemplo no es convergente, ni siquiera empezando de
una aproximacin inicial muy cercana a la solucin. La solucin exacta
es x = (1,1,1).

Ejemplo 11.16. Resolver

2
[ -1
11 -1 10
2 ][ Xl] = [ 1211 ]
X2
1 5 2 X3 8

partiendo de xO = (1.0001, 1.0001, 1.0001).

1.0012 1.0001 1.0001


1.0012 1.0134 1.0001
1.0012 1.0134 0.9660

0.6863 1.0134 0.9660


0.6863 -2.5189 0.9660
0.6863 -2.5189 9.9541

83.5031 -2.5189 9.9541


83.5031 926.4428 9.9541
83.5031 926.4428 -2353.8586

Algunos criterios garantizan la convergencia del mtodo de Gauss-


Seidel. 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 mtodo puede ser convergente. En la prctica, con
frecuencia, es muy dispendioso poder aplicar estos criterios.
U na matriz cuadrada es de diagonal estrictamente dominante
por filas si en cada fila el valor absoluto del elemento diagonal es mayor

242
ll.ll. MTODO DE GAUSS-SEIDEL

que la suma de los valores absolutos de los otros elementos de la fila,


n
laii 1 > I:: laij 1, Vi.
j=l,#i

Teorema 11.2. Si A es de diagonal estrictamente dominante por filas,


entonces el mtodo de Gauss-Seidel converge para cualquier xO inicial.

Teorema 11.3. Si A es definida positiva, entonces el mtodo de Gauss-


Seidel converge para cualquier xO inicial.

Tericamente el mtodo de Gauss-Seidel se debera detener cuando Ilxk-


x* 11 < E. Sin embargo la condicin anterior necesita conocer x*, que es
precisamente lo que se est buscando. Entonces, de manera prctica el
mtodo de GS se detiene cuando Ilxk - xk+nll < E.
Dejando de lado los superndices, las frmulas del mtodo de Gauss-
Seidel se pueden reescribir para facilitar el algoritmo y para mostrar que
Ilxk - x*11 y Ilxk - xk+nll estn relacionadas.
n
bi - I:: aijXj
j=l,#i

n
bi - I:: aijX j + aiiXi
j=l

aii
bi - At. x
Xi <-:- Xi + ~-~
aii

Sean

bi - Ai. X,
ri
aii

El valor ri es simplemente el error, residuo o resto que se comete en la


i-sima ecuacin al utilizar el X actual. Si ri = 0, entonces la ecuacin i-
sima se satisface perfectamente. El valor Oi es la modificacin que sufre
Xi en una iteracin.

Sean r = (rl, r2, ... , r n), o = (01,02, ... , on). Entonces xk+n = xk + o.
Adems xk es solucin si y solamente si r = 0, o sea, si y solamente

243
11. SOLUCIN DE SISTEMAS LINEALES

15 = O. Lo anterior justifica que el mtodo de GS se detenga cuando


111511 :S . La norma 111511 puede ser la norma euclidiana o max It5i l o L: It5i l
Si en el criterio de parada del algoritmo se desea enfatizar sobre los
errores o residuos, entonces se puede comparar 111511 con /ll(au, ... , ann)ll;
por ejemplo,
111511 :S _ _

El esquema del algoritmo para resolver un sistema de ecuaciones por el


mtodo de Gauss-Seidel es:

datos: A, b, x O, , maxit
x=xo
para k = 1, ... ,maxit
nrmD+--- O
para i = 1, ... , n
t5i = (b i - prodEsc( A i ., x) ) / aii
Xi +--- Xi + t5i
nrmd +---nrmD+t5i
fin-para i
si nrmD :S ent x* ~ x, salir
fin-para k

La siguiente es la implementacin en e, casi la traduccin literal, del


algoritmo anterior.

int gaussSei(double *a, double *b, double *x, int n,


double eps, int maxi t)
{
II Metodo de Gauss-Seidel para resolver Ax b

II Devuelve:
II 1 si se obtuvo aproximadamente la soluciono
II O si hay un elemento diagonal nulo.
II 2 si hubo demasiadas iteraciones, mas de maxit.

II Entrando a la funcion, x contiene la


II aproximacion inicial de la soluciono
II Saliendo x tendra la ultima aproximacion.

244
11.12. SOLUCIN POR MNIMOS CUADRADOS

int i, ni, k;
double nrmD, di;

ni = n+l;
for(i=0;i<n;i++)if(fabs(a[i*nl])<=1.e-40)return O;

for( k=l; k <= maxit; k++){


nrmD = 0.0;
for( i=O; i<n; i++){
di = (b[i] - prodXY(&a[i*n], x, n))/a[i*nl];
nrmD += fabs(di);
x[i] += di;
}
if( nrmD <= eps ) return 1;
}
return 2;
}

11.12 Solucin por mnimos cuadrados


Consideremos ahora un sistema de ecuaciones Ax = b, no necesa-
riamente cuadrado, donde A es una matriz m x n cuyas columnas son
linealmente independientes. Esto implica que hay ms filas que colum-
nas, m 2: n, y que adems el rango de A es n. Es muy probable que
este sistema no tenga solucin, es decir, tal vez no existe x que cumpla
exactamente las m igualdades. Se desea que

Ax b,
Ax-b 0,
IIAx-bll 0,
IIAx - bl1 2 0,
IIAx - bll~ O.
Es Posible que lo deseado no se cumpla, entonces se quiere que el in-
cumplimiento (el error) sea lo ms pequeo posible. Se desea minimizar
esa cantidad,
min IIAx - bll~ . (11.15)

245
11. SOLUCIN DE SISTEMAS LINEALES

El vector x que minimice IIAx - bll~ se llama solucin por mnimos cua-
drados. Como se ver ms adelante, tal x existe y es nico (suponiendo
que las columnas de A son linealmente independientes).
Con el nimo de hacer ms clara la deduccin, supongamos que A
es una matriz 4 x 3. Sea f(x) = IIAx - bll~,

f(x) =(a11xl + a12x2 + a13x3 - b1)2 + (a21xl + a22x2 + a23x3 - b2)2+


(a31xl + a32x2 + a33x3 - b3 )2 + (a41xl + a42X2 + a43 x 3 - b4 )2.

11.12.1 Derivadas parciales

Este libro est dirigido principalmente a estudiantes de segundo se-


mestre, quienes todava no conocen el clculo en varias variables. En este
captulo y en el siguiente se requiere saber calcular derivadas parciales.
A continuacin se presenta una breve introduccin al clculo (mecnico)
de las derivadas parciales.
Sea <p una funcin de varias variables con valor real, <p : IR n ---t IR.
Bajo ciertas condiciones de existencia, la derivada parcial de <p con res-
pecto a Xi se obtiene considerando las otras variables como constantes
y derivando <P(Xl, X2, ... , x n ) nicamente con respecto a Xi. Esta derivada
parcial se denota
O<p
OXi .

Evaluada en un punto especfico x, se denota


O<p (x) .
OXi

Por ejemplo, si <p(Xl,X2,X3,X4) = (4xr + 6X4)9 + 5XIX2 + 8X4,


O<p
9(4xr + 6x4)8(12xr) + 5X2,
OXl
o<p
5Xl,
OX2
o<p
0,
OX3
o<p
54( 4xr + 6X4)8 + 8.
OX4

246
11.12. SOLUCIN POR MNIMOS CUADRADOS

11.12.2 Ecuaciones normales

Para obtener el mnimo de 1 se requiere que las tres derivadas par-


ciales, ol/oxl, 01/ox2 y 01/ox3, sean nulas.

01
~ =2(an X l
UX l
+ a12 x 2 + a13 X 3 - bl)an
+ 2(a21 x l + a22 x 2 + a23x3 - b2)a21
+ 2(a31 x l + a32 x 2 + a33X3 - b3)a31
+ 2(a41 x l + a42 x 2 + a43X3 - b4)a41.

Escribiendo de manera matricial,

01
~ =2(Al.X - bl)an + 2(A 2.x - b2)a21 + 2(A3.x - b3)a31
UXl
+ 2(A4.x - b4)a41.

Si B es una matriz y u un vector columna, entonces (BU)i = Bi.u.

2((( Ax h - bl)an + ((Axh - b2)a21 + ((Axh - b3)a31

+((AX)4 - b4 a41) ,
4
2 )Ax - b)i ail,
i=l
4
2 2)A. 1MAx - b)i,
i=l
4
2)AT1.MAx - b)i,
i=l
2AT 1.(Ax - b),
2(AT (Ax - b))l

De manera semejante

2(AT (Ax - b))2'

2(A T (Ax - b))3

247
11. SOLUCIN DE SISTEMAS LINEALES

Igualando a cero las tres derivadas parciales y quitando el 2 se tiene

(AT(Ax - b))l = O,
(AT(Ax - b))2 O,
(AT(Ax - b))3 = O

Es decir,
AT(Ax - b) O,
ATAx ATb. (11.16)
Las ecuaciones (11.16) se llaman ecuaciones normales para la solucin
(o seudosolucin) de un sistema de ecuaciones por mnimos cuadrados.
La matriz ATA es simtrica de tamao n x n. En general, si A es
una matriz m x n de rango r, entonces A T A tambin es de rango r
(ver [Str86]). Como se supuso que el rango de A es n, entonces ATA es
invertible. Ms an, ATA es definida positiva.
Por ser ATA invertible, hay una nica solucin de (11.16), o sea,
hay un solo vector x que hace que las derivadas parciales sean nulas.
En general, las derivadas parciales nulas son simplemente una condicin
necesaria para obtener el mnimo de una funcin (tambin lo es para
mximos o para puntos de silla), pero en este caso, como ATA es defi-
nida positiva, f es convexa, y entonces anular las derivadas parciales se
convierte en condicin necesaria y suficiente para el mnimo.
En resumen, si las columnas de A son linealmente independientes, en-
tonces la solucin por mnimos cuadrados existe y es nica. Para obtener
la solucin por mnimos cuadrados se resuelven las ecuaciones normales.
Como A T A es definida positiva, (11.16) se puede resolver por el mto-
do de Cholesky. Si m 2: n y al hacer la factorizacin de Cholesky resulta
que ATA no es definida positiva, entonces las columnas de A son lineal-
mente dependientes.
Si el sistema Ax = b tiene solucin exacta, sta coincide con la
solucin por mnimos cuadrados.
Ejemplo 11.17. Resolver por mnimos cuadrados:

-~ -21 3O 1 1 [
[ = 3.1
8.9 1
[ -2
5
2
4 -2
1
Xl
X2
X3
-3.1
0.1

248
11.12. SOLUCIN POR MNIMOS CUADRADOS

Las ecuaciones normales dan:

[ ;~ ~~ =~~14 1[XXX3~ 1
-15 -12
4.0
-20.5
[ 23.4
1
La solucin por mnimos cuadrados es:

x = (2.0252, -1.0132, 2.9728).

El error, Ax - b, es:
-0.0628 ]
0.0196 <>
-0.0039 .
[
0.0275

Ejemplo 11.18. Resolver por mnimos cuadrados:

Las ecuaciones normales dan:

Al tratar de resolver este sistema de ecuaciones por el mtodo de Cho-


leskYj no se puede obtener la factorizacin de Cholesky, luego ATA no
es definida positiva, es decir, las columnas de A son linealmente depen-
dientes. Si se aplica el mtodo de Gauss, se obtiene que ATA es singular
y se concluye que las columnas de A son linealmente dependientes. <>

Ejemplo 11.19. Resolver por mnimos cuadrados:

-~ -~] [Xl]
[ -25 X22
= [ ~]
-6
4 6

249
11. SOLUCIN DE SISTEMAS LINEALES

Las ecuaciones normales dan:

34 20] [
[ 20 25
Xl ]
X2 [ i~ ]
La solucin por mnimos cuadrados es:

X = (2, -1).

El error, Ax - b, es:

[~ ]
En este caso, el sistema inicial tena solucin exacta y la solucin por
mnimos cuadrados coincide con ella. <>

La implementacin eficiente de la solucin por mnimos cuadrados,


va ecuaciones normales, debe tener en cuenta algunos detalles. No es
necesario construir toda la matriz simtrica ATA (n 2 elementos). Basta
con almacenar en un arreglo de tamao n(n + 1)/2 la parte triangular
superior de ATA.
Este almacenamiento puede ser por filas, es decir, primero los n ele-
mentos de la primera fila, enseguida los n - 1 elementos de la segunda
fila a partir del elemento diagonal, despus los n - 2 de la tercera fila
a partir del elemento diagonal y as sucesivamente hasta almacenar un
solo elemento de la fila n. Si se almacena la parte triangular superior
de ATA por columnas, se almacena primero un elemento de la primera
columna, enseguida dos elementos de la segunda columna y as sucesi-
vamente. Cada una de las dos formas tiene sus ventajas y desventajas.
La solucin por el mtodo de Cholesky debe tener en cuenta este tipo
de estructura de almacenamiento de la informacin.
Otros mtodos eficientes para resolver sistemas de ecuaciones por
mnimos cuadrados utilizan matrices ortogonales de Givens o de House-
holder.

250
11.12. SOLUCIN POR MNIMOS CUADRADOS

Ejercicios

11.1 Resuelva el sistema Ax = b, donde

11.2 Resuelva por el mtodo de Gauss con pivoteo parcial el sistema


Ax = b, donde

4 -12 -10] [6 ]
A = -12 45 30 ,b = -9 .
[ -10 30 41 -31

11.3 Halle la factorizacin LU = PApara la matriz A del ejercicio


anterior. Resuelva el sistema Ax = e, con

-36 ]
e= 126 .
[ 122

11.4 Resuelva por el mtodo de Gauss con pivoteo parcial el sistema


Ax = b, donde

4 -12 -10] [ -18 ]


A = -12 45 30 ,b = 63.
[ -10 45 25 60

11.5 Resuelva por el mtodo de Gauss con pivoteo parcial el sistema


Ax = b, donde

4 -15 -10] [ -42 ]


A= -12 45 15 ,b = 96.
[ -10 75/2 25 105

11.6 Resuelva por el mtodo de Cholesky el sistema Ax = b, donde

A= [-1~
-10
-!~30 -!~],
41
b= [ -~].
-31

251
11. SOLUCIN DE SISTEMAS LINEALES

11.1 Resuelva por el mtodo de Cholesky el sistema Ax = b, donde

442 562 846 -2]


-3 [8]
10
A=
[ -2 -4 ,b
-3 -4
14 .
3
=
-6

11.8 Resuelva por el mtodo de Cholesky el sistema Ax = b, donde

A = [ -~4 -2~ 2] [ 4]
~ ,b = : .

11.9 Resuelva por el mtodo de Gauss-Seidel el sistema Ax = b, donde

A =
[51 -1]
2 4
1 2
1
10
,b = [ 9]20
48
.

11.10 Resuelva por el mtodo de Gauss-Seidel el sistema Ax = b, donde

4 -12 -10] [6]


A =
[ -10
-12 45
30
30
41
, b= -9
-31
.

11.11 Resuelva por el mtodo de Gauss-Seidel el sistema Ax = b, donde

A=
[
1
6 4
2 57] , b = [10]15 .
8 9 3 20

11.12 Resuelva por mnimos cuadrados el sistema Ax = b, donde

147 825 3]
6 [10]
15
A =
[ 10 12
9 ,b =
15
20 .
25

11.13 Resuelva por mnimos cuadrados el sistema Ax = b, donde

~l, b=[~l
1 2
A= 4 5

1~
8
[
11 12 25

252
11.12. SOLUCIN POR MNIMOS CUADRADOS

11.14 Utilizando apuntadores dobles para almacenar la matriz A, elabore


un programa (y una funcin) que calcule el determinante de A.

11.15 Utilizando apuntadores dobles para almacenar la matriz A, ha-


ga un programa (y una funcin) para resolver un sistema por el
mtodo de Gauss con pivoteo parcial.

11.16 Utilizando apuntadores dobles para almacenar la matriz rectangu-


lar A, elabore un programa (y una funcin) que obtenga la forma
escalonada reducida por filas.

11.17 Utilizando apuntadores dobles para almacenar la matriz A, ha-


ga un programa (y una funcin) para resolver un sistema por el
mtodo de Cholesky.

11.18 Utilizando apuntadores dobles para almacenar la matriz A, ha-


ga un programa (y una funcin) para resolver un sistema por el
mtodo de Gauss-Seidel.

11.19 La informacin indispensable de una matriz simtrica es la parte


superior, o sea, n(n+ 1)/2 datos. sta se puede almacenar, fila por
fila, en un vector

que ocupa aproximadamente la mitad del espacio de los n 2 elemen-


tos de la matriz completa. Haga un programa para almacenar de
A nicamente la parte superior, hacer la factorizacin de Cholesky
y resolver el sistema Ax = b.

11.20 Resuelva por el mtodo de Cholesky el sistema Ax = b, donde

4 -2 2 O O O O -8
-2 5 -1 2 O O O 12
2 -1 5 4 6 O O 8
A= O 2 4 6 5 -2 O , b= 12
O O 6 5 11 4 3 23
O O O -2 4 12 2 18
O O O O 3 2 14 -6

11.21 Se dice que una matriz simtrica es una matriz banda de ancho
2m -1 si aij = O cuando Ij - i I ~ m. Demuestre que si A es definida

253
11. SOLUCIN DE SISTEMAS LINEALES

positiva y la factorizacin de Cholesky es A = UTU, entonces U


es una matriz triangular superior banda, de ancho m: aij = O si
i > j y aij = O si j - i 2:: m. En el ejercicio anterior m = 3.

11.22 La informacin indispensable de una matriz simtrica de ancho de


banda 2m - 1 se puede almacenar en una matriz m x n. Para la
matriz del penltimo ejercicio,
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 nicamente la banda su-
perior, hacer la factorizacin de Cholesky y resolver el sistema
Ax = b.
11.23 Se define la densidad de una matriz de tamao m x n como el
porcentaje de componentes no nulos de una matriz
d d(A) nmero de aij no nulos
d enSl a = 100.
mn
Una matriz, generalmente de tamao muy grande, se llama dis-
persa o rala, (sparse) , si su densidad es pequea, es decir menor
que 10 %, o menor que 5 %, o 1 %. Estas matrices se presentan
con frecuencia en problemas reales de fsica, ingeniera, economa,
etc. La informacin indispensable, los elementos no nulos, se puede
almacenar por una lista de triplas
(il,jl, v)
(i2,j2, V2)

(ik,jk,Vk)

donde aik,jk = Vk. Haga un programa para almacenar de A nica-


mente los elementos no nulos y resolver por el mtodo de Gauss-
Seidel el sistema Ax = b.

254
12

Solucin de ecuaciones

Uno de los problemas ms corrientes en matemticas consiste en


resolver una ecuacin, es decir, encontrar un valor x* E lR que satisfaga

f(x) = 0,

donde f es una funcin de variable y valor real, o sea,

f:lR---+lR.

Este x* se llama solucin de la ecuacin. A veces tambin se dice que x*


es una raz. Algunos ejemplos sencillos de ecuaciones son:

x5 - 3x4 + 10x - 8 0,
eX - x 3 + 8 0,
. x2 +x
---;-----,--- - x O.
cos(x - 1) + 2

En algunos casos no se tiene una expresin sencilla de f, sino que f (x)


corresponde al resultado de un proceso; por ejemplo:

-00 e
_t 2
dt - 0.2 = O.

Lo mnimo que se le exige a f es que sea continua. Si no es continua en


todo lR, por lo menos debe ser continua en un intervalo [a, b] donde se
busca la raz. Algunos mtodos requieren que f sea derivable. Para la

255
12. SOLUCIN DE ECUACIONES

aplicacin de algunos teoremas de convergencia, no para el mtodo en


s, se requieren derivadas de orden superior.
Los mtodos generales de solucin de ecuaciones sirven nicamente
para hallar races reales. Algunos mtodos especficos para polinomios
permiten obtener races complejas.
Los mtodos presuponen que la ecuacin f(x) = O tiene solucin. Es
necesario, antes de aplicar mecnicamente los mtodos, estudiar la fun-
cin, averiguar si tiene races, ubicarlas aproximadamente. En algunos
casos muy difciles no es posible hacer un anlisis previo de la funcin,
entonces hay que utilizar de manera mecnica uno o varios mtodos,
pero sabiendo que podran ser ineficientes o, simplemente, no funcionar.
La mayora de los mtodos parten de xo, aproximacin inicial de x* ,
a partir del cual se obtiene Xl. A partir de Xl se obtiene X2, despus X3,
y as sucesivamente se construye la sucesin {xd con el objetivo, no
siempre cumplido, de que

lim Xk=X*.
k---+oo

El proceso anterior es tericamente infinito, y obtendra la solucin des-


pus de haber hecho un nmero infinito de clculos. En la prctica el
proceso se detiene cuando se obtenga una aproximacin suficientemente
buena de x*. Esto querra decir que el proceso se detendra cuando

IXk-X*I:SE,

para un E dado. El anterior criterio supone el conocimiento de x*, que es


justamente lo buscado. Entonces se utiliza el criterio, ste si aplicable,

If(Xk)1 :s E.
En la mayora de los casos, cuanto ms cerca est Xo de x*, ms rpida-
mente se obtendr una buena aproximacin de x*.
Otros mtodos parten de un intervalo inicial [ao, boj, en el cual se
sabe que existe una raz x*. A partir de l, se construye otro intervalo
[al, blJ, contenido en el anterior, en el que tambin est x* y que es de
menor tamao. De manera anloga se construye [a2, b2]. Se espera que

256
12.1. MTODO DE NEWTON

la sucesin formada por los tamaos tienda a O. Explcitamente,

X* E [ao, bol,
[aHl, bk+1l e [ak, bk], k = 1,2, ... ,
x* E [ak, bk], k = 1,2, ... ,
lim (bk - ak) O.
k-.oo

En este caso, el proceso se detiene cuando se obtiene un intervalo sufi-


cientemente pequeo,
Ibk - akl ~ .
Cualquiera de los puntos del ltimo intervalo es una buena aproximacin
de x*.

12.1 Mtodo de Newton


Tambin se conoce como el mtodo de Newton-Raphson. Dado xo,
se construye la recta tangente en (xo, f (xo) ). El valor de x donde esta
recta corta el eje x es el nuevo valor Xl. Ahora se construye la recta
tangente en el punto (Xl, f(Xl))' El punto de corte entre la recta y el eje
X determina X2

Figura 12.1 Mtodo de Newton.

257
12. SOLUCIN DE ECUACIONES

En el caso general, dado Xk, se construye la recta tangente en el


punto (Xk, f(Xk)),

y = f'(Xk)(X - Xk) + f(Xk).


Para y = O se tiene x = Xk+l,
0= f'(Xk)(Xk+l - Xk) + f(Xk).
Entonces
f(Xk)
Xk+l Xk - f'(Xk) (12.1)

Ejemplo 12.1. Aplicar el mtodo de Newton a la ecuacin x 5 - 3x4 +


lOx - 8 = O, partiendo de Xo = 3.

k Xk f(Xk) f'(Xk)
O 3.000000 2.200000E+01 91.000000
1 2.758242 5. 589425E+00 47.587479
2 2.640786 9.381331E-01 32.171792
3 2.611626 4.892142E-02 28.848275
4 2.609930 1.590178E-04 28.660840
5 2.609924 1.698318E-09 28.660228
6 2.609924 -2. 838008E-15 28.660227

Las races reales del polinomio x 5 - 3x4 + lOx - 8 son: 2.6099, 1.3566,
1. Tomando otros valores iniciales el mtodo converge a estas races. Si
se toma Xo = 2.1, se esperara que el mtodo vaya hacia una de las races
cercanas, 2.6099 o 1.3566 . Sin embargo, hay convergencia hacia 1.

k Xk f(Xk) f'(Xk)
O 2.100000 -4.503290e+00 -3.891500
1 0.942788 -1.97425ge-01 3.894306
2 0.993484 -1.988663e-02 3.103997
3 0.999891 -3. 272854e-04 3.001745
4 1.000000 -9.509814e-08 3.000001
5 1.000000 -7.993606e-15 3.000000

El mtodo de Newton es muy popular por sus ventajas:

258
12.1. MTODO DE NEWTON

Sencillez.
Generalmente converge.
En la mayora de los casos, cuando converge, lo hace rpidamente.

Tambin tiene algunas desventajas:

Puede no converger.

Presenta problemas cuando f'(Xk) ~ o.


Requiere poder evaluar, en cada iteracin, el valor f'(x).

La implementacin del mtodo de Newton debe tener en cuenta va-


rios aspectos. Como no es un mtodo totalmente seguro, debe estar
previsto un nmero mximo de iteraciones, llamado por ejemplo maxi t.
Para una precisin e j, la detencin deseada para el proceso iterativo
se tiene cuando !f(Xk)! :S ej. Otra detencin posible se da cuando dos
valores de x son casi iguales, es decir, cuando !Xk - Xk-l! :S ex. Se
acostumbra a utilizar el cambio relativo, o sea, !Xk - Xk-l!I!Xk! :S ex.
Para evitar las divisiones por cero, se usa !Xk - Xk-l!/(l + !Xk!) :S ex.
Finalmente, siempre hay que evitar las divisiones por cero o por valo-
res casi nulos. Entonces, otra posible parada, no deseada, corresponde
a !f'(Xk)! :S eo. El algoritmo para el mtodo de Newton puede tener el
siguiente esquema:

datos: xO, maxit, e j, ex, eO


xk = xO
fx = f (xk), fpx = f' (xk)
para k=l, ... ,maxit
si Ifpx I :S eo ent salir
fJ = fx/fpx
xk = xk-fJ
fx = f (xk) , fpx = f' (xk)
si Ifxl :S ej ent salir
si I fJ I / (1 + Ixk 1) :S e x ent salir
fin-para k

Para la implementacin en C, es necesario determinar cmo se evala


f y f' Fundamentalmente hay dos posibilidades:

259
12. SOLUCIN DE ECUACIONES

Hacer una funcin de C para evaluar j y otra para evaluar 1'.


Hacer una funcin de C donde se evale al mismo tiempo j y J'.

Cada una de estas posibilidades puede hacerse con nombres fijos para
las funciones o por medio de apuntadores a funciones. En el mtodo de
Newton, en cada iteracin se calcula una vez j(x) y una vez j'(X).
Cuando se cambia j es necesario cambiar j'. Por razones de sencillez
en la escritura, la siguiente implementacin en C utiliza un nombre fijo
para una funcin donde al mismo tiempo se evala j y j'.

double newton(double xO, int maxit, double epsF,


double epsX, double epsO, int &indic)
{
II Metodo de Newton para resolver f(x) o.
II
II f(x) esta definida en fxfpx.
II Esta ultima funcion tambien calcula f'(x)
II
II indic valdra:
II 1 si f(xk) 1 <= epsF
II 2 si 1 xk-xkl I/( 1+ Ixkl ) <= epsX
II si 1 f'(xk ) 1 <= epsO
II
3 si en maxit iteraciones no se ha tenido
II convergencia
II
II Sea r el valor devuelto por newton.
II Si indic= 1, r es una buena aproximacion de una raiz
II Si indic= 2, r es una buena aproximacion de una raiz
II o el ultimo xk calculado.
II 3, r es el ultimo xk calculado.
II 0, r es el ultimo xk calculado.
II xO es una aproximacion inicial de la raiz.

int k;
double delta, xk, fx, fpx;

xk xO;
fx fxfpx(xk, fpx);

260
12.1. MTODO DE NEWTON

for( k=l; k<= maxit; k++){


if( fabs(fpx) <= epsO ){
indic = O;
return xk;
}
delta = fx/fpx;
xk = xk - delta;
fx = fxfpx(xk, fpx);
if( fabs(fx) <= epsF ){
indic = 1;
return xk;
}
if( fabs(delta)/( 1.0+fabs(xk) ) <= epsX ){
indic = 2;
return xk;
}
}
indic = 3;
return xk;
}
11---------------------------------------------------------
double fxfpx(double x, double &fpx)
{
II Calculo de f(x) y f'(x)
II Devuelve f(x)
II La variable fpx tendra el valor f'(x)

double fx;

fx = x*x*x*x*x - 3.0*x*x*x*x + 10.0*x - 8.0;


fpx = 5.0*x*x*x*x - 12.0*x*x*x + 10.0;

return fx;
}

La llamada a la funcin newton puede ser semejante a

261
12. SOLUCIN DE ECUACIONES

x = newton(3.0, 20, 1.0E-10, 1.0E-15, 1.0E-30, resul);


if( resul == 1 ) ...

12.1.1 Orden de convergencia

Definicin 12.1. Sea {xd una sucesin de nmeros reales con lmite
L. Se dice que la convergencia tiene orden de convergencia p, si pes
el mayor valor tal que el siguiente lmite existe y es finito.

lim IX k+1 - LI
k--->oo IXk - Llp = j3 < 00
En este caso se dice que j3 es la tasa de convergencia. Cuando el orden
es 1, se dice que la convergencia es lineal.

Cuando el orden es 2, se dice que la convergencia es cuadrtica.


De acuerdo con la definicin, lo ideal es tener rdenes altos con tasas
pequeas. Una convergencia lineal con tasa 1 es una convergencia muy
lenta; por ejemplo Xk = l/k. La convergencia de Xk = 1/3 k es ms
rpida, es lineal pero con tasa 1/3. La sucesin definida por Xo = 4/5,
Xk+l = x~ tiene convergencia cuadrtica.
Cuando se tiene una sucesin {x k } en ]Rn, para la definicin del orden
de convergencia se usa

lim II X k+1 - LII .


k--->oo Ilxk - LIiP

Teorema 12.1. Sean a < b, 1 = la, b[, f : 1 --+]R, x* El, f(x*) = 0, l'
y 1" existen y son continuas en 1, 1'(x*) f:. 0, {Xk} la sucesin definida
por 12.1. Si Xo est suficientemente cerca de x*, entonces

lim Xk *
x, (12.2)
k--->oo
IXk+1 - x*1 11"(x*)1
lim (12.3)
k--->oo IXk - x*1 2 21f'(x*)1

La demostracin de este teorema est en varios libros; por ejemplo,


en [Atk78] o en [Sch91]. El primer resultado dice que la sucesin converge
a x*. El segundo dice que la convergencia es cuadrtica o de orden su-
perior. La frase "xo est suficientemente cerca de x*, entonces ... " quiere

decir que existe E > tal que si Xo E [x* - E, x* + E] ~ 1, entonces ...

262
12.2. MTODO DE LA SECANTE

A manera de comprobacin, despus de que se calcul una raz, se


puede ver si la sucesin muestra aproximadamente convergencia cua-
drtica. Sea ek = Xk - x*. La sucesin lekl/lek-112 debera acercarse
a 1f"(x*)11 (2If'(x*)I). Para el ejemplo anterior 1f"(x*)/(2If'(x*)I)
16/(2 x 3) = 2.6666 .

k Xk lekl lekl/l ek-11 2


O 2.1000000000000001 1.100000e+00
1 0.9427881279712185 5.721187e-02 4. 728254e-02
2 0.9934841559110774 6.515844e-03 1.990666e+00
3 0.9998909365826297 1.090634e-04 2. 568844e+00
4 0.9999999683006239 3. 169938e-08 2.664971e+00
5 0.9999999999999973 2.664535e-15 2.651673e+00

12.2 Mtodo de la secante

Uno de los inconvenientes del mtodo de Newton es que necesita


evaluar f'(x) en cada iteracin. Algunas veces esto es imposible o muy
difcil. Si en el mtodo de Newton se modifica la frmula 12.1 reempla-
zando f'(Xk) por una aproximacin

entonces se obtiene

(12.4)

En el mtodo de Newton se utilizaba la recta tangente a la curva en el


punto (Xk, f(Xk)). En el mtodo de la secante se utiliza la recta (secante)
que pasa por los puntos (Xk, f(Xk)) Y (Xk-l, f(Xk-l)).

263
12. SOLUCIN DE ECUACIONES

Figura 12.2 Mtodo de la secante.

Ejemplo 12.2. Aplicar el mtodo de la secante a la ecuacin x 5 - 3x4 +


10x - 8 = O, partiendo de Xo = 3.
k Xk f(Xk)
O 3.000000 2.200000e+01
1 3.010000 2. 292085e+01
2 2.761091 5. 725624e+00
3 2.678210 2.226281e+00
4 2.625482 4. 593602e-01
5 2.611773 5.317368e-02
6 2.609979 1.552812e-03
7 2.609925 5.512240e-06
8 2.609924 5.747927e-10
9 2.609924 -2.838008e-15
Mediante condiciones semejantes a las exigidas en el teorema 12.1
se muestra (ver [Sch91]), que el mtodo de la secante tiene orden de
convergencia
1 + J5 ~ 1.618
2
Como el mtodo de la secante es semejante al mtodo de Newton, en-
tonces tienen aproximadamente las mismas ventajas y las mismas des-
ventajas, salvo dos aspectos:

264
12.2. MTODO DE LA SECANTE

La convergencia del mtodo de la secante, en la mayora de los


casos, es menos rpida que en el mtodo de Newton.

El mtodo de la secante obvia la necesidad de evaluar las derivadas.

El esquema del algoritmo es semejante al del mtodo de Newton.


Hay varias posibles salidas, algunas deseables, otras no.

datos: xO, maxit, Ej, Ex, EO


xl = xO + 0.1, fO = f(xO), fl f(xl)
para k=l, ... ,maxit
den = fi-fO
si Iden I :S EO ent salir
8 =f1*(xl-xO)/den
x2 = xl - 8, f2 = f (x2)
si If21 :S Ej ent salir
si 181/C1+lx21) :S Ex ent salir
xO = xl, fO = fl, xl = x2, fl f2
fin-para k

Para la implementacin en e, la evaluacin de f(x) puede hacerse en


una funcin con nombre fijo o por medio de un apuntador a funcin. En
la siguiente implementacin la evaluacin de f(x) se hace en la funcin
con prototipo double f (double x); .

double secante(double xO, int maxit, double epsF,


double epsX, double epsO, int &indic)
{
II Metodo de la secante para resolver t(x) = O.
II
II f(x) esta definida en la funcion f
II
II indic valdra:
II 1 si f(x2) I <= epsF
II 2 si I x2-xl I/( 1+ Ix21 ) <= epsX
II O si I f(xl) - f(xO) I <= epsO
II 3 si en maxit iteraciones no se ha tenido
II convergencia
II
265
12. SOLUCIN DE ECUACIONES

II Sea r el valor devuelto por secante.


II Si indic= 1, r es una buena aproximacion de una raiz
II Si indic= 2, r es una buena aproximacion de una raiz
II o el ultimo x2 calculado.
II = 3, r es el ultimo x2 calculado.
II = O, r es el ultimo x2 calculado.
II xO es una aproximacion inicial de la raiz.

int k;
double delta, xl, x2, fO, fl, f2, den;

xl xO + 0.01;
fO f(xO);
fl f(xl);
for( k=l; k<= maxit; k++){
den = fl - fO;
if( fabs(den) <= epsO ){
indic = O;
return xl;
}
delta = fl*(xl-xO)/den;
x2 = xl - delta;
f2 = f(x2);
if( fabs(f2) <= epsF ){
indic = 1;
return x2;
}
if( fabs(delta)/C 1.0+fabs(x2) ) <= epsX ){
indic = 2;
return x2;
}
xO xl; xl x2; fO f1; f1 f2;
}
indic = 3;
return x2;
}
11---------------------------------------------------------
double f(double x)

266
12.3. MTODO DE LA BISECCIN

{
II Calculo de f(x)

12.3 Mtodo de la biseccin


Si la funcin f es continua en el intervalo [a, b], a < b, Y si f(a) y
f (b) tienen signo diferente,
f(a)f(b) < 0,

entonces f tiene por lo menos una raz en el intervalo. Este mtodo ya


se vio en el captulo sobre funciones.

Usualmente se define el error asociado a una aproximacin como

En el mtodo de la biseccin, dado el intervalo [ak, bk], ak < bk , no se


tiene un valor de Xk. Se sabe que en [ak, bkl hay por lo menos una raz.
Cualquiera de los valores en el intervalo podra ser Xk. Sea Ek el mximo
error que puede haber en la iteracin k,

Como el tamao de un intervalo es exactamente la mitad del anterior

entonces

Finalmente

267
12. SOLUCIN DE ECUACIONES

Obviamente Ek -t OY
Ek 1 1
--=--t-
Ek-l 2 2
Esto quiere decir que la sucesin de cotas del error tiene convergencia
lineal (orden 1) y tasa de convergencia 1/2.
En el mtodo de la biseccin se puede saber por anticipado el nmero
de iteraciones necesarias para obtener un tamao deseado,

bk - ak < E,

(~) k (bo _ ao) < E,

(~)k <
-
E
bo - ao
,
bo - ao
2k >
E
1 bo-ao
klog2 > og ,
E
log bQ ~ aQ
k >
log2

Por ejemplo, si el tamao del intervalo inicial es 3, si E = LOE - 6,


entonces en k = 22 (~21.52) iteraciones se obtiene un intervalo sufi-
cientemente pequeo.

12.4 Mtodo de Regula Falsi


Igualmente se conoce con el nombre de falsa posicin. Es una modi-
ficacin del mtodo de la biseccin. Tambin empieza con un intervalo
[ao, boj donde f es continua y tal que f(ao) y f(bo) tienen signo diferente.
En el mtodo de biseccin, en cada iteracin, nicamente se tiene en
cuenta el signo de f(ak) Y de f(b k ), pero no sus valores: no se est utili-
zando toda la informacin disponible. Adems es de esperar que si f(ak)
est ms cerca de O que f(bk), entonces puede ser interesante considerar,
no el punto medio, sino un punto ms cercano a ak. De manera anloga,
si f(bk) est ms cerca de O que f(ak), entonces puede ser interesante
considerar, no el punto medio, sino un punto ms cercano a bk.

268
12.4. MTODO DE REGULA FALSI

En el mtodo de Regula Falsi se considera el punto donde la recta


que pasa por (ak, f(ak)), (b k , f(b k )) corta el eje x. Como f(ak) Y f(bk)
tienen signo diferente, entonces el punto de corte Ck queda entre ak Y bk.

y = f(x)

Figura 12.3 Regula Falsi.

La ecuacin de la recta es:


y _ f(ak) = f(bk) - f(ak) (x - ak)
bk - ak
Cuando y = O se tiene el punto de corte x = Ck,

(12.5)

Esta frmula es semejante a la de la secante. Como f(ak) y f(bk) tienen


signo diferente, entonces f(bk) - f(ak) tiene signo contrario al de f(ak).
Entonces - f(ak)/(f(b k ) - f(ak)) > o. Usando de nuevo que f(ak) Y
f(bk) tienen signo diferente, entonces If(ak)I/lf(bk) - f(ak)1 < 1. Luego
0< - f(ak)/(f(bk) - f(ak)) < 1. Esto muestra que ak < Ck < bk
Partiendo de un intervalo inicial [ao, bol, en la iteracin k se tiene
el intervalo [ak, bkl donde f es continua y f(ak), f(bk) tienen diferen-
te signo. Se calcula Ck el punto de corte y se tienen tres posibilidades
excluyentes:

269
12. SOLUCIN DE ECUACIONES

f(Ck) ~ O; en este caso Ck es, aproximadamente, una raz;

f(ak)f(ck) < O; en este caso hay una raz en el intervalo [ak,ckl =


[ak+1, bk+ll;
f(ak)f(ck) > O; en este caso hay una raz en el intervalo [Ck, bkl =
[ak+l, bk+1]'
Ejemplo 12.3. Aplicar el mtodo de Regula Falsi a la ecuacin x 5 -
3x4 + lOx - 8 = O, partiendo de [2,5].

k ak bk f(ak) f(bk) Ck f(Ck)


O 2.000000 5 -4.000000 1292 2.009259 -4.054857
1 2.009259 5 -4.054857 1292 2.018616 -4.108820
2 2.018616 5 -4.108820 1292 2.028067 -4.161744
3 2.028067 5 -4.161744 1292 2.037610 -4.213478
4 2.037610 5 -4.213478 1292 2.047239 -4.263862
5 2.047239 5 -4.263862 1292 2.056952 -4.312734
10 2.096539 5 -4.489666 1292 2.106594 -4.528370
20 2.198548 5 -4.739498 1292 2.208787 -4.744664
30 2.298673 5 -4.594020 1292 2.308244 -4.554769
335 2.609924 5 -0.000001 1292 2.609924 -0.000001

Como se ve, la convergencia es muy lenta. El problema radica en que


en el mtodo de Regula Falsi no se puede garantizar que

lim (b k - ak) = O.
k--->oo

Esto quiere decir que el mtodo no es seguro. Entonces, en una imple-


mentacin, es necesario trabajar con un nmero mximo de iteraciones.

12.5 Modificacin del mtodo de Regula Falsi


Los dos mtodos, biseccin y Regula Falsi, se pueden combinar en
uno solo de la siguiente manera. En cada iteracin se calcula mk Y Ck.
Esto define tres subintervalos en [ak, bk]' En por lo menos uno de ellos se
tiene una raz. Si los tres subintervalos sirven, se puede escoger cualquie-
ra, o mejor an, el de menor tamao. En un caso muy especial, cuando
mk Y Ck coinciden, se tiene simplemente una iteracin del mtodo de
biseccin.

270
12.5. MODIFICACIN DEL MTODO DE REGULA FALSI

En cualquiera de los casos

entonces

lo que garantiza que


lim (bk - ak) = O.
k~oo

Ejemplo 12.4. Aplicar la modificacin del mtodo de Regula Falsi a la


ecuacin x 5 - 3x 4 + lOx - 8 = O, partiendo de [2, 5].

k a b f(a) f(b) e f(c) m f(m)


O 2.0000 5.0000 -4.00e+0 1.2ge+3 2.0093 -4.0e+0 3.5000 1.0e+2
1 2.0093 3.5000 -4.05e+0 1.02e+2 2.0662 -4.4e+0 2.7546 5.4e+0
2 2.0662 2.7546 -4.36e+0 5.42e+0 2.3731 -4.2e+0 2.4104 -3.8e+0
3 2.4104 2.7546 -3.80e+0 5.42e+0 2.5523 -1.5e+0 2.5825 -7.4e-1
4 2.5825 2.7546 -7.44e-1 5.42e+0 2.6033 -1.ge-1 2.6686 1.ge+0
5 2.6033 2.6686 -1.87e-1 1.88e+0 2.6092 -2.0e-2 2.6360 7.8e-1
6 2.6092 2.6360 -2.00e-2 7.84e-1 2.6099 -9.7e-4 2.6226 3.7e-1
7 2.6099 2.6226 -9.73e-4 3.72e-1 2.6099 -2.3e-5 2.6162 1.8e-1
8 2.6099 2.6162 -2.33e-5 1.83e-1 2.6099 -2.8e-7 2.6131 9.1e-2
9 2.6099 2.6131 -2.81e-7 9.10e-2 2.6099 -1.7e-9

La modificacin es mucho mejor que el mtodo de Regula Falsi.


Adems, el nmero de iteraciones de la modificacin debe ser menor
o igual que el nmero de iteraciones del mtodo de biseccin. Pero para
comparar equitativamente el mtodo de biseccin y la modificacin de
Regula Falsi, es necesario tener en cuenta el nmero de evaluaciones de
f(x).
En el mtodo de biseccin, en k iteraciones, el nmero de evaluacio-
nes de f est dado por:

nbisec = 2+ kbisec .

En la modificacin de Regula Falsi,

nmodif = 2 + 2 kmodif .

271
12. SOLUCIN DE ECUACIONES

12.6 Mtodo de punto fijo


Los mtodos vistos se aplican a la solucin de la ecuacin f(x) = O.
El mtodo de punto fijo sirve para resolver la ecuacin

g(x) = x. (12.6)

Se busca un x* tal que su imagen, por medio de la funcin g, sea el


mismo x*. Por tal motivo se dice que x* es un punto fijo de la funcin
g.
La aplicacin del mtodo es muy sencilla. A partir de un Xo dado, se
aplica varias veces la frmula

Xk+l = g(Xk). (12.7)

Se espera que la sucesin {xd construida mediante (12.7) converja hacia


x*. En algunos casos el mtodo, adems de ser muy sencillo, es muy
eficiente; en otros casos la eficiencia es muy pequea; finalmente, en
otros casos el mtodo definitivamente no sirve.
Ejemplo 12.5. Resolver x 3 + x2 + 6x + 5 = O. Esta ecuacin se puede
escribir en la forma
x 3 + x2 + 5
x=
6
Aplicando el mtodo de punto fijo a partir de Xo = -1 se tiene:

Xo -1
Xl -0.833333
X2 -0.852623
x3 -0.851190
X4 -0.851303
x5 -0.851294
X6 -0.851295
x7 -0.851295
X8 -0.851295

Entonces se tiene una aproximacin de una raz, x* ~ -0.851295. En


este caso el mtodo funcion muy bien. Utilicemos ahora otra expresin
para X = g(x):
x 3 +6x +5
x=
X

272
12.6. MTODO DE PUNTO FIJO

Aplicando el mtodo de punto fijo a partir de Xo = -0.851, muy buena


aproximacin de la raz, se tiene:

Xo -0.8510
Xl -0.8488
X2 -0.8294
X3 -0.6599
X4 1.1415
X5 -11.6832
X6 -142.0691
X7 -2.0190e+4

En este caso se observa que, aun partiendo de una muy buena apro-
ximacin de la solucin, no hay convergencia. <>

Antes de ver un resultado sobre convergencia del mtodo de pun-


to fijo, observemos su interpretacin grfica. La solucin de g(x) = X
est determinada por el punto de corte, si lo hay, entre las grficas
y = g(x) y y = x.

Figura 12.4 Punto fijo.

Despus de dibujar las dos funciones, la construccin de los puntos


se hace de la siguiente manera. Despus de situar el valor
Xl, X2, x3 ...
Xo sobre el eje x, para obtener el valor Xl, se busca verticalmente la

273
12. SOLUCIN DE ECUACIONES

curva y = g(x). El punto obtenido tiene coordenadas (xQ,g(xQ)), o sea,


(XQ, Xl). Para obtener X2 = g(XI) es necesario inicialmente resituar Xl
sobre el eje x, para lo cual basta con buscar horizontalmente la recta
y = X para obtener el punto (Xl, Xl). A partir de este punto se puede
obtener X2 buscando verticalmente la curva y = g(x). Se tiene el punto
(Xl, g(x)), o sea, (Xl, 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+I), y a partir del punto obtenido buscar horizontalmente en la
recta y = X el punto (Xk+1, Xk+l). 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 grficamente la
utilizacin del mtodo; en los dos primeros casos hay convergencia; en
los otros dos no hay, aun si la aproximacin inicial es bastante buena.

Figura 12.5.a Mtodo de punto fijo.

274
12.6. MTODO DE PUNTO FIJO

y=x

y = g(x)

X2 X* X3 Xl

Figura 12.5.b Mtodo de punto fijo.

y=x

x* Xo X2 X3 X4

Figura 12.5.c Mtodo de punto fijo.

275
12. SOLUCIN DE ECUACIONES

y=x

Figura 12.5.d Mtodo de punto fijo.

En seguida se presentan dos teoremas (demostracin en [Atk78]) so-


bre la convergencia del mtodo de punto fijo; el primero es ms general
y ms preciso, el segundo es una simplificacin del primero, de ms fcil
aplicacin para ciertos problemas.

Teorema 12.2. Sea 9 continuamente diferenciable en el intervalo [a, b],


tal que

g([a, b]) ~ [a, b],


19'(x)1 < 1, para todo x E [a, b].

Entonces existe un nico x* en [a, b] solucin de x = g(x) y la iteracin


de punto fijo (12.7) converge a x* para todo Xo E [a, b].

Teorema 12.3. Sea x* solucin de x = g(x), 9 continuamente diferen-


ciable en un intervalo abierto 1 tal que x* El, 19' (x*) 1< 1. Entonces
la iteracin de punto fijo (12.7) converge a x* para todo Xo suficiente-
mente cerca de x*.

El caso ideal (la convergencia es ms rpida) se tiene cuando g'(x*) ~ O.


En los dos ejemplos numricos anteriores, para resolver x 3 +x 2+6x+
5 = O, se tiene: x = g(x) = -(x 3 + x2 + 5)/6, g'( -0.8513) = -0.0786.
Si se considera x = g(x) - (x 3 +6x+5)/x, g'(-0.8513) = 8.6020. Estos
resultados numricos concuerdan con el ltimo teorema.

276
12.6. MTODO DE PUNTO FIJO

Dos de los ejemplos grficos anteriores muestran justamente que


cuando Ig'(x*)1 < 1 el mtodo converge.
Ejemplo 12.6. Resolver x2 = 3, o sea, calcular J3.
X2 3,
x2 +x2 x2 + 3,
x2 + 3
x - -,
2x
x+3/x
x
2

Xo 3
Xl 2
X2 1.75000000000000
X3 1.73214285714286
X4 = 1.73205081001473
Xs 1.73205080756888
X6 1. 73205080756888

Se observa que la convergencia es bastante rpida. Este mtodo es


muy utilizado para calcular races cuadradas en calculadoras de bolsillo
y computadores.
Aplicando el teorema 12.3 y teniendo en cuenta que g' (x*) = g' ( J3)
= 1/2 - 1.5/x*2 = O, se concluye rpidamente que si x O est suficiente-
mente cerca de J3, entonces el mtodo converge.
La aplicacin del teorema 12.2 no es tan inmediata, pero se obtiene
informacin ms detallada. La solucin est en el intervalo [2,3]; consi-
deremos un intervalo an ms grande: 1 = [1 + E, 4] con O < E < 1.
g(l) 2,
g(4) 2.375,
1 3
g'(x)
2" - 2x2 '
g'( V3) = O,
g'(l) -1,
13
g'(4)
32'
3
g"(x) x3 '

277
12. SOLUCIN DE ECUACIONES


Entonces g"(x) > para todo x positivo. Luego g'(x) es creciente para
x> O. Como g'(1) = -1, entonces -1 < g'(1+E). De nuevo por ser g'(x)
creciente, entonces -1 < g'(x) :s: 13/32 para todo x E l. En resumen,
19'(x)1 < 1 cuando x E l.
Entre 1 + E Y J3 el valor de g' (x) es negativo. Entre J3 y 4
el valor de g'(x) es positivo. Luego 9 decrece en [1 + E, J3] y crece en
[J3,4]. Entonces g([1 +E,J3]) = [g(1 +E),J3] ~ [2,J3] Y g([J3, 4]) =
[J3, 2.375]. En consecuencia g(l) = [J3, 2.375] ~ l. Entonces el mtodo
de punto fijo converge a x* = J3 para cualquier Xo E]1, 4]. Este resultado
se puede generalizar al intervalo [1 + E, b] con b > J3.
Si se empieza con Xo = 1/2, no se cumplen las condiciones del teore-
ma; sin embargo, el mtodo converge. <>

12.6.1 Mtodo de punto fijo y mtodo de Newton


Supongamos que c .. es una constante y que x* es solucin de la
ecuacin f(x) = O. sta se puede reescribir

cf(x),
x x + cf(x) = g(x). (12.8)

Si se desea resolver esta ecuacin por el mtodo de punto fijo, la conver-


gencia es ms rpida cuando g'(x*) = 0, o sea,

1+cJ'(x*) 0,
1
c
- f'(x*)'

Entonces al aplicar el mtodo de punto fijo a (12.8), se tiene la frmula

f(Xk)
Xk+1 = Xk - f'(x*)' (12.9)

Para aplicar esta frmula se necesitara conocer f'(x*) e implcitamente


el valor de x* , que es precisamente lo que se busca. La frmula del mtodo
de Newton, (12.1), puede ser vista simplemente como la utilizacin de
(12.9) reemplazando f'(x*) por la mejor aproximacin conocida en ese
momento: f'(Xk).

278
12.7. MTODO DE NEWTON EN IR N

12.7 Mtodo de N ewton en lR n


Consideremos ahora un sistema de n ecuaciones con n incgnitas;
por ejemplo,

xI + XIX2 + X3 - 3 o
2XI + 3X2X3 - 5 O (12.10)
(Xl + X2 + X3)2 - lOx3 +1 o.
Este sistema no se puede escribir en la forma matricial Ax = b; entonces
no se puede resolver por los mtodos usuales para sistemas de ecuaciones
lineales. Lo que se hace, como en el mtodo de Newton en ffi., es utili-
zar aproximaciones de primer orden (llamadas tambin aproximaciones
lineales). Esto es simplemente la generalizacin de la aproximacin por
una recta.

Un sistema de n ecuaciones con n incgnitas se puede escribir de la


forma

FI (Xl, X2, ... , Xn ) O


F 2(XI, X2, ... , Xn ) O

donde cada Fi es una funcin de n variables con valor real, o sea, Fi


--t ffi.. Denotemos X = (Xl, X2, ... , Xn ) y
ffi.n

FI(X)
F 2 (x)
1
F(x) =
[
Fn(x)
As F es una funcin de variable vectorial y valor vectorial, F : ffi.n --t

ffi.n, y el problema se escribe de manera muy compacta:

F(x) = O. (12.11)

Este libro est dirigido principalmente a estudiantes de segundo semes-


tre, quienes todava no conocen el clculo en varias variables, entonces
no habr una deduccin (ni formal ni intuitiva) del mtodo, simplemente
se ver como una generalizacin del mtodo en R

279
12. SOLUCIN DE ECUACIONES

12.7.1 Matriz jacobiana

La matriz jacobiana de la funcin F : ]Rn ----+ ]Rn, denotada por JF(x)


o por F'(x), es una matriz de tamao n x n, en la que en la i-sima fila
estn las n derivadas parciales de F i ,

oFI (x) oFI (x) oFI(x)


OXI OX2 oXn
oF2 (x) OF2 (x) oF2 (x)
JF(X) = F'(x) = I OXI OX2 oXn

oFn (x) oFn (x) oFn (x)


OXI OX2 oXn
Para las ecuaciones (12.10), escritas en la forma F(x) = O,

2XI + X2 Xl

F'(x) = 3X3 3X2 1


[
2(x +:, + X3) 2(XI
1
+ X2 + X3) 2(XI + X2 + X3) - 10

F'(2, -3,4) =
1
2
2
12
1
-9
1
[
6 6 -4

12.7.2 Frmula de Newton en ]R.n

La frmula del mtodo de Newton en ]R,

f(Xk)
Xk+l = Xk - f'(Xk) ,

se puede reescribir con superndices en lugar de subndices:


k
Xk+1 = x k _ f(x )
f'(xk) .

280
12.7. MTODO DE NEWTON EN IR N

De nuevo, es simplemente otra forma de escribir

Esta expresin s se puede generalizar

(12.12)

Su interpretacin, muy natural, aparece a continuacin. Sea x*, un vec-


tor de n componentes, solucin del sistema (12.11). Dependiendo de la
conveniencia se podr escribir

El mtodo empieza con un vector xO = (x~, xg, ... , x~), aproximaclOn


inicial de la solucin x*. Mediante (12.12) se construye una sucesin
de vectores {xk = (xt, x~, ... , x~)} con el deseo de que xk --t x*. En
palabras, el vector xk+ 1 es igual al vector xk menos el producto de la
inversa de la matriz jacobiana F'(xk) y el vector F(xk). Para evitar el
clculo de una inversa, la frmula se puede reescribir

dk _F'(xk)-l F(x k )
xk+l xk + dk .

Premultiplicando por F' (xk)

F'(x k ) dk -F'(xk)F' (xk)-l F(x k ),


F'(xk) dk -F(x k ).

En esta ltima expresin se conoce (o se puede calcular) la matriz F' (xk).


Tambin se conoce el vector F(xk). O sea, simplemente se tiene un
sistema de ecuaciones lineales. La solucin de este sistema es el vector
d k . Entonces las frmulas para el mtodo de Newton son:

resolver F'(xk) d k = -F(x k ), (12.13)


xk+1 xk + dk .

281
12. SOLUCIN DE ECUACIONES

Ejemplo 12.7. Resolver el sistema

xi + XIX2 + X3 - 3 O
+ 3X2X3 - 5
2XI O
(Xl + X2 + X3)2 - lOx3 + 1 O

a partir de xO = (2, -3,4).

F(xO) = [ -~~ ] , F'(xo) = [ ~ 122 1


-9 ]
-30 6 6 -4

2.5753]
resolver 21 122 -91] [d!i]
dg = - [- 1 ]
-37 , ~= 0.5890
[ 6 6 -4 dg -30 [ -2.7534

xl = -32] + [2.5753]
0.5890 =
[4.5753]
-2.4110
[
4 -2.7534 1.2466

8.1494] 6.7397 4.5753 1.0000 ]


F(x l ) = -4.8656 , F'(xl) = 2.0000 3.7397 -7.2329
[ [
0.1689 6.8219 6.8219 -3.1781

6.7397 4.5753 1.0000] [d~ ] [8.1494] [-4.4433]


2.0000 3.7397 -7.2329 d~ =- -4.8656 ,dI = 4.6537
[ 6.8219 6.8219 -3.1781 d~ 0.1689 0.5048

4.5753] [ -4.4433]
[ 0.1321 ]
x2 = -2.4110 + 4.6537
2.2428 =
[
1.2466 0.5048
1.7514
A continuacin se presentan los resultados de F(x k ), F'(x k ), dk , xk+l.
k=2

[ -0.9350] [2.5069 0.1321 1.0000 ] [ 0.6513] [ 07833]


7.0481 , 2.0000 5.2542 6.7283 , -0.8376 , 1.4052
0.5116 8.2524 8.2524 -1.7476 -0.5870 1.1644
k=3

[ -01213] [2.9718 0.7833 1.0000] [01824] [0.9658]


1.4751 , 2.0000 3.4931 4.2156 , -0.3454 , 1.0598
0.5981 6.7057 6.7057 -3.2943 -0.1502 1.0141

282
12.7. MTODO DE NEWTON EN IR N

k=4

[-~:~~~; 1, [~:~~~~ ~:~~~: !:~~~~ 1, [-~:~~~~ 1, [~:~~~~ 1


0.0981 6.0793 6.0793 -3.9207 -0.0139 1.0002

k=5

[-~:~~~~ 1, [~:~~~~ ~:~~~~ !:~~~~], [-~:~~~~ 1, [~:~~~~ 1


0.0015 6.0012 6.0012 -3.9988 -0.0002 1.0000

Ejercicios
Trate de resolver las ecuaciones propuestas, utilice mtodos diferen-
tes, compare sus ventajas y desventajas. Emplee varios puntos iniciales.
Busque, si es posible, otras races.

12.1 x 3 + 2x2 + 3x + 4 = O.

12.2 x 3 + 2x2 - 3x - 4 = O.

12.3 x 4 - 4x 3 + 6x2 - 4x + 1 = O.

12.4 x 4 - 4x 3 + 6x2 - 4x - 1 = O.
12.5 x 4 - 4x 3 + 6x2 - 4x +2 = O.

12.6
3x-6 x-2
---
cos(x) + 2 x2 + 1 + x3 _ 8 = O.
x2 +x + 10
eX +x2

12.7
. (1 + i)12
1000000 z ( ')12 1 = 945560.
1 +z -

283
12. SOLUCIN DE ECUACIONES

12.8 x~ - XX2 + 3x - 4X2 + 10 = O,


-2x~ + x~ + 3XX2 - 4x + 5X2 - 42 = O.

12.9 X + X2 + 2XX2 - 31 = O,
6x + 5X2 + 3XX2 - 74 = O.

284
13

Interpolacin y
. .,
aproXlmaclon

En muchas situaciones de la vida real se tiene una tabla de valores


correspondientes a dos magnitudes relacionadas; por ejemplo,

lAo I Poblacin I
1930 3425
1940 5243
1950 10538
1960 19123
1970 38765
1980 82468
1985 91963
1990 103646
1995 123425

De manera ms general, se tiene una tabla de valores

Xo f(xo)
Xl f(XI)
X2 f(X2)

Xn f(x n )

285
13. INTERPOLACIN Y APROXIMACIN

y se desea obtener una funcin , sencilla y fcil de calcular, aproxi-


macin de f, o en otros casos, dado un x, se desea obtener 1(x) valor
aproximado de f(x).
y


x
Figura 13.1

Los valores f(Xi) pueden corresponder a:

Datos o medidas obtenidos experimentalmente.


Valores de una funcin f que se conoce pero tiene una expresin
analtica muy complicada o de evaluacin difcil o lenta.
Una funcin de la que no se conoce una expresin analtica, pero se
puede conocer f(x) como solucin de una ecuacin funcional (por
ejemplo, una ecuacin diferencial) o como resultado de un proceso
numrico.

Cuando se desea que la funcin pase exactamente por los puntos


conocidos,
(Xi) = f(Xi) Vi,
se habla de interpolacin o de mtodos de colocacin.

Figura 13.2

286
13.1. INTERPOLACIN

En los dems casos se habla de aproximacin. En este captulo se


ver aproximacin por mnimos cuadrados.

Figura 13.3

13.1 Interpolacin
En el caso general de interpolacin se tiene un conjunto de n puntos
(Xl, Yl), (X2, Y2), ... , (x n , Yn) con la condicin de que los Xi son todos
diferentes. Este conjunto se llama el soporte. La funcin 1, que se desea
construir, debe ser combinacin lineal de n funciones llamadas funciones
de la base. Supongamos que estas funciones son !.pi, !.p2, ... , !.pn. Entonces,

Como las funciones de la base son conocidas, para conocer 1 basta co-
nocer los escalares al, a2, ... , an .
Las funciones de la base deben ser linealmente independien-
tes. Si n 2: 2, la independencia lineal significa que no es posible que una
de las funciones sea combinacin lineal de las otras. Por ejemplo, las
funciones !.pi (x) = 4, !.p2 (x) = 6x2 - 20 Y !.p3 (x) = 2x 2 no son linealmente
independientes.
Los escalares al, a2, ... , an se escogen de tal manera que 1(Xi) = Yi,
para i = 1,2, ... , n. Entonces

al !.pi (Xl) + a2!.p2(Xl) + ... + an!.pn(Xl) Yl


al !.pi (X2) + a2!.p2(X2) + ... + an!.pn(X2) Y2

287
13. INTERPOLACIN Y APROXIMACIN

Las m igualdades anteriores se pueden escribir matricialmente:

ipl(XI) ip2(XI)
ipl(X2) ip2(X2) ipn(X2)
ipn(XI) 1[ala2 1 [ Y2YI. 1
..
[
ipl(Xn ) ip2(X n ) ipn(X n ) an Yn
De manera compacta se tiene

<I>a = y. (13.1)

La matriz <I> es una matriz cuadrada n x n, a es un vector columna


n x 1, y es un vector columna n x 1. Son conocidos la matriz <I> y el
vector columna y. El vector columna a es el vector de incgnitas. Como
las funciones de la base son linealmente independientes, entonces las
columnas de <I> son linealmente independientes. En consecuencia, <I> es
invertible y (13.1) se puede resolver (numricamente).
Ejemplo 13.1. Dados los puntos (-1,1), (2, -2), (3,5) Y la base for-
mada por las funciones ipl (x) = 1, ip2 (x) = X, ip3 (x) = x 2, encontrar la
funcin de interpolacin.

Al plantear <I>a = y, se tiene

11 -12 41] [al


a2 ] = [ -21]
[ 1 3 9 a3 5

[=n '
Entonces
2
a= j(x)=-4-3x+2x ,

que efectivamente pasa por los puntos dados. <>


Ejemplo 13.2. Dados los puntos mismos (-1,1), (2, -2), (3,5) Y la
base formada por las funciones ipl (x) = 1, ip2 (x) = eX, ip3 (x) = e2x ,
encontrar la funcin de interpolacin.

Al plantear <I>a = y, se tiene

1 0.3679 0.1353] [al] [ 1]


1 7.3891 54.5982 a2 = -2
[ 1 20.0855 403.4288 a3 5

288
13.2. INTERPOLACIN DE LAGRANGE

Entonces

a=
-1.2921
-0.8123
1, j(x) = 1.2921 - 0.8123 + 0.0496e 2x ,
[ 0.0496

que efectivamente tambin pasa por los puntos dados. ()

13.2 Interpolacin de Lagrange


En la interpolacin de Lagrange la funcin j que pasa por los puntos
es un polinomio, pero el polinomio se calcula sin resolver explcitamente
un sistema de ecuaciones. Ms precisamente, dados n + 1 puntos

donde Yi = f (Xi) = fi, se desea encontrar un polinomio p E P n (el con-


junto 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)

Por ejemplo, se desea encontrar un polinomio de grado menor o igual a


2 que pase por los puntos

(-1,1), (2,-2), (3,5).

Los valores Xi deben ser todos diferentes entre s. Sin perder generalidad,
se puede suponer que Xo < Xl < X2 < ... < Xn .
El problema 13.2 se puede resolver planteando n + 1 ecuaciones con
n + 1 incgnitas (los coeficientes del polinomio). Este sistema lineal se
puede resolver y se tendra la solucin. Una manera ms adecuada de
encontrar p es por medio de los polinomios de Lagrange.

13.2.1 Algunos resultados previos

Teorema 13.1. Seap E P n . Si existenn+1 valores diferentes XO,XI,X2,


... , Xn tales que p(xd = O Vi, entonces p(x) = O Vx, es decir, p es el
polinomio nulo.

289
13. INTERPOLACIN Y APROXIMACIN

Teorema 13.2. Teorema del valor medio. Sea f derivable en el


intervalo [a, b], entonces existe e E [a, b] tal que

f(b) - f(a) = f'(c).

Corolario 13.1. Si f(a) = f(b) = O, entonces existe c E [a, b] tal que

f'(c) = o.

13.2.2 Polinomios de Lagrange

Dados n + 1 valores diferentes xo, Xl, X2, ... , Xn , se definen n + 1 po-


linomios de Lagrange Lo, L l , L 2, ... , Ln de la siguiente manera:

rrn
(x - Xi)
Lk(X) = _i---:=O;:;-,~'-=--=f_k_ __ (13.3)
rr
n

i=O,i=fk
(Xk - Xi)

La construccin de los polinomios de Lagrange, para los datos del ltimo


ejemplo Xo = -1, Xl = 2, X2 = 3, da:

(x - 2)(x - 3) x 2 - 5x + 6
Lo(x)
(-1-2)(-1-3) = 12
(x - -1)(x - 3) 2
x - 2x - 3
Ll(X)
(2 - -1)(2 - 3) = -3
(x - -1)(x - 2) x2 - x - 2
L 2(x)
(3 - -1)(3 - 2) = - - 4

Es claro que el numerador de (13.3) es el producto de n polinomios de


grado 1; entonces el numerador es un polinomio de grado, exactamente,
n. El denominador es el producto de n nmeros, ninguno de los cuales
es nulo, luego el denominador es un nmero no nulo. En resumen, Lk es
un polinomio de grado n.

Reemplazando se verifica que Lk se anula en todos los Xi, salvo en Xk,

Osi i =1= k,
Lk(Xi) = { 1 si i = k. (13.4)

290
13.2. INTERPOLACIN DE LAGRANGE

Con los polinomios de Lagrange se construye inmediatamente p,


n
p(x) = 2: YkLk(X). (13.5)
k=O
Por construccin p es un polinomio en P n . Reemplazando, fcilmente se
verifica 13.2.

Para el ejemplo,
p(x) = 1Lo(x) - 2Ll(X) + 5L 2(x) = 2x 2 - 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).

(x- l)(x - 2)(x - 3) x3 - 6x2 + llx - 6


Lo(x)
(-1-1)(-1- 2)(-1- 3) -24
x 3 - 4x 2 + x + 6
Ll(X)
4
x 3 - 3x 2 - x + 3
-3
x 3 - 2x2 - X + 2
L3(X)
8
p(x) 2x 2 - 3x - 4. <>

En la prctica se usa la interpolacin de Lagrange de grado 2 o 3,


mximo 4. Si hay muchos puntos, stos se utilizan por grupos de 3 o 4,
mximo 5 puntos.

13.2.3 Existencia, unicidad y error

El polinomio p E P n existe puesto que se puede construir. Sea q E P n


otro polinomio tal que
q(Xi)=Yi, i=0,1,2, ... ,n.
Sea r(x) = p(x) -q(x). Por construccin, r E P n , adems r(xi) = 0, i =
0,1,2, n, o sea, r se anula en n + 1 valores diferentes, luego r(x) = 0, de
donde q(x) = p(x).

291
13. INTERPOLACIN Y APROXIMACIN

Teorema 13.3. Sean Xo, X2, ... , Xn reales distintos; t un real; It


Xl,
el menor intervalo que contiene a Xo, Xl, X2, ... , Xn , t; E CR+1 (J
tiene derivadas continuas de orden O, 1, 2, ... , n + 1); Pn el polinomio
de grado menor o igual a n que pasa por los n + 1 puntos (xo, (xo) ),
(XI,J(XI)), ... , (xn,J(x n )). Entonces E(t), el error en t, est dado por:
E(t) = (t)-Pn(t) = (t-xO)(t-XI) (t-x n )f(n+1)(O/(n+1)! (13.6)
para algn ~ E It.

Demostracin. Si t = Xi para algn i, entonces se tiene trivialmente el


resultado. Supongamos ahora que t t/: {xo, Xl, X2, ... , Xn}. Sean
<I>(X) (X - XO)(X - Xl) ... (X - x n ),
<I>(x)
C(x) E(x) - <I>(t) E(t).

Entonces
C E C n +1
lt '
<I>(Xi)
C(Xi) E(Xi) - <I>(t) E(t) = O,

C(t) E(t) - :~!~ E(t) = O.

Como C tiene por lo menos n + 2 ceros en I t , aplicando el corolario del


teorema del valor medio, se deduce que C ' tiene por lo menos n + 2 - 1
ceros en It. As sucesivamente se concluye que c(n+l) tiene por lo menos
un cero en It. Sea ~ tal que
c(n+1) (~) = o.
De acuerdo con las definiciones
E(n+1) (x) (n+1)(X) _ p~n+1)(x) = (n+1) (x),
<I>(n+1) (x) (n + 1)!,
<I>(n+1) ( )
c(n+1) (x) E(n+1) (x) _ X E(t)
<I>(t) ,
c(n+1) (x) (n+1)(x) _ (n + 1)! E(t)
<I>(t) ,
c(n+l)(~) (n+1)(o - (nx-~-'~)! E(t) = o.

292
13. INTERPOLACIN Y APROXIMACIN

Teorema 13.3. Sean Xo, X2, ... , Xn reales distintos; t un real; It


Xl,
el menor intervalo que contiene a Xo, Xl, X2, ... , Xn , t; E CR+1 (f
tiene derivadas continuas de orden O, 1, 2, ... , n + 1); Pn el polinomio
de grado menor o igual a n que pasa por los n + 1 puntos (xo,f(xo)),
(Xl, (Xl)), ... , (x n , (x n )). Entonces E(t), el error en t, est dado por:
E(t) = (t)-Pn(t) = (t-XO)(t-XI)'" (t-xn)f(n+I)(~)/(n+1)! (13.6)
para algn ~ E It.

Demostracin. Si t = Xi para algn i, entonces se tiene trivialmente el


resultado. Supongamos ahora que t ti: {xo, Xl, X2, ... , Xn}. Sean
cI>(X) (X - xo)(x - Xl)' .. (X - x n ),
cI>(x)
C(x) E(x) - cI>(t) E(t).

Entonces
C E eItn +1 '
cI> (Xi)
C(Xi) E(Xi) - cI>(t) E(t) = O,
cI>(t)
C(t) E(t) - cI>(t) E(t) = O.

Como C tiene por lo menos n + 2 ceros en I t , aplicando el corolario del


teorema del valor medio, se deduce que C ' tiene por lo menos n + 2 - 1
ceros en It. As sucesivamente se concluye que c(n+1) tiene por lo menos
un cero en h Sea ~ tal que
c(n+1)(o = o.
De acuerdo con las definiciones
E(n+1) (x) (n+1)(X) _ p~n+1)(x) = (n+1) (x),
cI>(n+1) (x) (n + 1)!,
cI>(n+1) ( )
c(n+1) (x) E(n+1) (x) _ X E(t)
cI>(t) ,
c(n+1) (x) (n+l) (x) _ (n + 1)! E(t)
cI>(t) ,
c(n+1)(~) (n+1)(~) _ (nx-~-<~)! E(t) = o.

292
13.3. DIFERENCIAS DIVIDIDAS DE NEWTON

Entonces
E(t) = <I>(t) f{n+l)(().
(n + 1)!

13.3 Diferencias divididas de Newton


Esta es una manera diferente de hacer los clculos para la interpola-
cin polinmica. En la interpolacin de Lagrange se construye explcita-
mente p, es decir, se conocen sus coeficientes. Por medio de las diferencias
divididas no se tiene explcitamente el polinomio, pero se puede obtener
fcilmente el valor p(x) para cualquier x.

Supongamos de nuevo que tenemos los mismos n + 1 puntos,

Con ellos se obtiene Pn E Pn . Si se consideran nicamente los primeros


n puntos

(Xo, fo), (Xl, !I), (X2, 12), ... , (Xn-l, fn-l),


se puede construir Pn-l E P n-l. Sea c( X) la correccin que permite pasar
de Pn-l a Pn,
Pn(X) = Pn-I(X) + c(x), es decir, c(x) = Pn(x) - Pn--,-I(X).
Por construccin, e es un polinomio en P n . Adems,

La frmula anterior dice que e tiene n races diferentes xo, Xl, ... , Xn-l,
entonces

c(X) = an(x - xo)(x - XI)(X - X2) (X - Xn-l).

p(X n ) = Pn-I(X n ) + c(xn ),


Pn-I(X n ) + an(X n - XO)(X n - XI)(X n - X2) (X n - Xn-l).
De la ltima igualdad se puede despejar a n . Este valor se define como
la diferencia dividida de orden n de f en los puntos Xo, Xl, X2, ... , Xn .
Se denota

a n = J[xo, Xl, ... , xnl := ( )( f(xn~(- Pn-l (x n )( )


Xn - Xo Xn - Xl Xn - X2) Xn - Xn-l

293
13. INTERPOLACIN Y APROXIMACIN

El nombre diferencia dividida no tiene, por el momento, un significado


muy claro; ste se ver ms adelante. Una de las igualdades anteriores
se reescribe

Pn(X) = Pn-l (x) + f[xo, Xl, ... , Xn](X - XO)(X - Xt) ... (X - Xn-l). (13.7)
Esta frmula es la que se utiliza para calcular Pn(x), una vez que se sepa
calcular, de manera sencilla, f[xo, Xl, ... , Xn ].

Para calcular p(x), se empieza calculando po(x).

A partir depo(x), con el valor f[xo, Xl], se calculapl(X).

A partir depI(x), con el valor J[Xo, Xl, X2], se calculap2(x).

A partir de P2(X), con el valor J[XO,XI,X2,X3], se calcula P3(X).


A partir depn-l(x), con el valor J[XO,XI, ... ,Xn], se calculapn(x).

Obviamente
po(X) = f(xo). (13.8)
Por definicin, consistente con lo visto antes,

f[xo] := f(xo),
que se generaliza a
J[Xi] := f(Xi), Vi. (13.9)
Las dems diferencias divididas se deducen de (13.7),

PI(X) po(X) + f[xo, XI](X - xo),


PI(X) - Po(X)
f[xo, Xl]
X - Xo
Para X = Xl,

PI (Xl) - Po(XI)
f[xo, Xl]
XI- Xo
f(XI) - f(xo)
f[XO,XI]
Xl - Xo
J[XI] - f[xo]
f[xo, Xl]
Xl - Xo

294
13.3. DIFERENCIAS DIVIDIDAS DE NEWTON

La anterior igualdad se generaliza a

(13.10)

P2(X) Pl(X) + j[Xo, Xl, X2](X - XO)(X - Xl),


P2(X) - Pl(X)
f[xo, Xl, X2]
(X - XO)(X - Xt)'
X X2,
P2(X2) - Pl(X2)
(X2 - XO)(X2 - Xl)'

fO(X2 - Xl) - h(X2 - XO) + 12 (Xl - XO)


(X2 - Xl)(X2 - XO)(Xl - XO)
Por otro lado,

12 - h h - fa
j[Xl, X2] - f[xo, Xl]
X2 - Xo
j[Xl, X2] - f[xo, Xl] fO(X2 - Xl) - h(X2 - XO) + 12(xl - XO)
X2 - Xo (X2 - Xl)(X2 - XO)(Xl - XO)
Luego

Generalizando,

(13.11)

La generalizacin para diferencias divididas de orden j es:

(13.12)

Las frmulas anteriores dan sentido al nombre diferencias divididas.


Cuando no se preste a confusin, se puede utilizar la siguiente notacin:

(13.13)

295
13. INTERPOLACIN Y APROXIMACIN

Entonces

DOf[Xil - f(Xi), (13.14)


DO f[Xi+ll - DO f[Xil
Df[xil = Di f[Xil (13.15)
Xi+l - Xi
Di f[Xi+ll - Di j[xil
D 2f[Xil (13.16)
Xi+2 - Xi

Dj-l j[xi+ll - Dj-l j[xil


Dj f[Xil (13.17)
Xi+j - Xi

13.3.1 Tabla de diferencias divididas


Para ejemplos pequeos, hechos a mano, se acostumbra construir la
tabla de diferencias divididas, la cual tiene el siguiente aspecto:

Xi Ji f[Xi, Xi+ll j[Xi, Xi+l, xi+2l f[Xi, Xi+l, Xi+2, Xi+3l


Xo fo
f[XO,Xll
Xl h f[xo, Xl, X2l
j[Xl, x2l j[XO, Xl, X2, X3l
X2 12 f[Xl, X2, x3l
f[X2,X3l f[Xl, X2, X3, X4l
X3 13 f[X2, X3, X4l
f[X3, X4l
X4 f4

En la tabla anterior, dados 5 puntos, estn las diferencias divididas


hasta de orden 3. Claro est, se hubiera podido calcular tambin la
diferencia dividida de orden 4, que estara colocada en una columna
adicional a la derecha.
La elaboracin de la tabla es relativamente sencilla. Las dos prime-
ras columnas corresponden a los datos. La tercera columna, la de las
diferencias divididas de primer orden, f[Xi, Xi+l], se obtiene mediante la
resta de dos elementos consecutivos de la columna anterior dividida por
la resta de los dos elementos correspondientes de la primera columna.
Por ejemplo, f[X3, x4l = (f4 - 13)/(X4 - X3). Obsrvese que este valor se
coloca en medio de la fila de 13 y de la fila de f4.

296
13.3. DIFERENCIAS DIVIDIDAS DE NEWTON

Para el clculo de una diferencia dividida de segundo orden, cuar-


ta columna, se divide la resta de dos elementos consecutivos de la co-
lumna anterior por la resta de dos elementos de la primera columna,
pero dejando uno intercalado. Por ejemplo, J[XI, X2, X3] = (f[X2, X3] -
J[XI, X2])/(X3 - Xl)'
Para el clculo de una diferencia dividida de tercer orden, quinta
columna, se divide la resta de dos elementos consecutivos de la colum-
na anterior por la resta de dos elementos de la primera columna, pero
dejando dos intercalados. Por ejemplo, J[xQ, Xl, X2, X3] = (f[XI, X2, X3]-
J[XQ, Xl, X2])/(X3 - XQ).

Ejemplo 13.4. Construir la tabla de diferencias divididas, hasta el or-


den 3, a partir de los seis puntos siguientes:

(O, O), (0.5, 0.7071), (1, 1), (2, 1.4142), (3, 1.7321), (4, 2).

Xi Ji DJ[Xi] D2J[Xi] D 3J[Xi]


O 0.0000
1.4142
.5 0.7071 -0.8284
0.5858 0.3570
1 1.0000 -0.1144
0.4142 0.0265
2 1.4142 -0.0482
0.3179 0.0077
3 1.7321 -0.0250
0.2679
4 2.0000

El valor 1.4142 es simplemente (0.7071-0)/(0.5-0). El valor 0.2679


es simplemente (2 - 1.7321)/(4 - 3). El valor -0.1144 es simplemente
(0.4142 - .5858)/(2 - .5). El valor 0.0077 es simplemente (-0.0250 -
-0.0482)/(4 - 1). <)

El esquema algortmico para calcular la tabla de diferencias divididas


hasta el orden m es el siguiente:

297
13. INTERPOLACIN Y APROXIMACIN

para i = 0,000, n
DO j[Xi] = f(Xi)
fin-para i
para j = 1, ooo,m
para i = 0,000, n - j
calcular Dj f[Xi] segn (13017)
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 algn m todos los valores f[Xk, xk+l, 000' Xk+m] son iguales
(o aproximadamente iguales), entonces f es (aproximadamente)
un polinomio de grado mo

Si para algn r todos los valores f[Xk,Xk+l,ooo,Xk+r] son nulos


(o aproximadamente nulos), entonces f es (aproximadamente) un
polinomio de grado r - lo

13.3.2 Clculo del valor interpolado


La frmula (1307) se puede reescribir a partir de un punto Xk, pues
no siempre se debe tomar como valor de referencia Xo,

Pm(X) = Pm_l(x)+D m j[Xk](X-Xk)(X-Xk+l) o o o (X-Xk+m-I)o (13018)


Si se calcula Pm-I(X) de manera anloga, queda en funcin de Pm-2(X)
y as sucesivamente se obtiene:

Pm(X) = t, [n;f[Xkl TI (x - Xk+i)] . (13019)

El proceso para el clculo es el siguiente:

Po(X) = fk
PI(X) = Po(x) + DI f[Xk](x - Xk)
P2(X) = PI(X) + D 2f[Xk](x - Xk)(X - Xk+l)
P3(X) = P2(X) + D3 f[Xk](X - Xk)(X - Xk+1)(X - Xk+2)
P4(X) = P3(X) + D4j[Xk](X - Xk)(X - Xk+1) (x - Xk+2)(X - Xk+3)

298
13.3. DIFERENCIAS DIVIDIDAS DE NEWTON

Se observa que para calcular Pj (x) hay multiplicaciones que ya se hicieron


para obtener Pj-1(X); entonces, no es necesario repetirlas sino organizar
el proceso de manera ms eficiente.
1'0 = 1, po(X) = !k
1'1 = I'o(x - Xk), P1(X) = po(x) + DI f[XkJ 1'1
1'2 = 1'1 (X - Xk+1), P2(X) = P1(X) + D 2f[Xkl'Y2
1'3 = 1'2 (X - Xk+2), P3(X) = P2(X) + D 3f[XkJ 1'3
1'4 = 1'3 (X - Xk+3), P4(X) = P3(X) + D4f[Xkl'Y4

nicamente queda por precisar la escogencia del punto inicial o de re-


ferencia Xk. Si se desea evaluar Pm(x), cul debe ser Xk? Recordemos
que se supone que los puntos xo, Xl, X2, ... , Xn estn ordenados y que
m, orden del polinomio de interpolacin, es menor o igual que n. Obvia-
mente, aunque no es absolutamente indispensable, tambin se supone
que x ~ {XO,X1, ... ,xn }.
Naturalmente se desea que x E [Xk, Xk+mJ. Pero no siempre se cum-
ple; esto sucede cuando x ~ [xo, xnJ. En estos casos se habla de extra-
polacin y se debe escoger Xk = Xo si x < Xo. En el caso opuesto se
toma Xk = Xn- m .
En los dems casos, se desea que x est lo "ms cerca" posible del
intervalo [Xk, Xk+mJ o del conjunto de puntos Xk, Xk+1, Xk+2, ... , Xk+m'
Ejemplo 13.5. Considere los datos del ejemplo anterior para calcular
por interpolacin cuadrtica y por interpolacin cbica una aproxima-
cin de f(1.69).

El primer paso consiste en determinar el Xk. Para ello nicamente se


tienen en cuenta los valores Xi.

Xi
O
.5
1
2
3
4
Para el caso de la interpolacin cuadrtica, una simple inspeccin
visual determina que hay dos posibilidades para Xk. La primera es Xk =

299
13. INTERPOLACIN Y APROXIMACIN

0.5, intervalo [0.5,2]. La segunda es Xk = 1, intervalo [1,3]. Cul es


mejor?
Para medir la cercana se puede usar la distancia de x al promedio
de los extremos del intervalo (Xi + Xi+2)/2 (el centro del intervalo) o la
distancia de x al promedio de todos los puntos (Xi + Xi+! + xi+2)/3. En
general

Ui
Xi + Xi+m (13.20)
2
Vi
Xi + Xi+! + Xi+2 + ... + Xi+m (13.21)
m+1
Ix -ukl min{lx -
t
uil :x E [Xi, Xi+m]} , (13.22)
Ix - vkl m.in{lx - vil: x E [Xi, Xi+m]}. (13.23)
t

Los valores Ui Y Vi son, de alguna forma, indicadores del centro de ma-


sa del intervalo [Xi, Xi+m]. Con frecuencia, los dos criterios, (13.22) y
(13.23), definen el mismo Xk, pero en algunos casos no es as. De todas
formas son criterios razonables y para trabajar se escoge un solo cri-
terio, lo cual da buenos resultados. Se puede preferir la utilizacin de
Vi que, aunque requiere ms operaciones, tiene en cuenta todos los Xj
pertenecientes a [Xi, Xi+m].
Los resultados numricos para la interpolacin cuadrtica dan:

Xi Ui Ix - uil . Vi Ix - vil

O
.5 1.25 0.44 1.1667 0.5233
1 2.00 0.31y' 2.0000 0.3100y'
2
3
4

Para la interpolacin cbica hay tres posibilidades para Xk: O, 0.5 y


1.

300
13.3. DIFERENCIAS DIVIDIDAS DE NEWTON

Xi Ui IX - Uil Vi IX - Vil

O 1.00 0.69 0.875 0.815


.5 1.75 0.06J 1.625 0.065J
1 2.50 0.81 2.500 0.810
2
3
4

Una vez escogido Xk = 1 para obtener la aproximacin cuadrtica de


f(1.69), los clculos dan:

'/'0 = 1, po(X) = 1,
'/'1 = 1(1.69 - 1) = 0.69, Pl(X) = 1 + 0.4142(0.69) = 1.285798
'/'2 = 0.69(1.69 - 2) = -0.2139, P2(X) = 1.285798 - 0.0482( -0.2139)
P2(X) = 1.296097

Para la interpolacin cbica, Xk = 0.5:

'/'0=1, po(X) =0.7071,


'/'1 = 1(1.69-0.5) = 1.19, PI (x) = 0.7071 +0.5858(1.19)
PI (x) = 1.404202
'/'2 = 1.19(1.69-1) =0.8211, P2(X) = 1.404202-0.1144(0.8211)
P2 (x) = 1. 310268
'/'3 =0.8211(1.69-2) =-D.254541, P3(X) = 1.310268+0.0265(-D.254541)
P3(x)=1.303523. <>

El esquema del algoritmo para calcular Pm(x), a partir de la tabla


de diferencia divididas, es el siguiente:

determinar Xk
px = f(Xk)
gi = 1.0
para j = 1, ... ,m
gi = gi * (x - Xk+j-l)
px = px + gi * Dj f[Xkl
fin-para j

301
13. INTERPOLACIN Y APROXIMACIN

13.4 Diferencias finitas


Cuando los puntos (xo, f(xo)), (Xl, f(XI)), (X2, f(X2)), ... , (x n , f(x n )),
estn igualmente espaciados en x, es decir, existe un h > O tal que
Xi = Xo + ih, i = 1, ... , n
entonces se pueden utilizar las diferencias finitas, definidas por
~Ofi fi (13.24)
~fi fi+l - Ji (13.25)
~k+1 fi ~k(~fi) = ~k fi+l - ~k fi (13.26)
Algunas de las propiedades interesantes de las diferencias finitas son:

~kfi t( j=O
-1)j (~) fi+k-j ,
J
(13.27)

k
fi+k L (~)~j Ji. (13.28)
j=o J
Las demostraciones se pueden hacer por induccin. La primera igualdad
permite calcular ~k fi sin tener explcitamente los valores ~k-Ifj. La
segunda igualdad permite el proceso inverso al clculo de las diferencias
finitas (se obtienen a partir de los valores iniciales f p ), es decir, obtener
un valor fm a partir de las diferencias finitas.
Para valores igualmente espaciados, las diferencias finitas y las divi-
didas estn estrechamente relacionadas.
DO f[Xi] = f[Xi] fi = ~Ofi
fi+l - fi ~l Ji
DI f[Xi] = f[Xi, Xi+1]
Xi+1 - Xi h
j[Xi+I, Xi+2] - f[Xi, Xi+l] ~2Ji
D 2f[Xi] = j[Xi, Xi+1, Xi+2]
Xi+2 - Xi 2h 2
~mfi
D m f[Xi] = j[Xi, ... , Xi+m] (13.29)
m!hm

13.4.1 Tabla de diferencias finitas


La tabla de diferencias finitas tiene una estructura anloga a la tabla
de diferencias divididas. Se usa para ejemplos pequeos hechos a mano.

302
13.4. DIFERENCIAS FINITAS

Xi Ji t::.h t::. 2 Ji t::. 3 Ji


Xo Jo
t::.Jo
Xl h t::. 2 Jo
t::.h t::. 3 Jo
X2 12 t::. 2h
t::.12 t::. 3h
X3 h t::. 212
t::.h
X4 J4
La elaboracin de la tabla es muy sencilla. Las dos primeras co-
lumnas 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, t::.h = J4 - h. Obsrvese que este
valor se coloca en medio de la fila de h y de la fila de J4. Por ejemplo,
t::. 2 h = t::.12 - t::.h De manera semejante, t::. 3 Jo = t::. 2 h - t::. 2 Jo.
Ejemplo 13.6. Construir la tabla de diferencias finitas, hasta el orden
3, a partir de los seis puntos siguientes: (O, O), (0.5, 0.7071), (1, 1),
(1.5, 1.2247), (2, 1.4142), (2.5, 1.5811).

Xi h t::.Ji t::. 2h t::. 3h


O 0.0000
0.7071
.5 0.7071 -0.4142
0.2929 0.3460
1 1.0000 -0.0682
0.2247 0.0330
1.5 1.2247 -0.0352
0.1895 0.0126
2 1.4142 -0.0226
0.1669
2.5 1.5811

El valor 0.1895 es simplemente 1.4142 - 1.2247. El valor 0.0330 es


simplemente -0.0352 - -0.0682. O

El esquema algortmico para calcular la tabla de diferencias finitas


hasta el orden m es el siguiente:

303
13. INTERPOLACIN Y APROXIMACIN

para i = 0, ... , n
b..0Ji = f(Xi)
fin-para i
para j = 1, ... ,m
para i = 0, ... , n - j
. . 1 . 1
b..J fi = b..J - fi+l - b..J - Ji
fin-para i
fin-para j

13.4.2 Clculo del valor interpolado

Teniendo en cuenta la relacin entre diferencias divididas y finitas


(13.29), la igualdad (13.19) se puede escribir

Pm(X) = m [b..ifk
i! h i II (x -
i-l
Xk+j)
1
t=O J=O

El valor i! se puede escribir n~:,1(j + 1). Adems, sea 8 = (x - xk)/h, es


decir, x = Xk + 8h. Entonces, x - Xk+j = Xk + 8h - Xk - jh = (8 - j)h.

Pm(X) t, [~i{: II (8 - j)h 1


t, [ ;(k II(
Ll 8 - 1
j)

m i-l 8 _ j
b..
.
t=
iA P
J=O
j +1

Si a y b son enteros no negativos, a 2 b, el coeficiente binomial est de-


finido por

(~)=~ .. _
..
Desarrollando los factoriales y simplificando se tiene

a) = a(a - l)(a - 2) .. (a - b + 1) = a(a - l)(a - 2) .. (a - b + 1)


(b 1 x 2 x 3 x ... x b b!

304
13.4. DIFERENCIAS FINITAS

Esta ltima expresin sirve para cualquier valor real a y cualquier entero
no negativo b, con la convencin de que (~) = 1. Entonces,

i-l .
s -J
II
j=oJ
.+ 1

se puede denotar simplemente por (:) y as

(13.30)

Este coeficiente (:) guarda propiedades semejantes a las del coeficiente


binomial, en particular

( ~)
'/,
(. s ) s -
'/, -1
~+1
'/,
Esto permite su clculo de manera recurrente

Escoger el Xk para interpolar por un polinomio de grado m, se hace


como en las diferencias divididas. Como los valores Xi estn igualmente
espaciados los valores, Ui Y Vi coinciden.
Xi + 2Xi+m ,'/,. = O, ... , n-m,
min{lx - uil : i = O, ... ,n - m}.

305
13. INTERPOLACIN Y APROXIMACIN

Definido el Xk, es necesario calcular s:


X-Xk
s= h

El esquema de los clculos es:

1'0 = 1, po(X) = fk
1'1 = 1'0 s, PI (X) = Po (X)+ ,6,1 ik 1'1
1'2 = 1'1 (s - 1)/2, P2 (X) = PI (X)+ fl 2ik 1'2
1'3 = 1'2(S - 2)/3, P3(X) = P2(X) + fl3 fk 1'3
1'4 = 1'3(S - 3)/4, P4(X) 4
= P3(X) + fl ik1'4

Ejemplo 13.7. Calcular P3(1.96) y P2(1.96) a partir de los puntos


(O, O), (0.5, 0.7071), (1, 1), (1.5, 1.2247), (2, 1.4142), (2.5, 1.5811).
La tabla de diferencias finitas es la misma del ejemplo anterior. Para
calcular P3(1.96) se tiene Xk = X2 = 1. Entonces s = (1.96 - 1)/0.5 =
1.92.
1'0 = 1, Po(X) = 12 = 1
1'1 = 1(1.92) = 1.92, Pl(X) = 1 + .2247(1.92)= 1.431424
1'2 = 1.92(1.92 - 1)/2 = .8832, P2(X) = 1.431424 - .0352(.8832)
P2(X) = 1.400335
1'3 = 1'2(1.92 - 2)/3 = -.023552, P3(X) = 1.400335 + .0126(-.023552)
P3(X) = 1.400039

Para calcular P2(1.96) se tiene Xk = X3 = 1.5. Entonces s = (1.96 -


1.5) /0.5 = 0.92.

1'0=1, po(x)=h=1.2247
1'1 = 1(0.92) =0.92, PI (x) = 1.2247 + .1895(.92) = 1.39904
1'2=0.92(0.92 -1)/2=-.0368, P2(X) = 1.39904 - .0226(-0.0368)
P2(X) = 1.399872

13.5 Aproximacin por mnimos cuadrados


Cuando hay muchos puntos no es conveniente buscar un nico polino-
mio o una funcin que pase exactamente por todos los puntos. Entonces
hay dos soluciones: la primera, vista anteriormente, es hacer interpola-
cin por grupos pequeos de puntos. Para muchos casos es una solucin

306
13.5. APROXIMACIN POR MNIMOS CUADRADOS

muy buena. Sin embargo, en algunas ocasiones se desea una funcin que
sirva para todos los puntos. La segunda solucin consiste en obtener una
sola funcin j que, aunque no pase por todos los puntos, pase relativa-
mente cerca de todos. Este es el enfoque de la aproximacin por mnimos
cuadrados.
Se supone que hay m puntos (Xl, YI), (X2, Y2), ... , (x m , Ym) y que
los Xi son todos diferentes. La funcin j, que se desea construir, debe
ser combinacin lineal de n funciones llamadas funciones de la base.
Supongamos que estas funciones son 'PI, 'P2, ... , 'Pn' Entonces,
}(x) = al'PI(x) + a2'P2(x) + ... + an'Pn(x).
Como las funciones de la base son conocidas, para conocer j basta co-
nocer los escalares al, a2, ... , ano
Como se supone que hay muchos puntos (m grande) y como se desea
que j sea sencilla, es decir, n es relativamente pequeo, entonces se debe
tener que m ~ n.
Las funciones de la base deben ser linealmente independien-
tes. Los escalares al, a2, ... , a n se escogen de tal manera que }(Xi) ~ Yi,
para i = 1,2, ... , m. Entonces,

al'PI(XI) + a2'P2(xI) + ... + an'Pn(XI) ~


YI
al'PI(x2) + a2'P2(x2) + ... + an'Pn(X2) ~
Y2
al'PI(x3) + a2'P2(x3) + ... + a n'Pn(X3) ~
Y3

al'PI(x m ) + a2'P2(x m ) + ... + an'Pn(xm ) ~


Ym'
Las m igualdades (aproximadas) anteriores se pueden escribir de manera
matricial:
'PI (xI) 'P2(XI) 'Pn(XI) YI
'PI (X2) 'P2(X2) 'Pn(X2) Y2
'PI (X3) 'P2(X3) 'Pn(X3) Y3

[f 1 ~

Ym
De manera compacta se tiene
cI>a ~ y. (13.31)

307
13. INTERPOLACIN Y APROXIMACIN

La matriz cp es una matriz m x n rectangular alta (m 2: n), a es un vector


columna n x 1, y es un vector columna m x 1. Son conocidos la matriz
cp y el vector columna y. El vector columna a es el vector de incgnitas.
Como las funciones de la base son linealmente independientes, entonces
las columnas de cp son linealmente independientes. En consecuencia,
(13.31) se puede resolver por mnimos cuadrados:
(cpTcp) a = cpT y . (13.32)

Recordemos del captulo 11 que para resolver por mnimos cuadrados el


sistema Ax = b, se minimiza IIAx - bll~. Traduciendo esto al problema
de aproximacin por mnimos cuadrados, se tiene

min t, (t,aj~j(Xi) _Y') 2

es decir,
m _ 2
min L ((Xi) - Yi) .
i=l

Esto significa que se est buscando una funcin ,


combinacin lineal de
las funciones de la base, tal que minimiza la suma de los cuadrados de
las distancias entre los puntos (Xi, (Xi)) y (Xi, Yi).
Ejemplo 13.8. Dadas las funciones <Pl(X) = 1, <P2(X) = X, <P3(X) = x 2,
encontrar la funcin que aproxima por mnimos cuadrados la funcin
dada por los puntos (0,0.55), (1,0.65), (1.5,0.725), (2,0.85), (3,1.35).
Como las funciones de la base son 1, X, x 2 , en realidad se est bus-
cando aproximar por mnimos cuadrados por medio de un parbola. El
sistema inicial es
1 O O 0.55
1
1
1
1
1

2
3
1
1.5 2.25
4
9
[;:l ~ 0.65
0.725
0.85
1.35
Las ecuaciones normales dan:
7.5
1625 ][ a) ] [ 4.1250]
[ 5
7.5 16.25 39.375 a2 7.4875
16.25 39.375 103.0625 a3 17.8313

308
13.5. APROXIMACIN POR MNIMOS CUADRADOS

La solucin es:

0.56] -
a= -0.04 , f(x) = 0.56 - 0.04x + O.lx 2 .
[ 0.10

j(Xl) 0.56 0.55


j(X2) 0.62 0.65
j( X3) = <Pa = 0.725 y= 0.725 <>
j( X4) 0.88 0.85
j( X5) 1.34 1.35

Ejercicios

13.1 Halle, resolviendo el sistema de ecuaciones, el polinomio de inter-


polacin que pasa por los puntos

(1, -5),
(2, -4),
(4, 4).

13.2 Halle, por medio de los polinomios de Lagrange, el polinomio de


interpolacin que pasa por los puntos del ejercicio anterior.

13.3 Halle el polinomio de interpolacin que pasa por los puntos

(-1,-5),
(1, -5),
(2, -2),
(4, 40).

13.4 Halle el polinomio de interpolacin que pasa por los puntos

(-1, 10),
(1, 8),
(2, 4),
(4, -10).

309
13. INTERPOLACIN Y APROXIMACIN

13.5 Considere los puntos

(0.10, 11.0000),
(0.13, 8.6923),
(0.16, 7.2500),
(0.20, 6.0000),
(0.26, 4.8462),
(0.40, 3.5000),
(0.32, 4.1250),
(0.50, 3.0000).

Construya la tabla de diferencias dividas hasta el orden 3. Ob-


tenga P2(0.11), P2(0.08), P2(0.25), P2(0.12), P2(0.33), P2(0.6),
P3(0.25), P3(0.33), P3(0.6).

13.6 Considere los puntos

(0.05,21.0000),
(0.10, 11.0000),
(0.15, 7.6667),
(0.20, 6.0000),
(0.25, 5.0000),
(0.30, 4.3333),
(0.35, 3.8571),
(0.40, 3.5000).

Construya la tabla de diferencias divididas hasta el orden 3. Calcu-


le P2(0.11), P2(0.08), P2(0.25), P2(0.12), P2(0.33), P2(0.6), P3(0.25),
P3(0.33), P3(0.6).

13.1 Considere los mismos puntos del ejercicio anterior. Construya la ta-
bla de diferencias finitas hasta el orden 3. Halle P2(0.11), P2(0.08),
P2(0.25), P2(0.12), P2(0.33), P2(0.6), P3(0.25), P3(0.33),
P3(0.6).

310
13.5. APROXIMACIN POR MNIMOS CUADRADOS

13.8 Considere los puntos


(0.05,2.0513),
(0.10, 2.1052),
(0.15, 2.1618),
(0.20,2.2214),
(0.25, 2.2840),
(0.30, 2.3499),
(0.35,2.4191),
(0.40, 2.4918).
Obtenga la recta de aproximacin por mnimos cuadrados.

13.9 Considere los mismos puntos del ejercicio anterior. Obtenga la


parbola de aproximacin por mnimos cuadrados.

13.10 Considere los mismos puntos de los dos ejercicios anteriores. Use
otra base y obtenga la correspondiente funcin de aproximacin
por mnimos cuadrados.

311
14

Integracin y diferenciacin

14.1 Integracin numrica


Esta tcnica sirve para calcular el valor numrico de una integral
definida, es decir, parar obtener el valor

1= lb f(x)dx.

y = f(x)

a
Figura 14.1

En la mayora de los casos no se puede calcular el valor exacto 1;


simplemente se calcula i aproximacin de l.
De todas maneras primero se debe tratar de hallar la antideriva-
da. Cuando esto sea imposible o muy difcil, entonces se recurre a la

313
14. INTEGRACIN Y DIFERENCIACIN

integracin numrica. Por ejemplo, calcular una aproximacin de

0.5

0.1
X2
e dx.

En este captulo hay ejemplos de integracin numenca con funciones


cuya antiderivada es muy fcil de obtener y para los que no se debe
utilizar la integracin numrica; se usan solamente para comparar el
resultado aproximado con el valor exacto.

14.2 Frmula del trapecio


La frmula del trapecio, como tambin la frmula de Simpson, hace
parte de las frmulas de Newton-Cotes. Sean n + 1 valores igualmente
espaciados a = xo, Xl, x2, ... , Xn = b, donde

Xi = a + ih, i = 0,1,2, ... , n, h = b - a ,


n

y supongamos conocidos Yi = f(Xi)' Supongamos adems que n es un


mltiplo de m, n = km. La integral J:on f(x)dx se puede separar en
intervalos ms pequeos:

r
Jxo
n
f(x)dx = r
Jxo
m
f(x)dx + {X2m
JXm
f(x)dx + ... + r n

}X -
f(x)dx.
nm

Xo Xl x2 xm X2m xn - m xn
a b
Figura 14.2

314
14.2. FRMULA DEL TRAPECIO

En el intervalo [xo, xml se conocen los puntos (xo, Yo), (Xl, YI), ... ,
(x m , Ym) y se puede construir el polinomio de interpolacin de Lagrange
Pm(x). Entonces la integral J:om f(x)dx se aproxima por la integral de
Pm,

xm f(x)dx xm Pm(x)dx.
Xo
~
xo

Para m = 1 se tiene la frmula del trapecio. Su deduccin es mucho


ms sencilla si se supone que Xo = o. Esto equivale a hacer el cambio de
variable x' = X - Xo.

X- Xl X - Xo
PI (x) = Yo Xo - Xl
+ Yl
Xl -Xo
,

x-h X
PI(X) = Yo-=-;: + YI h'
YI - Yo
PI (X ) = Yo +X h .

Entonces

Xo
Xl
PI(x)dx =
lho
(Yo + X
YI - Yo
h )dx

_ h + h 2 YI - Yo
- Yo 2 h '
= h( Yo + J!..!..-)
2 2'

Xo
Xl f(x)dx ~ h Yo + YI.
2
(14.1)

De la frmula (14.1) o de la grfica se deduce naturalmente el nombre


de frmula del trapecio.

315
14. INTEGRACIN Y DIFERENCIACIN

Yo YI

Xo h Xl

Figura 14.3
Ejemplo 14.1.
0.2 1 1
10
eXdx ~ 0.2( _ea + _eO. 2) = 0.22214028. <>
22
Aplicando la frmula del trapecio a cada uno de los intervalos [Xi-l, Xi]
se tiene:
Xl f(x)dx ~ h( Yo + n),
Jxo 2 2

X2

Xl
f(x)dx ~ h(n + ~),
2 2
~

Xnf(x)dx ~ h(Yn-1 + Yn).


JXn-l 2 2

Xn f(x)dx ~ h( Yo + n + n + Y2 + ... Yn-l + Yn),


Jxo 2 2 2 2 2 2

Xo
xn
f(x)dx ~ h( ;
y
+ YI + Y2 + ... + Yn-2 + Yn-l +
yn
2 ), (14.2)
n-l
(X n y y
Jx f(x)dx~h(-f+LYi+ ;).
xo i=l

Ejemplo 14.2.
0.8 1 1
1 eXdx ~ 0.2( _ea
2
+ eO. 2 + e.4 + eO. 6 + _eO. 8 ) = 1.22962334. <>
2

316
14.2. FRMULA DEL TRAPECIO

14.2.1 Errores local y global

El error local de la frmula del trapecio es el error proveniente de la


frmula (14.1).

eloe = Iloe - loe,

eloe = Xl
xo
Yo
f(x)dx - h(2 +
YI
2)
= {Xl f(x)dx _ (Xl PI(x)dx
Jxo Jxo
= Xl (j(X) - PI(x))dx.
Jxo
Utilizando la frmula del error para la interpolacin polinmica 13.6,

El teorema del valor medio para integrales dice: Sean f continua en


[a, b], g integrable en [a, b], g no cambia de signo en [a, b], entonces

b f(x)g(x)dx = f(c) b g(x)dx

para algn e en [a, b].


Teniendo en cuenta que (x - xo)(x - Xl) :::; O en el intervalo [xo, Xl] y
aplicando el teorema del valor medio para integrales, existe z E [xo, Xl]
tal que

f"(z) Xl
eloe = - - (X - XO)(x - xI)dx, z E [XO, Xl].
2 Xo

Mediante el cambio de variable t = X - xo, dt = dx,

eloe =
f"(z) r
-2- Jo t(t - h)dt, z E [xo, Xl],
f"(z) h 3
= -2-(-6), z E [xo, Xl],
3 f"(z)
eloe = -h ~' z E [xo, Xl]. (14.3)

317
14. INTEGRACIN Y DIFERENCIACIN

La frmula anterior, como muchas de las frmulas de error, sirve princi-


palmente para obtener cotas del error cometido.

lelocl ~ ~;M , M = max{IJ"(z)1 : z E [XQ, Xl]}. (14.4)

En el ejemplo 14.1, f"(x) = eX, max{If"(z)1 : z E [O, 0.2]} = 1.22140276,


luego el mximo error que se puede cometer, en valor absoluto, es (0.2)3 x
1.22140276/12 = 8.1427.10- 4 . En este ejemplo, se conoce el valor exacto
1 = eQ 2 - 1 = 0.22140276, luego lel = 7.3752 . 10-4 .
En algunos casos, la frmula del error permite afinar un poco ms.
Si f"(x) > O (f estrictamente convexa) en [XQ,XI] Y como 1 = + eloc ,
entonces la frmula del trapecio da un valor aproximado pero superior
al exacto.
En el mismo ejemplo, f" (x) vara en el intervalo [1, 1.22140276] cuan-
do X E [O, 0.2]. Luego

eloc E [-0.00081427, -0.00066667],

entonces
1 E [0.22132601,0.22147361].

El error global es el error correspondiente al hacer la aproximacin de


la integral sobre todo el intervalo [xQ, X n ], o sea, el error en la frmula
14.2,

.
eglob = Xo
xn
f(x)dx - h( -fy + YI + Y2 + ... + Yn-2 + Yn-l +
yn
2 )

. n f"(Zi) h 3
=2:) , n ) ' ZiE[Xi-I,Xi]
i=l
h3 n
= - 12 I:.. J" (Zi) , Zi E [Xi-l, Xi]
i=l

Sean

MI = min{J"(x) : X E [a, b]}, M 2 = max{f"(x) : X E [a, b]}.

318
14.3. FRMULA DE SIMPSON

Entonces
MI :::; f"(Zi) :::; M2, Vi
n
nMl :::; L f"(Zi) :::; nM2,
i=l
n
MI :::; -1 ~
~ f "( Zi):::; M 2
n i=l
Si f E C~,bl' entonces, aplicando el teorema del valor intermedio a f",
existe ~ E [a, b] tal que

f"(~) = ~
n
t
i=l
f"(zd

Entonces

~ E [a,b].

Como h = (b - a)/n, entonces n = (b - a)/h.

(b - a)f"(~)
eglob = - h2 12 ,~E [a,b]. (14.5)

14.3 Frmula de Simpson


Es la frmula de Newton-Cotes para m = 2,
X2 f(x)dx lx2 P2(x)dx.
~
lXo Xo

El polinomio de interpolacin P2 (x) se construye a partir de los pun-


tos (xo, Yo), (Xl, Yd, (X2, Y2). Para facilitar la deduccin de la frmula,
supongamos que P2 es el polinomio de interpolacin que pasa por los
puntos (O, Yo), (h, Yl), (2h, Y2). Entonces
(X - h)(x - 2h) (x - O)(x - 2h) (x - O)(x - h)
P2(X) = Yo (O _ h)(O _ 2h) + Yl (h - O)(h - 2h) + Y2 (2h - 0)(2h - h)'
1
= 2h 2 (Yo(x - h)(x - 2h) - 2Yl x(x - 2h) + Y2 x(x - h)),

= 2h12 ( X2 (Yo - 2Yl + Y2) + hx( -3yo + 4Yl - Y2) + 2h 2Yo ) ,

319
14. INTEGRACIN Y DIFERENCIACIN

{2h 1 8h 3 4h 2
Jo P2(x)dx = 2h2 (3(YO - 2Yl + Y2) + h T (-3yO + 4YI - Y2)

+ 2h 2(2h)yO) ,
(2h 1 4 1
Jo P2(x)dx = h(3 YO + 3Y1 + 3 Y2 ).

Entonces

X2

Xo
h
f(x)dx ~ 3(YO + 4Yl + Y2) (14.6)

Suponiendo que n es par, al aplicar la frmula anterior a cada uno de los


intervalos [xo, X2], [X2, X4], [X4, X6], ... , [X n-4,;:l::n- 2], [X n-2, x n], se tiene:

Xo
xn h
f(x)dx ~ 3(YO + 4Yl + 2Y2 + 4Y3 + ... + 4Yn-l + Yn) (14.7)

{X n h k k-l
Jx f (X )dx ~ 3 ( Yo + 4 L Y2j-l + 2 L Y2j + Yn)
Xo j=l j=l

Ejemplo 14.3.

o.S 02
l eX dx ~ -'-(eo + 4(eO. 2 + eO. 6) + 2 e.4
3
+ eO. s) = 1.22555177.

El valor exacto, con 8 cifras decimales, es 1.22554093, entonces el error


es -0.00001084. <>

14.3.1 Errores local y global

Para facilitar la deduccin del error local, consideremos la integral


entre -h y h. Sea f E C~h,hl'

e{h) = eloc(h) = : : f(x) dx - P2(X) dx,

=
t h
J-h f(x)dx - 3(J(-h) + 4f(0) + f(h)).

320
14.3. FRMULA DE SIMPSON

Sea F tal que F'(x) = f(x), entonces J~h f(x) dx = F(h) - F( -h). Al
derivar con respecto a h se tiene f(h) + f( -h).
1
e'(h) = f(h) + f( -h) - 3" (J( -h) + 4f(0) + f(h))
- ~ ( - f' (- h) + f' (h) ) ,
3e'(h) = 2f(h) + 2f(-h) - 4f(0) - h(f'(h) - f'(-h)).

3e"(h) = 2f'(h) - 2f'(-h) - f'(h) + f'(-h) - h(f"(h) + f"(-h)),


= f'(h) - f'(-h) - h(f"(h) + f"(-h)).

3e"'(h) = f"(h) + f"(-h) - (f"(h) + f"(-h)) - h(f"'(h) - f"'(-h)),


= -h(f"'(h) - f"'(-h)),

e'" (h) = - ~ ( f'" (h) - f'" (- h) ),


2
e"'(h) = _ 2h f"'(h) - f"'(-h).
3 2h
De los resultados anteriores se ve claramente que e(O) = e'(O) = e"(O) =
e'" (O) = O. Adems, como f E e4, entonces 1'" E el. Por el teorema
del valor medio, existe {3 E [-h, h], {3 = o:h, o: E [-1,1], tal que

f"'(h) ~:"'( -h) = f(4) (o:h) , o: E [-1,1].

Entonces
e"'(h) = - 2~2 f(4) (o:h) , o: E [-1,1].

Sea

e"(h) = fohe"'(t) dt + e"(O),

e"(h) = -- 21
3 O
h
t 2 g4(t) dt.

321
14. INTEGRACIN Y DIFERENCIACIN

Como 94 es continua, t 2 es integrable y no cambia de signo en [O, h], se


puede aplicar el teorema del valor medio para integrales,

e"(h) = -~ 94(~4) fh t 2 dt, ~4 E [O, h],


3 Jo
e"(h) = -~ h3 94(~4).

Sea

93(h) = 94(~4) = (4) ((hh) , -1:S 03 :S 1,

entonces

e" (h) = -"92 h3 93 (h) .

De manera semejante,

e'(h) = !ah e"(t) dt + e'(O),


e' ( h) = - - 21
9 o
h
t393 (t) dt,

e'(h) = -~ 93(6) fh t 3 dt, 6 E [O, h],


9 Jo
e' (h) = - 118 h493(6).

Sea

92(h) = 93(6) = (4) (02 h) , -1:S O2 :S 1,


e '( h ) 1 h4 92(h).
= -18

322
14.3. FRMULA DE SIMPSON

e(h) = 1 h
e'(t)dt + e(O),

e(h) = -11
8
1 h
t492(t) dt,

e(h) = - 118 92(6) 1 h


4
t dt, 6 E [O, h],
1 5
e(h) = - 90 h 92(6),
h5
e(h) =- 90 (4) (()h) , -1:::; el :::; 1,
h5
e(h) = - 90 (4)(z) , -h:::; Z :::; h.

Volviendo al intervalo [xo, X2],

(14.8)

La deduccin del error global se hace de manera semejante al error global


en la frmula del trapecio. Sean n = 2k, MI = min{j(4) (x) : x E [a,b]},
M 2 = max{j(4) (x) : x E [a,b]}.

eglob = 1Ja
b
(x) dx - ( 3" ( Yo
h

j=l
k
+ 4 I: Y2j -1 + 2 I: Y2j +
k-1

j=l
Yn)),

= t (-
j=l
h5 (~bZj)), Zj E [X2j-2,X2j],

h5 k
= - 90 I: (4) (Zj)
j=l

MI :::; (4) (Zj) :::; M 2 , Vj


k
kM1 :::; I: (4)(Zj) :::; kM2 ,
j=l
1 k
MI :::; k I:(4)(Zj):::; M2,
j=l

323
14. INTEGRACIN Y DIFERENCIACIN

Entonces, existe ~ E [a, b], tal que

kLj=l k
(4) (Zj) = (4) (~),
k
L(4)(Zj) = k(4)(~),
j=l
k
" " (4) (Zj) = ?!: (4)(~),
~
)=1
2
k
L (4) (Zj) =. b- a
2h
(4)(~).
j=l

Entonces

4 (b-a)(4)(~)
eglob = -h 100 ,~ E [a, b]. (14.9)

La frmula de Simpson es exacta para polinomios de grado inferior o


igual a 3. El error global es del orden de h 4 .
Pasando de una interpolacin lineal (frmula del trapecio) a una
interpolacin cuadrtica (frmula de Simpson), el error global pasa de
O(h 2 ) a O(h 4 ), es decir, una mejora notable. Se puede ver que al utilizar
interpolacin cbica se obtiene

X3

XQ
(x)dx =
h
S(3YQ + 9Y1 + 9Y2 + 3Y3) -
3
80h5 (4)(z) , Z E [xQ, X3],

llamada segunda frmula de Simpson. Entonces el error local es O(h 5 ) y


el error global es O(h 4 ). La frmula anterior es exacta para polinomios de
grado inferior o igual a 3. En resumen, la interpolacin cbica no mejora
la calidad de la aproximacin numrica, luego es preferible utilizar la
frmula (14.7), ms sencilla y de calidad semejante.
Sin embargo, cuando se tiene una tabla fija con un nmero impar
de subintervalos (n impar, nmero par de puntos), se puede aplicar la
(primera) frmula de Simpson sobre el intervalo [xQ, Xn -3] Y la segunda
frmula sobre el intervalo [X n -3, x n ].

324
14.4. OTRAS FRMULAS DE NEWTON-COTES

14.4 Otras frmulas de Newton-Cotes

Las frmulas de Newton-Cotes se pueden clasificar en abiertas y


cerradas. Las frmulas del trapecio y de Simpson son casos particulares
de las frmulas cerradas. En ellas se aproxima la integral en el intervalo
[xo, x m] usando el polinomio de interpolacin, de grado menor o igual a
m, construido a partir de los puntos (xo, Yo), (Xl, YI), ... , (Xm-l, Ym-l),
(x m , Ym), igualmente espaciados en x.

Xm xm
xo f(x)dx>:::: xo Pm(x)dx.
La siguiente tabla muestra las ms importantes.

m error
h f"(z) 3
1 "2 (Yo + YI) ---h
12
h f(4)(z) 5
2 3(YO + 4YI + Y2) 90 h
3h 3f(4)(z) 5
3 8(YO + 3YI + 3Y2 + Y3) 80 h
2h 8 f(6)(z) 7
4 45 (7yo + 32YI + 12Y2 + 32Y3 + 7Y4) 945 h

En todos los casos, z E [xo,x m ].

14.4.1 Frmulas de Newton-Cotes abiertas

En estas frmulas el polinomio de interpolacin se calcula sin utilizar


los extremos del intervalo de integracin,

xm+2 f(x)dx>:::: Xm+2 Pm(x)dx,


l Xo Xo

donde Pm, polinomio de grado menor o igual a m, se construye utilizan-


do los puntos (Xl, YI), (X2, Y2), ... , (x m , Ym), (Xm+l, Ym+1), igualmente

325
14. INTEGRACIN Y DIFERENCIACIN

espaciados en x.

m error
f"(Z) h 3
+ __
O 2hYl
3
1
3h
2(Yl + Y2) + 3 f"(z)
h3
4
4h 14f(4)(Z) 5
2 3(2Yl - Y2 + 2Y3) + 45 h
5h 95f(4)(Z) 5
3 24 (l1Yl + Y2 + Y3 + llY4) + 144 h
En todos los casos z E [xo, Xm +2].

Ejemplo 14.4.

0.8 4 x 02
1 eX dx ~
3
. (2 eO. 2 - eO. 4 + 2 eO. 6 ) = 1.22539158.

El valor exacto, con 8 cifras decimales, es 1.22554093, entonces el error


es 0.00014935. <>

En general, las frmulas cerradas son ms precisas que las abiertas,


entonces, siempre que se pueda, es preferible utilizar las frmulas cerra-
das. Las frmulas abiertas se usan cuando no se conoce el valor de la
funcin f en los extremos del intervalo de integracin; por ejemplo, en
la solucin numrica de algunas ecuaciones diferenciales ordinarias.

14.5 Cuadratura de Gauss

En las diferentes frmulas 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(xd). 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 funcin en valores
especficos.

326
14.5. CUADRATURA DE GAUSS

La frmula de cuadratura de Gauss tiene la forma

(14.10)

Los valores Wi se llaman los pesos o ponderaciones y los Xi son las abs-
cisas. Si se desea integrar en otro intervalo,

es necesario hacer un cambio de variable,

t =
2
-(~ - a) -1, ~
b-a
= -2-(t + 1) + a, d~ = b - a dt
b-a 2

(14.11)

(14.12)

(14.13)

En la cuadratura de Gauss se desea que la frmula (14.10) sea exacta


para los polinomios de grado menor o igual que m = m n , y se desea que
este valor m n sea lo ms grande posible. En particular,
1 n

)-1
r f(x) dx = L Wi f(Xi) ,
i=l
si f(x) = 1, X, x 2, ... , xmn.

La anterior igualdad da lugar a m n + 1 ecuaciones con 2n incgnitas (los


Wi Y los Xi). De donde m n = 2n - 1, es decir, la frmula (14.10) debe
ser exacta para polinomios de grado menor o igual a 2n - 1.

Recordemos que
o si k es impar,

2
si k es par.
k+1

327
14. INTEGRACIN Y DIFERENCIACIN

Para n = 1, se debe cumplir

WI = {I 1 dx = 2,
J-l
WlXl = {l xdx = O.
J-l
Se deduce inmediatamente que
Wl = 2, Xl = O. (14.14)
Para n ~ 2, se puede suponer, sin perder generalidad, que hay simetra
en los valores Xi yen los pesos Wi. Ms especficamente, se puede suponer
que:
Xl < X2 < ... < Xn ,

Xi = -Xn+l-i ,

Wi = Wn+l-i

Para n = 2,

Wl + W2 = {l 1 dx = 2,
J-l
WlXl + W2 X 2 = {l xdx = O,
J-l
2
Wlxl +W2X2
2= JI 2dx = -2,X
-1 3

WlX~ + W2X~ = {l x 3 dx = O.
J-l
Por suposicione~ de simetra,
Xl < O< X2,

Xl = -X2,

Wl = W2

Entonces
2Wl = 2,
2 _ _2 -o
2WlXl - 3

328
14.5. CUADRATURA DE GAUSS

Finalmente,

Para n = 3,

Wl + W2 + W3 = 2,
WlXl + W2X2 + W3X3 = O,
2 2 2 2
Wlxl + W2 x 2 + w3 x 3 = 3'
Wlxl + W2 x 2 + W3 x 3 =
3 3 3 O,
4 4 4 2
Wlxl + W2 x 2 + w3 x 3 = 5'
Wl xf + W2X~ + W3X~ = o.

Por suposiciones de simetra,

Xl < O = X2 < X3 ,

Xl = -X3,
Wl = W3

Entonces

2Wl + W2 = 2,
2 2
2WlXl = 3'
4 2
2WlXl = 5

Finalmente,

Wl = ~,Xl = -/f,
8
W2 = 9,X2 = O,

W3 = ~,X3 = /f.
329
14. INTEGRACIN Y DIFERENCIACIN

La siguiente tabla contiene los valores Wi, Xi, para valores de n menores
o iguales a 4.

n Wi Xi
1 2 O
2 1 0.577350269189626
3 0.555555555555555 O. 774596669241483
0.888888888888889 O
4 0.347854845137454 0.861136311594053
0.652145154862546 0.339981043584856

Tablas ms completas se pueden encontrar en [Fr070J o en [AbS74J.


Ejemplo 14.5. Calcular una aproximacin de

0.2
0.8
eX dx

por cuadratura de Gauss con n = 3.

6 = 0.8; 0.2 (-0.774596669241483 + 1) + 0.2 = 0.26762099922756


0.8 - 0.2 ( )
6 = 2 O+ 1 + 0.2 = 0.5
6 = 0.8 =- 0.2 (0.774596669241483 + 1) + 0.2 = 0.73237900077244

0.8
0.2
e
xd
x:::::!
0.8-0.2(5 6
2 9
8
9
56)
-e +-e6 +-e
9
:::::! 1.00413814737559

El valor exacto es eO. 8 - eO. 2 = 1.00413817033230, entonces el error es


0.00000002295671 :::::! 2.3 10- 8 . Si se emplea la frmula de Simpson, que
tambin utiliza tres evaluaciones de la funcin, se tiene

0.2
0.8
dx
03
:::::! - ' -
3
(eO. 2 + 4 eO. 5 + eO. 8) = 1.00418287694532

El error es -0.00004470661302 :::::! 4.5 . 10- 5 . O

330
14.5. CUADRATURA DE GAUSS

La frmula del error para 14.10 es:


22n +1(n,)4
. (2n) (e) -1<~<1. (14.15)
en = -:-:(2-n-+-1--:--C)(:-:-,(2--'--n"-"")!):-;;-3 ." ,

Para 14.12 el error est dado por:


_ (b - a)2 n+l(n!)4(2n)(c)
en - (2n+ 1)2n)!)3 .", a < ~ < b. (14.16)

Comparemos el mtodo de Simpson y la frmula de cuadratura de Gauss


con n = 3, para integrar en el intervalo [a, b], con h = (b - a)/2. En los
dos casos es necesario evaluar tres veces la funcin.
h (4)(z) 5

es lmpson -- __
90 '
_ (2h)7(3!)4 (6) _ ~ (6)
eGauss3 - 7(6!)3 (~) - 15750 (~).
Se observa que mientras que la frmula de Simpson es exacta para poli-
nomios de grado menor o igual a 3, la frmula de Gauss es exacta hasta
para polinomios de grado 5. Sea 0< h < 1. No slo h7 < h5 , sino que el
coeficiente 1/15750 es mucho menor que 1/90.
En el ejemplo anterior, h = 0.3, Y tanto (4) como (6) varan en el
intervalo [1.22, 2.23].
.
eSlmpSOn -- - 2 . 7 10- 5 (4) (z ) ,
eGauss3 = 1.39.10- 8 (6)(0

14.5.1 Polinomios de Legendre

Las frmulas de cuadratura vistas son las frmulas de Gauss-Legen-


dre. En ellas estn involucrados los polinomios ortogonales de Legen-
dre. Tambin 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:
Po(x) = 1, (14.17)
n
1 d (2 )n (14.18)
Pn (X ) = -nn.
2' - d
xn x - 1 .

331
14. INTEGRACIN Y DIFERENCIACIN

Por ejemplo,

Po(x) = 1,
P1 (x) = x,
1 2
P2(X) = 2(3x - 1),
1 3
P3(X) = 2(5x - x),
1
P4 (x) = S (35x 4 - 30x 2 + 3).

Tambin existe una expresin recursiva:

Po (x) = 1, (14.19)
P1 (x) = x, (14.20)
2n+ 1 n
Pn+1(X) = X Pn(x) - --lPn-1(x). (14.21)
n+1 n+
Algunas de las propiedades de los polinomios de Legendre son:

(1 xkPn(x)dx=O, k=0,1,2, ... ,n-1, (14.22)


J-1
.1 1
1 Pm(x)Pn(X) dx = 0,. m i= n, (14.23)

(1 2
J_1(Pn (x))2 dx = (14.24)

Las abscisas de las frmulas de cuadratura de Gauss-Legendre son exac-


tamente las races de Pn(x). Adems,

w. = 1 (1 Pn(x) dx (14.25)
t P~(Xi) J-1 X - Xi '
1 2
(14.26)
Wi = (P~(Xi))2 1 - x; .

14.6 Derivacin numrica


Dados los puntos (xo, Yo), (Xl, Y1), ... , (x n , Yn) igualmente espaciados
en x, o sea, Xi = xo+ih, se desea tener aproximaciones de '(Xi) y "(Xi).

332
14.6. DERIVACIN NUMRICA

Como se vio anteriormente (13.6),

f(x) = Pn(x) + (x - xo)(x - Xl)'" (X - Xn)f(n+l)(~)/(n + 1)!.

Sea <I>(x) = (X-XO)(X-Xl)'" (x-x n ). Como ~ depende de x, se puede


considerar F(x) = f(n+l)(~(x))/(n + 1)!. Entonces

f(x) = Pn(x) + <I>(x)F(x)


J'(x) = p~(x) + <I>'(x)F(x) + <I>(x)F'(x),
f'(Xi) = p~(Xi) + <I>'(xi)F(Xi) + <I>(xi)F'(Xi) ,
f'(Xi) = P~(Xi) + <I>'(xdF(Xi).

Para n = 1

(Yl - YO) , () (Yl - YO)


PI (x) = Yo + h (x - xo) , PI X =
h
.

<I>(X) = (X - xo)(x - Xl), <I>'(x) = 2x - 2xo - h


Entonces

J'(Xo) = (Yl ~ YO) + (2x o _ 2xo _ h)F(xo) = (Yl ~ Yo) - ~f"(~(xo)),


f'(Xl) = (Yl - YO) + (2X l - 2xo _ h)F(Xl) = (Yl - Yo) + '2 f"(~(Xl)).
h h 2

En general,

- '22 f"(C),
." ."e E [Xi,Xi+l ] (14.27)

+ ~f"((), (E [Xi-l,Xi] (14.28) . "

El primer trmino despus del signo igual corresponde al valor aproxi-


mado. El segundo trmino es el error. Se acostumbra decir que el error
es del orden de h. Esto se escribe

333
14. INTEGRACIN Y DIFERENCIACIN

Para n = 2, sea s = (x - xo)/h,


2
P2(X) = Yo + sb..fo + s(s - 1) b.. fo
<'O 2'
2
P2(x)=Yo+x-x0b..fo+x-xO x-xo-h b.. fo
h h h --2-'
p~(x) = b..fo
2
+ 2x - 2xo - h b.. fo
h h2 --2-'
f 2
p;(XI) = b.. o + b.. fo = ...
h 2h
,( Y2 - Yo
P2 Xl) = .
2h

<I>(X) = (X - xo)(x - Xo - h)(x - Xo - 2h),


<I>(x) = (X :..- xO)3 - 3h(x - xO)2 + 2h2(x - xo),
<I>'(x) = 3(x - xO)2 - 6h(x - xo) + 2h 2,
<I>'(xd = 3h2 - 6h 2 + 2h 2 = _h 2.

Entonces
2
f '( Xl ) = Y2 - Yo
<'OL - 6h f"'(C)
"', 'C" E [xo, x2 1.
De manera general, ,,,\
(.
2
f '()
Xi = Yi+l - Yi-l
2h h f"'(C)
- 6 "', 'C" E [xi-l, Xi+l 1, (14.29)

f'(Xi) = Yi+l : Yi-l + O(h 2).

En [YoG72], pgina 357, hay una tabla con varias frmulas para diferen-
ciacin numrica. Para la segunda derivada, una frmula muy empleada
es:
2
f "( x~.) -- Yi+l - 2Yi +
h2
Yi-l _ h
12
f(4)(~), ~ E [Xi-l, Xi+1], (14.30)

f " (Xi) -_ Yi+l - 2Yi


J.?
+ Yi-l + O(h 2).

La deduccin de las frmulas de derivacin numrica se hizo a partir


de una tabla de valores (Xi, yd, pero para el uso de stas solamente se
requiere conocer o poder evaluar f en los puntos necesarios. Por esta

334
14.6. DERIVACIN NUMRICA

razn, algunas veces las frmulas aparecen directamente en funcin de


h:

1'(x) = f(x + h~ - f(x) + O(h),


f'(x) = f(x) - ~(x - h) + O(h),
f'(x) = f(x + h) ~f(x - h) + O(h2),

f"(x) = f(x + h) - 2~~X) + f(x - h) + O(h2).

Ejemplo 14.6. Dada f(x) = yIX, evaluar aproximadamente f'(4) y


f"(4), utilizando h = 0.2.

1'(4) ~ 2.0494 - 2 = 0.2470


0.2
1'(4) ~ 2 - 1.9494 = 0.2532
0.2
f'(4) ~ 2.0494 - 1.9494 = 0.2501
2 x 0.2
f"(4) ~ 2.0494 - 2 x 22 + 1.9494 = -0.0313. <>
0.2
El error de las dos primeras aproximaciones no es el mismo, pero es .
del mismo orden de magnitud O(h). La tercera aproximacin es mejor
que las anteriores; su error es del orden de O(h 2 ). Los valores exactos.
son 1'(4) = 0.25, 1"(4) = -0.03125.

Ejercicios

14.1 Calcule
{l eXdx
JO.2
utilizando la frmula del trapecio y de Simpson, variando el nme-
ro de subintervalos. Tambin por medio de la cuadratura de Gauss
variando el nmero puntos. Calcule los errores. Compare.

14.2 Calcule

335
14. INTEGRACIN Y DIFERENCIACIN

utilizando la frmula de Simpson. Utilice seis cifras decimales. To-


me los valores n = 2, 4, 8, 16, 32 ... hasta que no haya variacin.

14.3 Haga un programa para calcular J: f(x)dx, siguiendo el esquema


del ejercicio anterior.

14.4 Observe, por ejemplo, que para n = 2 se evala la funcin en a,


(a + b)/2, b. Para n = 4 se evala la funcin en a, a + (b - a)/4,
(a + b)/2, a + 3(b - a)/4, b. Haga el programa eficiente para que
no evale la funcin dos veces en el mismo punto.

14.5 Haga un programa para calcular J:


f(x)dx, partiendo [a, b] en su-
bintervalos y utilizando en cada subintervalo cuadratura de Gauss.

14.6 Considere los puntos


(0.05, 2.0513),
(0.10,2.1052),
(0.15,2.1618),
(0.20,2.2214),
(0.25, 2.2840),
(0.30,2.3499),
(0.35, 2.4191),
(0.40, 2.4918).
Calcule de la mejor manera posible

0.35

0.05
f(x)dx, 0.05
0.40
f(x)dx,
r.45
Jo
0.05
f(x)dx.

14.7 Considere los mismos puntos del ejercicio anterior. Calcule una
aproximacin de f'(0.25), f'(0.225), 1"(0.30).

14.8 Combine integracin numrica y solucin de ecuaciones para re-


solver X

e
_t 2
dt = 0.1.

336
15

Ecuaciones diferenciales

Este captulo se refiere nicamente a ecuaciones diferenciales or-


dinarias. Generalmente una ecuacin diferencial ordinaria de primer
orden con condiciones iniciales, ED01CI, se escribe de la forma

y' = f(x, y) para a :S x :S b,


(15.1)
y(xo) = yo

Frecuentemente la condicin inicial est dada sobre el extremo izquierdo


del intervalo, o sea, a = xo. Un ejemplo de ED01CI es:

Y, = xy + 3x 2 x E [2 4]
l+x 2 +y 2 ' "

y(2) = 5.
Temas importantsimos como existencia de la solucin, unicidad o esta-
bilidad, no sern tratados en este texto. El lector deber remitirse a un
libro de ecuaciones diferenciales. Aqu se supondr que las funciones sa-
tisfacen todas las condiciones necesarias (continuidad, diferenciabilidad,
condicin de Lipschitz ... ) para que la solucin exista, sea nica ...
Como en todos los otros casos de mtodos numricos, la primera
opcin para resolver una ED01CI es buscar la solucin analtica. Si
esto no se logra, entonces se busca la solucin numrica que consiste en
encontrar valores aproximados YI, Y2, ... , Yn tales que

Yi ~ Y(Xi), i = 1, ... , n, donde a = Xo < Xl < X2 < '" < Xn = b.

337
15. ECUACIONES DIFERENCIALES

En muchos casos los valores Xi estn igualmente espaciados, o sea,

Xi = a + ih, i = 0,1, ... , n, con h = b - a


n
En varios de los ejemplos siguientes se aplicarn los mtodos numricos
para ecuaciones diferenciales con solucin analtica conocida. Esto se
hace simplemente para comparar la solucin numrica con la solucin
exacta.

15.1 Mtodo de Euler


Se aplica a una EDOICI como en (15.1) utilizando puntos igualmente
espaciados. Su deduccin es muy sencilla.

Y'(Xo) ~ y(xo + h) - y(xo)


h

Por otro lado

y'(Xo) = f(xo, YO).

Entonces

y(xo + h) ~ Yo + hf(xo, YO).


Si denotamos por Yl la aproximacin de y(xo + h), entonces la frmula
del mtodo de Euler es justamente

Yl = Yo + hf(xo, YO).

Aplicando varias veces el mismo tipo de aproximaciones, se tiene la


frmula general:

Yi+l = Yi + hf(Xi, yd (15.2)

Grficamente esto significa que Y(Xi + h) = Y(Xi+t) se aproxima por el


valor obtenido a partir de la recta tangente a la curva en el punto (Xi, Yi).

338
15.1. MTODO DE EULER

(Xl, YI)

Y(Xo + h) ----------- ----~-~-~-~---~---

Yo = y(XO)

Xo Xo +h
Figura 15.1 Mtodo de Euler.

El valor YI es una aproximacin de Y(XI). A partir de YI, no de Y(XI),


se hace una aproximacin de y'(XI). Es decir, al suponer que Y2 es una
aproximacin de Y(X2), se han hecho dos aproximaciones consecutivas
y el error pudo haberse acumulado. De manera anloga, para decir que
Y3 es una aproximacin de Y(X3), se han hecho tres aproximaciones, una
sobre otra.
Sea ({J(t, h) definida para tI ::; t ::; t2 Y para valores pequeos de h.
Se dice que
({J(t, h) = O(hP)

si para valores pequeos de h existe una constante e tal que

Tambin se acostumbra decir que

El error local tiene que ver con el error cometido para calcular Y(Xi+1)
suponiendo que Yi es un valor exacto, es decir, Yi = Y(Xi). El error global
es el error que hayal considerar Yn como aproximacin de y(x n) (n indica
el nmero de intervalos).
Los resultados sobre el error en el mtodo de Euler son:
2 (15.3)
YI = Y(XI) + O(h )
Yn = y(x n ) + O(h). (15.4)

339
15. ECUACIONES DIFERENCIALES

Ejemplo 15.1. Resolver, por el mtodo de Euler, la ecuacin diferencial

y' = 2x 2 - 4x +Y
y(1) = 0.7182818

en el intervalo [1,3], con h = 0.25.


La primera observacin es que esta ecuacin diferencial se puede
resolver analticamente. Su solucin es y = eX - 2x 2 . Luego no debera
ser resuelta numricamente. Sin embargo, el hecho de conocer su solucin
exacta permite ver el error cometido por el mtodo numrico.

Yl = Yo + hf(xo, Yo)
= 0.7182818 + 0.25f(1, 0.7182818)
= 0.7182818 + 0.25(0.7182818 + 2 x 12 - 4 x 1)
= 0.3978523
Y2 = Yl + hf(Xl, yd
= 0.3978523 + 0.25f(1.25, 0.3978523)
= 0.3978523 + 0.25(0.3978523 + 2 x 1.252 - 4 x 1.25)
= 0.0285654
Y3 = ...

Xi I Y(Xi) y(xd
1.00 0.7182818 0.7182818
1.25 0.3978523 0.3653430
1.50 0.0285654 -0.0183109
1.75 -0.3392933 -0.3703973
2.00 -0.6428666 -0.6109439
2.25 -0.8035833 -0.6372642
2.50 -0.7232291 -0.3175060
2.75 -0.2790364 0.5176319
3.00 0.6824545 2.0855369

340
15.2. MTODO DE HEUN

1

o


-1 +------,-------------r------------~--

1 2 3
Figura 15.2 Mtodo de Euler.
En los primeros valores se observa que el error es muy pequeo. A
partir de x = 2 se empiezan a distanciar los valores jj(x) y y(x). Si se
trabaja con h = 0.1 se obtiene jj(3) = 1.4327409; con h = 0.01 se obtiene
y(3) = 2.0133187; con h = 0.001 se obtiene y(3) = 2.0782381. O

15.2 Mtodo de Heun


Este mtodo es una modificacin o mejora del mtodo de Euler y
se utiliza para el mismo tipo de problemas. Tambin se conoce con el
nombre de mtodo del trapecio. En el mtodo de Euler se utiliza la
aproximacin
y(x + h) = y(x) + hy'(x).
En el mtodo de Heun se busca cambiar, en la aproximacin anterior, la
derivada en x por un promedio de la derivada en x y en x + h.

y(xo + h)
Yo = y(xo)

Xo Xo +h
Figura 15.3 Mtodo de Heun.

341
15. ECUACIONES DIFERENCIALES

y(x + h) :=::; y(x) + h y'(x) + y'(x + h)


2

o sea,

y(x + h) :=::; y(x) +h f(x, y(x)) + f(x + h, y(x + h))


2

La frmula anterior no se puede aplicar. Sirve para aproximar y(x + h)


pero utiliza y(x+h). Entonces, en el lado derecho, se reemplaza y(x+h)
por la aproximacin dada por el mtodo de Euler

y(x + h) :=::; y(x) + h f(x, y(x)) + f(x + h, y(x) + hf(x, y(x)))


2

La anterior aproximacin suele escribirse de la siguiente manera:

Kl = hf(Xi, Yi)
K2 = hf(Xi + h, Yi + K 1) (15.5)
1
Yi+l = Yi + "2(K1 + K 2 ).

Ejemplo 15.2. Resolver, por el mtodo de Heun, la ecuacin diferencial

y' = 2x 2 - 4x + Y
y(l) = 0.7182818

en el intervalo [1,3], con h = 0.25.

342
15.2. MTODO DE HEUN

K 1 = hf(xo, YO)
= 0.25f(1, 0.7182818)
= -0.320430
K 2 = hf(xo + h, Yo + Kl)
= 0.25f(1.25, 0.397852)
= -n.369287
Yl = Yo + (K1 + K2)/2
= 0.3734236

K 1 = hf(Xl, Yl)
= 0.25f(1.25, 0.3734236)
= -0.375394
K2 = hf(Xl + h, Yl + K 1 )
= 0.25f(1.500000, -0.001971)
= -0.375493
Y2 = Yl + (K1 + K2)/2
= -0.0020198

1.00 0.7182818 0.7182818


1.25 0.3734236 0.3653430
1.50 -0.0020198 -0.0183109
1.75 -0.3463378 -0.3703973
2.00 -0.5804641 -0.6109439
2.25 -0.6030946 -0.6372642
2.50 -0.2844337 -0.3175060
2.75 0.5418193 0.5176319
3.00 2.0887372 2.0855369

343
15. ECUACIONES DIFERENCIALES

-1 +I------,------------,------------~--
1 2 3
Figura 15.4 Mtodo de Heun.

En este ejemplo los resultados son mucho mejores. Por un lado, el


mtodo es mejor, pero, por otro, es natural tener mejores resultados pues
hubo que evaluar 16 veces la funcin (x, y), 2 veces en cada iteracin.
En el ejemplo del mtodo de Euler hubo simplemente 8 evaluaciones de la
funcin (x, y). Al aplicar el mtodo de Heun con h = 0.5 (es necesario
evaluar 8 veces la funcin) se obtiene y(3) = 2.1488885, resultado no
tan bueno como 2.0887372, pero netamente mejor que el obtenido por el
mtodo de Euler. Si se trabaja con h = 0.1 se obtiene y(3) = 2.0841331;
con h = 0.01 se obtiene y(3) = 2.0855081; con h = 0.001 se obtiene
y(3) = 2.0855366. <>

15.3 Mtodo del punto medio

Tambin este mtodo es una modificacin o mejora del mtodo de


Euler y se utiliza para el mismo tipo de problemas. En el mtodo de
Euler se utiliza la aproximacin

y(x + h) = y(x) + hy'(x).

En el mtodo del punto medio se busca cambiar, en la aproximacin


anterior, la derivada en x por la derivada en el punto medio entre x y
x + h, o sea, por la derivada en x + h/2.

344
15.3. MTODO DEL PUNTO MEDIO

y(xo + h)
I (Xl,Yl)
I
Yo = Y(Xo) I
I
I
I
I
I
I

Xo Xo + h/2 Xo +h

Figura 15.5 Mtodo del punto medio.

y(x + h) :::::: y(x) + hy'(x + h/2)


o sea,

y(x + h) :::::: y(x) + h f( x + h/2, y(x + h/2))


Como no se conoce y(x + h/2), se reemplaza por la aproximacin que
dara el mtodo de Euler con un paso de h/2.

h
y(x + h/2) :::::: y(x) + "2 f(x, y)
h
y(x + h) :::::: y(x) + hf(x + h/2,y(x) + "2 f (x,y)).
La anterior aproximacin suele escribirse de la siguiente manera:

Kl = hf(Xi, Yi)
K2 = hf(Xi + h/2, Yi + K1/2) (15.6)
Yi+l = Yi + K 2

Ejemplo 15.3. Resolver, por el mtodo del punto medio, la ecuacin


diferencial

y' = 2x2 - 4x + Y
y(1) = 0.7182818

345
15. ECUACIONES DIFERENCIALES

en el intervalo [1,3J, con h = 0.25.

K 1 = hf(xo, YO)
= 0.25f(1, 0.7182818)
= -0.320430
K 2 = hf(xo + h/2, Yo + KI/2)
= 0.25f(1.125, 0.558067)
= -0.352671
Yl = Yo +K2
= 0.3656111

K 1 = hf(Xl, Yl)
= 0.25f(1.25, 0.3656111)
= -0.377347
K 2 = hf(Xl + h/2, Yl + KI/2)
= 0.25f(1.375, 0.176937)
= -0.385453
Y2 = Yl + K 2
= -0.0198420

K1 = oo'

Xi I ii(Xi) Y(Xi)
1.00 0.7182818 0.7182818
1.25 0.3656111 0.3653430
1.50 -0.0198420 -0.0183109
1.75 -0.3769851 -0.3703973
2.00 -0.6275434 -0.6109439
2.25 -0.6712275 -0.6372642
2.50 -0.3795415 -0.3175060
2.75 0.4121500 0.5176319
3.00 1.9147859 2.0855369

346
15.4. MTODO DE RUNGE-KUTTA

-1 +-----~------------~------------~--

1 2 3
Figura 15.6 Mtodo del punto medio.
Tambin, en este ejemplo, los resultados son mucho mejores. De nue-
vo hubo que evaluar 16 veces la funcin (x, y), 2 veces en cada iteracin.
Al aplicar el mtodo del punto medio con h = 0.5 (es necesario evaluar
8 veces la funcin) se obtiene i/(3) = 1.5515985, resultado no tan bueno
como 2.0887372, pero netamente mejor que el obtenido por el mto-
do de Euler. Si se trabaja con h = 0.1 se obtiene i/(3) = 2.0538177;
con h = 0.01 se obtiene i/(3) = 2.0851903; con h = 0.001 se obtiene
i/(3) = 2.0855334. (>

15.4 Mtodo de Runge-Kutta


El mtodo de Runge-Kutta o, ms bien, los mtodos de Runge-Kutta
se aplican a una ED01CI como en (15.1) utilizando puntos igualmente
espaciados. La forma general del mtodo RK de orden n es la siguiente:
K 1 = hf(Xi, Yi)
K 2 = hf(Xi + Ct2h, Yi + f321 K d
K3 = hf(Xi + Ct3h, Yi + f331 K l + f332 K 2)
(15.7)

Kn = hf(Xi + Ctnh, Yi + f3nl K l + f3n2 K 2 + ... + f3n,n-l K n-l)


Yi+1 = Yi + RIKl + R 2K 2 + ... + RnKn
Se ve claramente que los mtodos vistos son de RK: el mtodo de Euler
es uno de RK de orden 1, el mtodo de Heun y el del punto medio son
mtodos de RK de orden 2.

347
15. ECUACIONES DIFERENCIALES

Mtodo de Euler:

K = hf(Xi, Yi)
Yi+ = Yi + K.

Mtodo de Heun:

K = hf(Xi, Yi)
K 2 = hf(Xi + h, Yi + K)
1 1
Yi+1 = Yi + 2"K + 2"K2.

Mtodo del punto medio:

K = hf(Xi, Yi)
1 1
K2 = hf(Xi + 2"h, Yi + 2"K)
Yi+ = Yi + OK + K2

Un mtodo muy popular es el siguiente mtodo RK de orden 4:

K = hf(Xi, Yi)
K2 = hf(Xi + h/2, Yi + Kf2)
K3 = hf(Xi + h/2, Yi + K2/2) (15.8)
K4 = hf(Xi + h, Yi + K3)
Yi+ = Yi + (K + 2K2 + 2K3 + K4)/6.

Ejemplo 15.4. Resolver, por el mtodo RK4 anterior, la ecuacin di-


ferencial

y' = 2x2 - 4x + y
y(1) = 0.7182818

348
15.4. MTODO DE RUNGE-KUTTA

en el intervalo [1,3]' con h = 0.25.

K 1 = hf(xo, YO)
= 0.25f(1, 0.7182818)
= -0.320430
K 2 = hf(xo + h/2, Yo + KI/2)
= 0.25f(1.125, 0.558067)
= -0.352671
K3 = hf(xo + h/2, Yo + K2/2)
= 0.25f(1.125, 0.541946)
= -0.356701
K4 = hf(xo + h, Yo + K 3)
= 0.25f(1.25, 0.361581)
= -0.378355
Yl = Yo + (K1 + 2K2 + 2K3 + K4)/6
= 0.3653606

K 1 = hf(Xl, Yl)
= 0.25f(1.25, 0.3653606)
= -0.377410
K2 = hf(Xl + h/2, Yl + KI/2)
= 0.25f(1.375, 0.176656)
= -0.385524

K3 = hf(Xl + h/2, Yl + K2/2)


= 0.25f(1.375, 0.172599)
= -0.386538
K4 = hf(Xl + h, Yl + K3)
= 0.25f(1.5, -0.02117)
= -0.380294
Y2 = Yl + (Kl + 2K2 + 2K3 + K 4 )/6
= -0.0182773

349
15. ECUACIONES DIFERENCIALES

Xi I Y(Xi) Y(Xi)
1.00 0.7182818 0.7182818
1.25 0.3653606 0.3653430
1.50 -0.0182773 -0.0183109
1.75 -0.3703514 -0.3703973
2.00 -0.6108932 -0.6109439
2.25 -0.6372210 -0.6372642
2.50 -0.3174905 -0.3175060
2.75 0.5175891 0.5176319
3.00 2.0853898 2.0855369

-1 +I~~~---'--~~~~~~--.~~~~~~-----r-

1 2 3
Figura 15.7 Mtodo de Runge-Kutta 4.

En este ejemplo, los resultados son an mejores. Hubo que evaluar


32 veces la funcin (x, y), 4 veces en cada iteracin. Si se trabaja con
h = 0.1 se obtiene y(3) = 2.0855314; con h = 0.01 se obtiene y(3)
2.0855369; con h = 0.001 se obtiene y(3) = 2.0855369. <>

15.5 Deduccin de RK2

En secciones anteriores se hizo la deduccin, de manera ms o menos


intuitiva, de los mtodos de Heun y del punto medio. Los dos resultan
ser mtodos de RK de orden 2. En esta seccin veremos una deduccin
diferente y general de RK2.

350
15.5. DEDUCCiN DE RK2

El mtodo RK2 tiene el siguiente esquema:

K 1 = hf(Xi, Yi)
K 2 = hf(Xi + 0'.2 h , Yi + /321 K t)
Yi+l = Yi + RI K l + R2 K 2.

Como hay un solo coeficiente O'. y un solo coeficiente /3, utilicmoslos sin
subndices:

Kl = hf(Xi, Yi)
K2 = hf(Xi + O'.h, Yi + /3K 1)
Yi+1 = Yi + RI K l + R 2K 2.

Sea 9 una funcin de dos variables. Si 9 es diferenciable en el punto


(u, v), entonces
, se puede utilizar la siguiente aproximacin de primer
orden:

g(u + ~u, V + ~v) ~ g(u, v) + ~u ~~ (u, v) + ~v ~~ (u, v). (15.9)

La aproximacin de segundo orden para Y(Xi + h) es:

h2
Y(Xi + h) = y(xd + hy'(Xi) + 2 Y"(Xi) + O(h3 ) (15.10)
h2
Y(Xi + h) ~ Y(Xi) + hy'(Xi) + 2 y"(Xi). (15.11)

En la aproximacin anterior, podemos tener en cuenta que Y(Xi) = Yi,


Y que y'(xd = f(Xi, Yi). Adems,

351
15. ECUACIONES DIFERENCIALES

Para acortar la escritura utilizaremos la siguiente notacin:

f := f(Xi, Yi)
af
fx := ax f(Xi, Yi)
af
fy := ay f(Xi, Yi)
y := Y(Xi)
y' := y'(Xi) = f(Xi, Yi) = f
y" := y"(Xi).

Entonces

y" = fx + ffy
h2 h2
Y(Xi + h) ';:::;, y + hf + 2" fx + 2" f fy (15.12)

Por otro lado, el mtodo RK2 se puede reescribir:

Yi+l = Yi + Rlhf(Xi, Yi) + R2 h f(Xi + ah, Yi + f3K 1 ).


Utilizando (15.9):

Yi+l = Yi + Rlhf(Xi, Yi)


f
+ R2 h ( f(Xi, Yi) + ah af a )
ax (Xi, Yi) + f3K 1 ay (Xi, Yi) .

Utilizando la notacin se obtiene:

Yi+l = Y + Rlhf + R2 h (f + ahfx + f3 K d y)


Yi+l = y + (R 1 + R 2 )hf + R2h2afx + R2hf3 K d y

Como Kl = hf, entonces

Yi+l = Y + (R 1 + R 2)hf + R2 ah2 fx + R2f3h 2f fy (15.13)

Al hacer la igualdad Y(Xi + h) = Yi+l, en las ecuaciones (15.12) y (15.13)

352
15.6. CONTROL DEL PASO

se comparan los coeficientes de hf, de h 2 fx y de h 2 f fy y se deduce:

Rl + R2 = 1,
1
R2 a = -
2'
1
R2/3 -- -2'

Entonces

/3 = a, (15.14)
1
R2=-' (15.15)
2a
Rl = 1- R2 (15.16)

Si a = 1, entonces /3 = 1, R2 = 1/2 Y Rl = 1/2, es decir, el mtodo


de Heun. Si a = 1/2, entonces /3 = 1/2, R2 = 1 Y Rl = 0, es decir, el
mtodo del punto medio. Para otros valores de a se tienen otros mtodos
de RK de orden 2.

15.6 Control del paso


Hasta ahora se ha supuesto que para hallar la solucin numenca
de una ecuacin diferencial, los puntos estn igualmente espaciados, es
decir, Xi - Xi-l = h para i = 1,2, ... , n. Esta poltica no es, en gene-
ral, adecuada. Es preferible utilizar valores de h pequeos cuando es
indispensable para mantener errores relativamente pequeos, y utilizar
valores grandes de h cuando se puede.
Hay varios mtodos para el control de h. En uno de ellos, se supone
conocido Yi, una muy buena aproximacin de Y(Xi), y se aplica un mto-
do con un paso h para obtener i aproximacin de Y(Xi + h). Tambin se
aplica el mismo mtodo dos veces con el paso h/2 para obtener y,otra
aproximacin de y (Xi + h). Con estos dos valores se puede acotar el error
y as saber si es necesario trabajar con un paso ms pequeo.
En otro enfoque, el que veremos en esta seccin, se aplican dos mto-
dos diferentes, con el mismo h y con estas dos aproximaciones se acota el
error. As se determina la buena o mala calidad de las aproximaciones.

353
15. ECUACIONES DIFERENCIALES

Supongamos que tenemos dos mtodos: el mtodo A con error local


O(hP ) y el mtodo B con error local O(hP+ I ) (o con error local O(h q ), q 2:
p+ 1). Partimos de Yi, muy buena aproximacin de Y(Xi)' Aplicando los
dos mtodos calculamos YA y YB, aproximaciones de Y(Xi+h). El control
de paso tiene dos partes: en la primera se obtiene una aproximacin del
posible error obtenido.

lerrorl ~ e = /'PI(YA,YB,h,p).

Si e es menor o igual que un valor E dado, entonces se acepta YB


como buena aproximacin de y(x + h). En caso contrario, es necesario
utilizar un valor de h ms pequeo. En ambos casos el valor de h se
puede modificar, bien sea por necesidad (e > E), bien sea porque, siendo
h aceptable, es conveniente modificarlo para el siguiente paso. Para ello
se calcula un coeficiente C o que sirve para obtener C coeficiente de h

Co = /'P2(YA, YB, h,p)


C = <p(Co, ... )
h' = Ch.

Los diferentes algoritmos difieren en la manera de calcular e, Co y


C (las funciones /'PI, /'P2 Y <p). Ms an, para el mismo mtodo A y el
mismo mtodo B hay diferentes algoritmos.
Un mtodo muy popular es el de Runge-Kutta-Fehlberg, cons-
truido a partir de un mtodo de RK de orden 5 (el mtodo A) y de un
mtodo de RK de orden 6 (el mtodo B). Una de sus ventajas est dada
por el siguiente hecho: los valores K I , K 2 , K 3 , K4 Y K5 son los mismos
para los dos mtodos. Teniendo en cuenta la forma general (15.7) del
mtodo RK, basta con dar los valores ni Y (3ij. Recurdese que siempre
KI = hf(Xi, Yi).

354
15.6. CONTROL DEL PASO

Di f3i1 f3i2

1 1
2 - -
4 4
3 3 9
3 -
8 32 32
12 1932 7200 7296
4
13 2197 2197 2197
439 3680 845
5 1 -8 ---
216 513 4104
1 8 3544 1859 11
6 - 2 ---
2 27 2565 4104 40

_. 25 K 1408 2197 _ ~
YA-Yt+216K1+0 2+ 2565K3+ 4104 K4 5 K5
-. 16 K OK 6656 K 28561 K - ~K ~K
YB - Yt + 135 1 + 2 + 12825 3 + 56430 4 50 5 + 55 6
(15.17)

Los errores locales son respectivamente O(h 5 ) y O(h 6 ). Realmente hay


varias frmulas RK5 y RK6; las anteriores estn en [BuF85] y [EnU96].
Hay otras frmulas diferentes en [ChC99].
La aproximacin del error est dada por

IYA -YBI
Ierror I ;::::j e = h . (15.18)

El coeficiente para la modificacin del valor de h est dado por:

Co = 0.84 ( ~
E) 1/4 ,
C = min{Co,4}, (15.19)

C = max{C,O.l}.

Las frmulas anteriores buscan que C no sea muy grande ni muy pe-
queo. Ms especficamente, C debe estar en el intervalo [0.1, 4].

355
15. ECUACIONES DIFERENCIALES

En la descripcin del algoritmo usaremos la siguiente notacin 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.

MTODO RUNGE-KUTTA-FEHLBERG
datos: xo, Yo, b, ho, , hmin
x = xo, Y = Yo, h = ho
X = [xo], Y = [Yo]
mientras x < b
h=min{h,b-x}
hbien = O
mientras hbien = O
calcular Ya, YB segn (15.17)
e = IYA - YBI/h
si e ~
X = X + h, Y = YB
bienh = 1
X = [X; x], Y = [Y; y]
fin-si
Co = O.84(/e)1/4
C = max{Co,O.l}, 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 pequeo. 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 versin ligeramente ms eficiente, inicialmente no se calcula
YA ni YB Se calcula directamente

_J_1-K _
e- 360 1
128
4275 K3
_ 2197 K4
75240 +
~K
50 5 +
~ K6
55
J

356
15.6. CONTROL DEL PASO

Cuando el valor de h es adecuado, entonces se calcula YB para poder


hacer la asignacin y = y B.

Ejemplo 15.5. Resolver, por el mtodo RKF con control de paso, la


ecuacin diferencial

y' = 2x 2 - 4x +Y
y(1) = 0.7182818

en el intervalo [1,3], con ho = 0.5 Y E = 10-6 .

YA = -0.01834063
YB = -0.01830704
e = 0.00006717

h = 0.5 no sirve.

eo = 0.29341805
e= 0.29341805
h = 0.14670902
YA = 0.51793321
YB = 0.51793329
e = 0.00000057

h = 0.14670902 sirve.

x = 1.14670902
Y = 0.51793329
eo = 0.96535578
e = 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
-- -- -
h - -
y(x)
-
-
y(x)
-
1

1.0000000 0.1467090 0.7182818 0.7182818


1.1467090 0.1416264 0.5179333 0.5179333
1.2883354 0.1622270 0.3071282 0.3071282
1.4505624 0.1686867 0.0572501 0.0572501
1.6192491 0.1333497 -0.1946380 -0.1946380
1.7525988 0.1329359 -0.3736279 -0.3736279
1.8855347 0.1191306 -0.5206051 -0.5206051
2.0046653 0.1092950 -0.6137572 -0.6137571
2.1139603 0.1024064 -0.6566848 -0.6566847
2.2163666 0.0971218 -0.6506243 -0.6506241
2.3134884 0.0928111 -0.5948276 -0.5948275
2.4062996 0.0891591 -0.4877186 -0.4877184
2.4954587 0.0859853 -0.3273334 -0.3273332
2.5814440 0.0831757 -0.1114979 -0.1114977
2.6646196 0.0806534 0.1620898 0.1620900
2.7452730 0.0783639 0.4958158 0.4958160
2.8236369 0.0762674 0.8921268 0.8921270
2.8999043 0.0743333 1.3535162 1.3535164
2.9742376 0.0257624 1.8825153 1.8825156
3.0000000 2.0855366 2.0855369

358
15.7. ORDEN DEL MTODO Y ORDEN DEL ERROR

-1 +------,----------;r-------~-

1 2 3
Figura 15.8 Mtodo de Runge-Kutta-Fehlberg.

15.7 Orden del mtodo y orden del error

Para algunos de los mtodos hasta ahora vistos, todos son mtodos
de RK, se ha hablado del orden del mtodo, del orden del error local y
del orden del error global.
El orden del mtodo se refiere al nmero de evaluaciones de la funcin
f en cada iteracin. As por ejemplo, el mtodo de Euler es un mtodo
de orden 1 y el mtodo de Heun es un mtodo de orden 2.
El orden del error local se refiere al exponente de h en el error terico
cometido en cada iteracin. Si la frmula es

se dice que el error local es del orden de hP , o simplemente, el error local


es de orden p.
El orden del error global se refiere al exponente de h en el error
obtenido al aproximar y(b) despus de hacer (b - xo)/h iteraciones.
Hemos visto seis mtodos, Euler, Heun, punto medio, un RK4, un
RK5 y un RK6. La siguiente tabla presenta los rdenes de los errores.

359
15. ECUACIONES DIFERENCIALES

Mtodo Frmula Orden del Error


mtodo local
Euler (15.2) 1 O(h 2 )
Heun (15.5) 2 O(h 3 )
Punto medio (15.6) 2 O(h 3 )
RK4 (15.8) 4 O(h 5 )
RK5 (15.17) 5 O(h 5 )
RK6 (15.17) 6 O(h6 )

El orden del error global es generalmente igual al orden del error


local menos una unidad. Por ejemplo, el error global en el mtodo de
Euler es O(h).
A medida que aumenta el orden del mtodo, aumenta el orden del
error, es decir, el error disminuye. Pero al pasar de RK4 a RK5 el orden
del error no mejora. Por eso es ms interesante usar el RK4 que el RK5
ya que se hacen solamente 4 evaluaciones y se tiene un error semejan-
te. Ya con RK6 se obtiene un error ms pequeo, pero a costa de dos
evaluaciones ms.

15.7.1 Verificacin numrica del orden del error


Cuando se conoce la solucin exacta de una ecuaClOn diferencial,
en muchos casos, se puede verificar el orden del error de un mtodo
especfico. Ms an, se podra obtener el orden del error si ste no se
conociera.
Sea O(hP ) el error local del mtodo. Se puede hacer la siguiente
aproximacin:
error = e ;::::; chp .
Al tomar logaritmo en la aproximacin anterior se obtiene

log(e) ;::::; log(c) + plog(h) (15.20)

Para diferentes valores de h se evala el error cometido y se obtienen


as varios puntos de la forma (log(hi ), log(ei)). Estos puntos deben estar,
aproximadamente, sobre una recta. La pendiente de esta recta es preci-
samente p. El valor de p se puede obtener grficamente o por mnimos
cuadrados.

360
15.7. ORDEN DEL MTODO Y ORDEN DEL ERROR

Ejemplo 15.6. Obtener numricamente el orden del error local del


mtodo de Heun usando la ecuacin diferencial

y' = 2x 24x + Y
-

y(l) = 0.7182818,

con h = 0.1, 0.12, 0.14, 0.16, 0.18 Y 0.2.

h xo+h y(xo + h) y(xo + h) e log(h) log(e)


0.10 1.10 0.584701 0.584166 0.000535 -2.302585 -7.532503
0.12 1.12 0.556975 0.556054 0.000921 -2.120264 -6.989970
0.14 1.14 0.529024 0.527568 0.001456 -1.966113 -6.532007
0.16 1.16 0.500897 0.498733 0.002164 -1.832581 -6.135958
0.18 1.18 0.472641 0.469574 0.003067 -1.714798 -5.787212
0.20 1.20 0.444304 0.440117 0.004187 -1.609438 -5.475793

En la siguiente grfica, log(h) en las abscisas y log(e) en las ordena-


das, los puntos estn aproximadamente en una recta.

-5

-6


-7

-8 '--_ _-'--_ _ - - L_ _----'_ __

-2.5 -2.0 -1.5


Figura 15.9 Orden local.

Al calcular numricamente los coeficientes de la recta de aproxima-


cin por mnimos cuadrados, se obtiene

log(e) ~ 2.967325 log(h) - 0.698893


e ~ 0.497135h 2.97

Estos resultados numricos concuerdan con el resultado terico. <>

361
15. ECUACIONES DIFERENCIALES

15.8 Mtodos multipaso explcitos

Los mtodos RK son considerados como mtodos monopaso (unipa-


so) por la siguiente razn. El valor Yi+l se calcula nicamente a partir del
punto (Xi, Yi). En los mtodos multipaso se utilizan otros puntos ante-
riores, por ejemplo, para calcular Yi+1 se utilizan los puntos (Xi-2, Yi-2),
(Xi-l, Yi-I) y (Xi, Yi).
Veamos un caso particular. Supongamos que se conocen los valores
Yo = Y(xo), YI = Y(XI) Y Y2 = Y(X2)' Por facilidad para la deduccin,
supongamos que Xo = h, Xl = h y X2 = 2h.
Sea P2 (X) el polinomio de grado menor o igual a 2 que interpola a J
en los valores O, h y 2h, es decir, el polinomio pasa por los puntos (O, Jo),
(h, JI) y (2h,"12), donde Ji = J(Xi, Yi). Este polinomio se puede obtener
utilizando polinomios de Lagrange:

(X ~ h)(x - 2h) (x - O)(x - 2h) (x - O)(x - h)


P2(X) = Jo (O _ h)(O _ 2h) + fr (h - O)(h - 2h) + 12 (2h - 0)(2h - h)'

Despus de algunas factorizaciones se obtiene:

1
P2(X) = 2h 2 (Uo - 2fr + 12)x2 + (-3Jo + 4fr - 12)hx + 2h 2Jo).

Por otro lado, por el teorema fundamental del clculo integral

X2
X3

y'(x)dx = Y(X3) - Y(X2)

Y(X3) = Y(X2) + X3

Xz
y'(x)dx

Y(X3) = Y(X2) + 3h

2h
J(x, y)dx.

362
15.8. MTODOS MULTlPASO EXPLCITOS

Si se reemplaza f(x, y) por el polinomio de interpolacin, se tiene:

Y(X3) ~ Y(X2) + (3h P2(x)dx


12h
Y(X3) ~ Y(X2) + l: 2~2h
((Jo - 2ft + h)x +
2

2
(-3fo + 4ft - 12)hx + 2h fo )dX

1 ( 19 h 3
Y3 = Y2 + 2h 2 (Jo - 2ft + 12)3 +

(-3fo + 4ft - 5h
12 ) 2 3+ 2h3)
fo
h
Y3 = Y2 + 12 (5fo - 16ft + 2312) (15.21)

La anterior igualdad se conoce con el nombre de frmula de Adams-


Bashforth de orden 2 (se utiliza un polinomio de orden 2). Tambin
recibe el nombre de mtodo multipaso explcito o mtodo multipaso
abierto de orden 2.
Si los valores Yo, Yl Y Y2 son exactos, o sea, si Yo = y(xo), Yl = Y(Xl)
y Y2 = Y(X2), entonces los valores h son exactos, o sea, f(Xi, Yi) =
f(Xi, Y(Xi)) y el error est dado por

h 3
Y(X3) = Y(X2) + 12 (5fo - 16h + 2312) + "B y (3) (z)h 4 , Z E [xo, X3]'
(15.22)

La frmula (15.21) se escribe en el caso general

h
Yi+l = Yi + 12 (5fi-2 - 16fi-l + 23fi). (15.23)

Para empezar a aplicar esta frmula se requiere conocer los valores fj


anteriores. Entonces es indispensable utilizar un mtodo RK el nmero
de veces necesario. El mtodo RK escogido debe ser de mejor calidad
que el mtodo de Adams-Bashforth que estamos utilizando. Para nuestro
caso podemos utilizar RK4.

Ejemplo 15.7. Resolver, por el mtodo de Adams-Bashforth de orden

363
15. ECUACIONES DIFERENCIALES

2, la ecuacin diferencial

y' = 2x 2 - 4x + Y
y(l) = 0.7182818

en el intervalo [1,3], con h = 0.25.

Al aplicar el mtodo RK4 dos veces se obtiene:

YI = 0.3653606
Y2 = -0.0182773.

Entonces

fo = f(xo, Yo) = -1.2817182


h = f(XI, YI) = -1.5096394
12 = -1.5182773
Y3 = Y2 + h(5fo - 16h + 2312)/12
= -0.3760843
13 = f(X3, Y3) = -1.2510843
Y4 = -0.6267238

Xi I Y(Xi) Y(Xi)
1.00 0.7182818 0.7182818
1.25 0.3653606 0.3653430
1.50 -0.0182773 -0.0183109
1.75 -0.3760843 -0.3703973
2.00 -0.6267238 -0.6109439
2.25 -0.6681548 -0.6372642
2.50 -0.3706632 -0.3175060
2.75 0.4320786 0.5176319
3.00 1.9534879 2.0855369

364
15.8. MTODOS MULTIPASO EXPLCITOS

-1 +-----~------------~----------~---
1 2 3
Figura 15.10 Mtodo de Adams-Bashforth 2.
En este caso hubo que evaluar 8 veces la funcin para los dos valores
de RK4 y en seguida 6 evaluaciones para un total de 14 evaluaciones de
la funcin f. <>

MULTIPASO EXPLCITO; ADAMS-BASHFORTH

error

o Yi+l = Yi + h/i ~y"(~)h2

h
1 Yi+l = Yi + 2"( -/i-l + 3fi) 152y"'(~)h3

h
2 Yi+l = Yi + 12 (5/i-2 - 16/i-l + 23/i) iy(4)(~)h4

h
3 Yi+1 = Yi + 24 (-9/i-3 + 37/i-2 - 59fi-l + 55/i) ~~~y(5)(~)h5

h
4 Yi+l = Yi + 720 (251/i-4 - 1274/i-3 + 2616fi-2 is5sy(6) (~)h6
-2774/i-l + 1901fi)

En la anterior tabla se muestran las principales frmulas. All n in-


dica el grado del polinomio de interpolacin usado. En algunos libros,

365
15. ECUACIONES DIFERENCIALES

n est asociado con nmero de puntos utilizados para la interpolacin


(igual al grado del polinomio ms uno). Obsrvese que la primera frmu-
la es simplemente el mtodo de Euler.

15.9 Mtodos multipaso implcitos


En estos mtodos se utiliza un polinomio de interpolacin, el mismo
de los mtodos explcitos, pero el intervalo de integracin vara.
Veamos un caso particular. Supongamos que se conocen los valores
Yo = y(xo), Yl = Y(Xl) y Y2 = Y(X2)' Por facilidad para la deduccin,
supongamos que Xo = h, Xl = h Y X2 = 2h.
Sea P2(X) el polinomio de grado menor o igual a 2 que interpola a
f en los valores 0, h Y 2h, es decir, el polinomio pasa por los puntos
(O, fo), (h, fd y (2h, 12), donde Ji = f(Xi, Yi). Como se vio en la seccin
anterior,

P2(X) = 2~2 ((Jo - 2ft + f2)x2 + (-3fo + 4ft - h)hx + 2h 2fo) .

El teorema fundamental del clculo integral se usa de la siguiente ma-


nera:

Xl
X2

y'(x)dx = Y(X2) ~ y(xd

Y(X2) = Y(Xl) + XI
X2

y'(x)dx
2h
Y(X2) = Y(Xl) + lh f(x, y)dx.

Si se reemplaza f(x, y) por el polinomio de interpolacin se tiene:

2h
Y(X2) ~ Y(Xl) + lh P2(x)dx

2h 1 (
Y(X2) ~ Y(Xl) + lh 2h 2 (Jo - 2ft + h)x 2+

(-3fo + 4ft - h)hx + 2h2fo)dX

366
15.9. MTODOS MULTIPASO IMPLCITOS

Y2 = Yl + 2h1 2 ( (JO - 2h + 12)37 h 3 +


(-3fo + 4h - 3h
12)2 3+ 2h3)
fo
h
Y2 = Yl + 12 (- fo + 8h + 512) (15.24)

La anterior igualdad se conoce con el nombre de frmula de Adams-


Moulton de orden 2 (se utiliza un polinomio de orden 2). Tambin
recibe el nombre de mtodo multipaso implcito o mtodo multipaso
cerrado de orden 2.
Si los valores Yo, Yl Y Y2 son exactos, o sea, si Yo = y(xo), Yl = y(xt)
y Y2 = Y(X2), entonces los valores fi son exactos, o sea, f(Xi, Yi) =
f(Xi, Y(Xi)) y el error est dado por
h 1
Y(X2) = Y(Xl) + 12 (- fo + 8h + 512) 24 y (3) (z)h 4 , Z E [XO,X2].
(15.25)
La frmula (15.24) se escribe en el caso general
h
Yi+l = Yi + 12 (- fi-l + 8fi + 5fi+l). (15.26)

Para empezar a aplicar esta frmula es indispensable conocer los valores


fj anteriores. Entonces se requiere utilizar un mtodo RK el nmero de
veces necesario. El mtodo RK escogido debe ser de mejor calidad que el
mtodo de Adams-Bashforth que estamos utilizando. Para nuestro caso
podemos utilizar RK4.
Una dificultad ms grande, y especfica de los mtodos implcitos,
est dada por el siguiente hecho: para calcular Yi+l se utiliza fi+l, pero
este valor es justamente f(Xi+l, Yi+l). Cmo salir de este crculo vi-
cioso? Inicialmente se calcula Y?+ll una primera aproximacin, por el
mtodo de Euler. Con este valor se puede calcular fP+ 1 = f (Xi+ 1, Y?+ 1)
Y en seguida Y[+1' De nuevo se calcula f l+ 1 = f (Xi+ 1, Y[+1) y en seguida
Y;+l' Este proceso iterativo acaba cuando dos valores consecutivos, Yf+l
y Y':tl, son muy parecidos. Este mtodo recibe tambin el nombre de
mtodo predictor-corrector. La frmula queda entonces as:

Y~:l = Yi + 1~ (- fi-l + 8fi + 5fl'+1)' (15.27)

367
15. ECUACIONES DIFERENCIALES

El criterio de parada puede ser:


k+l
IYi - yfl
max{l,ly:+1I} :::; E.

Ejemplo 15.8. Resolver, por el mtodo de Adams-Moulton de orden


2, la ecuacin diferencial

y' = 2x 2 - 4x +Y
y(l) = 0.7182818
en el intervalo [1,3]' con h = 0.25 Y E = 0.0001.
Al aplicar el mtodo RK4 una vez, se obtiene:

Yl = 0.3653606

Entonces

Jo = J(xo, Yo) = -1.2817182


JI = J(Xl,Yl) = -1.5096394

Aplicando Euler se obtiene una primera aproximacin de Y2:

y~ = -0.0120493
J~ = -1.5120493

Empiezan las iteraciones:

y~ = -0.0170487
Ji = -1.5170487
y~ = -0.0175694
Ji = -1.5175694
y~ = -0.0176237 = Y2

Para calcular Y2 se utilizan los valores:

JI = -1.5096394
12 = -1.5176237.

368
15.9. MTODOS MULTIPASO IMPLCITOS

Aplicando Euler se obtiene una primera aproximacin de Y3:

y~ = -0.3970296
j~ = -1.2720296

Empiezan las iteraciones:

Y5 = -0.3716132
jj = -1.2466132
y~ = -0.3689657
jj = -1.2439657
y~ = -0.3686899
j1 = -1.2436899
yj = -0.3686612 = Y3

1.00 0.7182818 0.7182818


1.25 0.3653606 0.3653430
1.50 -0.0176237 -0.0183109
1.75 -0.3686612 -0.3703973
2.00 -0.6076225 -0.6109439
2.25 -0.6315876 -0.6372642
2.50 -0.3084043 -0.3175060
2.75 0.5316463 0.5176319
3.00 2.1065205 2.0855369

369
15. ECUACIONES DIFERENCIALES

-1 +I------~------------~----------_,---
1 2 3
Figura 15.11 Mtodo de Adams-Moulton 2.

En este caso hubo que evaluar 4 veces la funcin para el valor de


RK4 y en seguida, en cada uno de los otros 7 intervalos, una evaluacin
fija ms las requeridas al iterar. En este ejemplo hubo, en promedio, 4
por intervalo, para un total de 32 evaluaciones de f. El valor final Ys es
ms exacto que el obtenido por Adams-Bashforth, pero a costa de ms
evaluaciones. <>

Tericamente, los dos mtodos multipaso de orden 2 tienen un error


local del mismo orden, O(h4 ), pero el coeficiente en el mtodo multi-
paso explcito, 3/8, es nueve veces el coeficiente en el error del mtodo
implcito, 1/24.

MULTIPASO IMPLCITO: ADAMS-MOULTON

r:l
-

h
error

-l2y"(~)h3 I
1 Yi+1 = Yi + 2(Ji + fi+l)
h
2 Yi+l = Yi + 12 (- fi-l + 81i + 5fi+l) -214y(3)(~)h4

h
3 Yi+l = Yi + 24 (Ji-2 - 5fi-l + 19fi + 9fi+) - /ioy(4) (Oh 5
h
4 Yi+l = Yi + 720 (-19fi-3 + 1061i-2 - 264fi-l -1oy(5)(~)h6

+646fi + 25 1fi+l)
-- ---
-
370
15.10. SISTEMAS DE ECUACIONES DIFERENCIALES

La tabla anterior contiene las principales frmulas. All n indica el


grado del polinomio de interpolacin usado. Obsrvese que el mtodo
de Heun corresponde a una iteracin (una sola) del mtodo multipaso
implcito de orden 1.

15.10 Sistemas de ecuaciones diferenciales


Un sistema de m ecuaciones diferenciales de primer orden se puede
escribir de la siguiente forma:

para Xo ::; x ::; b, con las condiciones iniciales

Yl(XO) = y~
Y2(XO) = y~

Utilicemos la siguiente notacin:

y = (Yl, Y2, ... , Ym)


yO = (y~, y~, ... , Y~J
f(x, y) = f(x, Yl, Y2, ... , Ym)
= (ft(x, Yl, ... , Ym), h(x, Yl, ... , Ym), ... , fm(x, Yl, ... , Ym)).
De esta manera, el sistema se puede escribir as:

y' = f(x, y), xo::; x ::; b


y(xo) = yO.

371
15. ECUACIONES DIFERENCIALES

La solucin numrica del sistema de ecuaciones consiste en un con-


t ode vect ores y 0
Jun y , ... , y n ,
, y1, 2

Yi = (Y1'
i i
Y2' i )
... , Ym ,

donde cada y; es una aproximacin:


y; ~ Yj(Xk).

Los mtodos vistos anteriormente se pueden generalizar de manera


inmediata. Si se trata de los mtodo RK, entonces los Ki dejan de ser
nmeros y pasan a ser vectores K i . Para y se utiliza un superndice para
indicar el intervalo, ya que los subndices se usan para las componentes
del vector. Por ejemplo, las frmulas de RK4 se convierten en:

K 1 = hf(Xi, yi)
K 2 = hf(Xi + h/2, yi + K 1/2)
K3 = hf(Xi + h/2, yi + K2/2) (15.28)
K4= hf(Xi + h, yi + K 3 )
yi+1 = yi + (K 1 + 2K 2 + 2K3 + K4)/6.
Ejemplo 15.9. Resolver el siguiente sistema de ecuaciones por RK4:

2Y1 3
Y1 = - x + X Y2, 1 <
f
- x <
- 2
f 3
Y2 = --Y2
x
Y1(1) = -1
Y2(1) = 1

con h = 0.2.
La solucin (exacta) de este sencillo sistema de ecuaciones es:

Y1(X) = -x
Y2(X) = x- 3 .

372
15.11. ECUACIONES DIFERENCIALES DE ORDEN SUPERIOR

Para la solucin numrica:

K 1 = (-0.2, -0.6)
K 2 = (-0.2136600, -0.3818182)
K 3 = (-0.1871036, -0.4413223)
K4 = (-0.2026222, -0.2793388)
yl = (-1.2006916, 0.5790634)

K1 = (-0.2001062, -0.2895317)
2
K = (-0.2093988, -0.2004450)
K 3 = (-0.1912561, -0.2210035)
K 4 = (-0.2011961, -0.1534542)
y2 = (-1.4011269, 0.3647495)

1.0 -1.0 1.0 -1.0 1.0


1.2 -1.2006916 0.5790634 -1.2 0.5787037
1.4 -1.4011269 0.3647495 -1.4 0.3644315
1.6 -1.6014497 0.2443822 -1.6 0.2441406
1.8 -1.8017156 0.1716477 -1.8 0.1714678
2.0 -2.0019491 0.1251354 -2.0 0.125

15.11 Ecuaciones diferenciales de orden


superior

Una ecuacin diferencial ordinaria, de orden m, con condiciones ini-


ciales, se puede escribir de la siguiente manera:

373
15. ECUACIONES DIFERENCIALES

y (m) -- f( X,y,y,y,
,,, ... ,y (m-l)) , Xo :S X :S b
y(XO) = Yo
y'(XO) = yb
Y"()
Xo = Yo "

(m-l)( ) _ (m-l)
Y Xo - YO .
Esta ecuacin diferencial se puede convertir en un sistema de ecuaciones
diferenciales de primer orden, mediante el siguiente cambio de variables:
Ul = Y
U2 = y'
U3 = Y"

U
m
= y(m-l)

Entonces la ecuacin diferencial se convierte en el siguiente sistema:


ul
,= U2
,
u2 = U3
,
u3 = U4

,
um-l = Um
u~ = f(x, Ul, U2, ... , u m )
Ul(XO) = Yo
U2(XO) = yb
U3(XO) = y~

(m-l)
Um (Xo) = Yo .
De forma ms compacta,
u' = F(x, u), xo:S x :S b
u(xo) = /'i,O,

374
15.11. ECUACIONES DIFERENCIALES DE ORDEN SUPERIOR

donde /\'0 = [Yo Y yg ... y~m-l)lT. Este sistema se puede resolver por
los mtodos para sistemas de ecuaciones diferenciales de primer orden.

Ejemplo 15.10. Resolver la ecuacin diferencial

" 4y - xy/
=
Y
x
2 ' 1::; x ::; 2,

y(l) = 3
y'(l) = 10,

por el mtodo RK4, con h = 0.2.


Sean Ul = y, U2 = y/.

/
Ul = U2
/ 4Ul - XU2
u2 = 2 ,1 ::; x ::; 2,
x
ul(1)=3
u2(1) = 10.

La solucin exacta es y = 4x 2 -x- 2 . Al aplicar el mtodo 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)

1.0 3.0 10.0 3.0


1.2 5.0652642 10.757147 5.0655556
1.4 7.3293797 11.928367 7.3297959 <>
1.6 9.8488422 13.287616 9.849375
1.8 12.65069 14.742141 12.651358
2.0 15.749173 16.249097 15.75

375
15. ECUACIONES DIFERENCIALES

15.12 Ecuaciones diferenciales con condiciones


de frontera

Una ecuacin diferencial de segundo orden con condiciones de fron-


tera se puede escribir de la forma

y" = (x, y, y'), a:S x :S b,


y(a) = Ya (15.29)
y(b) = Yb.

Esta ecuacin diferencial se puede convertir en un sistema de dos ecua-


ciones diferenciales, pero para obtener su solucin numrica se presenta
un inconveniente: se debera conocer el valor y~ = y' (a). Esta dificultad
se supera mediante el mtodo del disparo (shooting).
Como no se conoce y~, se le asigna un valor aproximado inicial. Puede
ser
y' r'oJ Yb - Ya
a r'oJ b_ a .
Con este valor inicial se busca la solucin numrica, hasta obtener

y(b) = Y(b,y~).

Este valor debera ser el valor conocido Yb. Si no coinciden, es necesa-


rio modificar la suposicin de y~ hasta obtener el resultado deseado. Si
y(b, y~) < Yb, entonces se debe aumentar la pendiente inicial del dispa-
ro. De manera anloga, si y(b, y~) > Yb, se debe disminuir la pendiente
inicial del disparo. Lo anterior se puede presentar como la solucin de
una ecuacin:
'P(y~) = Yb - y(b, y~) = O.
Esta ecuacin se puede resolver, entre otros mtodos, por el de la secante
o el de biseccin.

376
15.12. ECUACIONES DIFERENCIALES CON CONDICIONES DE FRONTERA

Para facilitar la presentacin del mtodo se considera el problema


P(v), donde:

v = aproximacin de y~,
n = nmero de intervalos para la solucin numrica,
y = (Yo, YI, ... , Yn) = solucin numrica del siguiente problema:

y' = j (x, y), a:S x :S b


y(a) = Ya P(v)
y'(a) = v,

<p(v) = Yb - Yn = Yb - y(b, v). (15.30)

Se desea encontrar v* tal que <p(v*) = O. Entonces la solucin numrica


de P(v*) es la solucin numrica de (15.29). Si se aplica el mtodo de la
secante para resolver la ecuacin <p( v) = O, el algoritmo es el siguiente:

MTODO DEL DISPARO


datos: j, a, b, Ya, Yb, e, maxit, eo
er = max{l, IYbl} e
Vo = (Yb - Ya)/(b - a)
y = solucin numrica de P(vo)
<Po = Yb - Yn
si l<pol :S er ent parar
VI = Vo + <po/(b - a)
y = solucin numrica de P(VI)
<PI = Yb - Yn
si I<PII :S er ent parar
para k = 1, ... ,maxit
8 = <PI - <Po
si 181 :S eo ent parar
V2 = VI - <PI(VI - vo)/8
y = solucin numrica de P(V2)
<P2 = Yb - Yn
si I<P21 :S er ent parar
Vo = VI, VI = V2, <Po = <PI, <PI = <P2
fin-para
OJO: no hubo convergencia.

377
15. ECUACIONES DIFERENCIALES

Ejemplo 15.11. Resolver la ecuacin diferencial

2cos(2x) - y' - 4x2y O


11 _
y -
x
<) , . 2 :S x:s 07.
y(0.2) = 0.3894183
y(0.7) = 0.9854497,

con h = 0.1 Y utilizando RK4 para la solucin del sistema de ecuaciones


diferenciales asociado.
La primera aproximacin de y' (a) es

Vo = (0.9854497 - 0.3894183)/(0.7 - 0.2) = 1.19206278

Al resolver numricamente el problema P(1.19206278) se obtiene:

Y5 = 0.94935663.

El disparo result muy bajo.

'Po = 0.03609310
VI = 1.19206278 + 0.03609310/(0.7 - 0.5) = 1.26424897

Al resolver numricamente el problema P(1.26424897) se obtiene:

Y5 = 0.95337713
'PI = 0.03207260

Primera iteracin del mtodo de la secante:

V2 = 1.84009748

Al resolver numricamente el problema P(1.84009748) se obtiene:

Y5 = 0.98544973

Este disparo fue preciso (no siempre se obtiene la solucin con una sola
iteracin de la secante). El ltimo vector y es la solucin. La solucin
exacta es y = sen(2x).

378
15.13. ECUACIONES LINEALES CON CONDICIONES DE FRONTERA

I Xi I
0.2 0.3894183 0.3894183
0.3 0.5647741 0.5646425
0.4 0.7174439 0.7173561
0.5 0.8415217 0.8414710
0.6 0.9320614 0.9320391
0.7 0.9854497 0.9854497

15.13 Ecuaciones diferenciales lineales con


condiciones de frontera
U na ecuacin 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:S X :S b,


y(a) = Ya (15.31)
y(b) = Yb.

Obviamente esta ecuacin se puede resolver por el mtodo del dispa-


ro, pero, dada la linealidad, se puede resolver usando aproximaciones
numricas (diferencias finitas) para y' y y".
El intervalo [a, b] se divide en n 2 2 sub intervalos de tamao h =
(b - a)/n. Los puntos Xi estn igualmente espaciados (Xi = a + ih). Se
utilizan las siguientes aproximaciones y la siguiente notacin:

" Yi-l - 2Yi + Yi+1


Yi ~ h2
, -Yi-l + Yi+l
Yi ~ 2h
Pi := p(Xi)
qi := q(Xi)
ri := r(Xi)
Si := s(xd

Entonces:

i = 1, ... , n-1.

379
15. ECUACIONES DIFERENCIALES

Es decir, se tiene un sistema de n - 1 ecuaciones con n - 1 incgnitas,


Y1, Y2, ... , Yn-1

2
2 Yi-1 - 2y~ + Yi+1 h -Yi-1 + Yi+1 2h2riYi 2h Si
Pi 2h2 + q~ + 2h2 2h2 2h2
2
(2Pi - hqi)Yi-1 + (-4Pi + 2h2ri)Yi + (2pi + hqi)Yi+1 = 2h s i

Este sistema es tridiagonal.

d1 U1 Y1 {31
h d2 U2 Y2 {32
l2 d 3 U3 Y3 {33
, (15.32)

ln-3 d n - 2 Un-2 Yn-2 {3n-2


ln-2 dn-1 Yn-1 n-1

donde

di = -4Pi + 2h2ri, i = 1, ... ,n -1,


Ui = 2Pi + hqi, i = 1, ... ,n - 2,
li = 2Pi+1 - hqi+1, i = 1, ... ,n - 2,
{31 = 2h2Sl - (2P1 - hq1)Ya,
{3i = 2h 2 si , i = 2, ... ,n - 2,
2
{3n-1 = 2h Sn-1 - (2Pn-1 + hqn-1)Yb.

Ejemplo 15.12. Resolver por diferencias finitas la ecuacin diferencial

x2y" + y' + 4x2y = 2cos(2x), 0.2 ~ x ~ 0.7


y(0.2) = 0.3894183
y(0.7) = 0.9854497,

con n = 5, es decir, h = 0.1.

380
15.13. ECUACIONES LINEALES CON CONDICIONES DE FRONTERA

Al calcular los coeficientes del sistema tridiagonal se obtiene:

d = -4p + 2h2r
d = -4(0.3)2 + 2(0.1)24(0.3)2 = -0.3528
u = 2p + hq
u = 2(0.3)2 + 0.1(1) = 0.28
l = 2P2 - hq2
l = 2(0.4)2 - 0.1(1) = 0.22
d = (-0.3528, -0.6272, -0.98, -1.4112),
u = (0.28, 0.42, 0.6),
l = (0.22, 0.4, 0.62),
f3 = (0.00186, 0.0278683, 0.0216121, -0.7935745).

Su solucin es

(y, Y2, Y3, Y4) = (0.5628333, 0.7158127, 0.8404825, 0.9315998).

I Xi I
0.2 0.3894183 0.3894183
0.3 0.5628333 0.5646425
0.4 0.7158127 0.7173561 <>
0.5 0.8404825 0.8414710
0.6 0.9315998 0.9320391
0.7 0.9854497 0.9854497

Ejercicios

Escoja varias ecuaciones diferenciales (o sistemas de ecuaciones di-


ferenciales) de las que conozca la solucin exacta. Fije el intervalo
de trabajo. Determine qu mtodos puede utilizar. Aplique va-
rios de ellos. Compare los resultados. Cambie el tamao del paso.
Compare de nuevo.
Un procedimiento adecuado para obtener las ecuaciones diferen-
ciales consiste en partir de la solucin (una funcin cualquiera) y
construir la ecuacin diferencial.

381
15. ECUACIONES DIFERENCIALES

La aplicacin de los mtodos se puede hacer de varias maneras: a


mano con ayuda de una calculadora; parte a mano y parte con ayu-
da de software para matemticas como Scilab o Matlab; haciendo
un programa, no necesariamente muy sofisticado, para cada mto-
do.
A continuacin se presentan algunos ejemplos sencillos.
15.1
y' = eX _ J!..
x
y(l) = o.
eX
Su solucin es y = eX - - .
x
15.2

y~ = 2Yl + Y2 + 3
y~ = 4Yl - Y2 + 9
Yl(O) = -3
Y2(0) = 5.
Su solucin es Yl(t) = _e- 2t - 2, Y2(t) = 4e- 2t + 1.
15.3

y" = 2 ,
x(2 -x) Y
y(l) = -2
y'(l) = 1.

Su solucin es y = -21n(2 - x) - x-lo Tenga especial cuidado


con el intervalo de trabajo.
15.4
y'" + y" + y' + y = 4e x
y(O) = 1
y'(O) = 2
y" (O) = 1
y'" (O) = O.
Su solucin es y = eX + sen(x).

382
l5.l3. ECUACIONES LINEALES CON CONDICIONES DE FRONTERA

15.5

y"y = e2x - sen 2 (x)


y(O) = 1
Y(7r) = e 7r

Su solucin es y = eX + sen(x).
15.6

y" + e-Xy' + y = 2e x + 1 + e-x cos(x)


y(O) = 1
Y(7r) = e 7r

Su solucin es y = eX + sen(x).

383
l5.l3. ECUACIONES LINEALES CON CONDICIONES DE FRONTERA

15.5

y"y = e2x - sen 2 (x)


y(O) = 1
Y(7r) = e 7r

Su solucin es y = eX + sen(x).
15.6

y" + e-Xy' + y = 2e x + 1 + e-x cos(x)


y(O) = 1
Y(7r) = e 7r

Su solucin es y = eX + sen(x).

383
Bibliografa

[AbS74] Abramowitz Milton. y Stegun Irene A. (eds.), Handbook of Mat-


hematical 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


e++, Addison-Wesley, Reading, 1994.
[Ber01] Berryhill John R., e++ Scientific Programming, Wiley, Nueva
York, 2001.

[BraOO] Braquelaire Jean-Pierre, Mthodologie de la programmation en


e, Dunod, Pars, 2000.
[BroOO] Bronson Gary J., e++ para ingeniera y ciencias, Int. Thom-
son, Mxico, 2000.

[BuF85] Burden Richard L. y Faires J. Douglas, Numerical Analysis,


3a. ed., Prindle-Weber-Schmidt, Boston, 1985.

[Buz93] Buzzi-Ferraris Guido, Scientific e++, Building Numerical Li-


braries the Object-Oriented Way, Addison-Wesley, Wokingham,
Inglaterra, 1993.

[ChC99] Chapra Steven C. y Canale Raymond P., Mtodos Numricos


para Ingenieros, 3 ed., McGraw-Hill, Mxico, 1999.

[Cap94] Capper Derek M., Introducing e++ for Scientists, Engineers


and Mathematicians, Springer-Verlag, Londres, 1994.

385
BIBLIOGRAFA

[DaB74] Dahlquist Germund y Bjork Ake, Numerical Methods, Prentice


Hall, Englewood Cliffs, 1974.

[DeD99] Deitel H.M. y Deitel P.J., e++, cmo programar, Prentice Hall
Hispanoamericana, Mxico, 1999.

[ElS90] Ellis Margaret A. y Stroustrup Bj arne , The Annotated e++


Reference Manual, Addison-Wesley, Reading, 1990.
[EnU96] Engeln-MuellgeS Giesela y Uhlig Frank, Numerical Algorithms
with e , Springer, Nueva York, 1996.

[Flo95] Flowers B.H., An Introduction to Numerical Methods in e++,


Clarendon Press, Oxford, 1995.

[Fro70] Froberg Karl-Erik, An Introduction to Numerical Analysis, 2a.


ed. Addison-Wesley, Reading, 1970.

[Gla93] Glasey Robert, Numerical eomputation Using e, Acedemic


Press, Boston, 1993.

[GoV96] Golub Gene H. y Van Loan Charles H., Matrix eomputations,


3rd ed., Johns Hopkins University Press, Baltimore, 1996.

[IsK66] Isaacson Eugene y Keller Herbert B., Analysis of Numerical


Methods, Wiley, Nueva York, 1966, Dover, Nueva York, 1994.
[Kem87] Kempf James, Numerical Software Tools in e, Prentice Hall,
Englewood Cliffs, 1987.

[LaT87] Lascaux P. y Theodor R., Analyse numrique matricielle ap-


plique a l'art de l'ingnieur, Tomos 1 y 2, Masson, Pars, 1987.

[LIH01] Liberty Jesse y Horvath David B., Aprendiendo e++ para Li-
nux en 21 das, Prentice Hall, Pearson, Mxico, 2001.

[MorOl] Mora Hctor, Optimizacin no lineal y dinmica, Departamento


de Matemticas, Universidad Nacional, Bogot, 1997.

[Nak93] Nakamura Shoichiro, Applied Numerical Methods in e, PTR


Prentice Hall, Englewood Cliffs, 1993.

[NoD88] Noble Ben y Daniel James W., Applied Linear Algebra 3rd ed.,
Prentice Hall, Englewood Cliffs, 1988.

386
BIBLIOGRAFA

[OrG98] Ortega James M. y Grimshaw Andrew S., An Introduction to


C++ and Numerical Methods, Oxford University Press, Oxford,
1998.

[Pre93] Press Wiliam H. et al., Numerical Recipes in C, The Art of


Scientific Computing, 2 ed., Cambridge University Press, Cam-
bridge, 1993.

[Pre02] Press Wiliam H. et al., Numerical Recipes in C++, The Art


of Scientific Computing, 2 ed., Cambridge University Press, Cam-
bridge, 2002.

[ReD90] Reverchon Alain y Ducamp Marc, Analyse numrique en C,


Armand Colin, Pars, 1990.

[ReD93] Reverchon Alain y Ducamp Marc, M athematical Software Tools


in C++, Wiley, Chichester, 1993.

[Sch91] Schatzman Michelle, Analyse numrique, Cours et exercises


pour la licence, InterEditions, Pars, 1991.

[Sch92] Schildt Herbert, Turbo CjC++, Manual de referencia, McGraw-


Hill, Madrid, 1993.

[StB93] Stoer J. y Bulirsch R., Introductian ta Numerical Analysis, 2a.


ed., Springer-Verlag, Nueva York, 1993.

[Str02] Stroustrup Bjarne, El lenguaje de programacin C++, ed. espe-


cial, Addison Wesley, Madrid, 2002.

[Str86] Strang Gilbert, lgebra lineal y sus aplicaciones, Addison-


Wesley Iberoamericana, Wilmington, 1986.

[YanOl] Yang Daoqi, C++ and Object-Oriented Numeric Computing far


Scientists and Engineers, Springer, Nueva York, 2001.

[YoG72] Young David M. y Gregory Rober T., A Survey of Numerical


Mathematics, vols. I y 11, Addison-Wesley, Reading, 1974.

387
BIBLIOGRAFA

[OrG98] Ortega James M. y Grimshaw Andrew S., An Introduction to


C++ and Numerical Methods, Oxford University Press, Oxford,
1998.

[Pre93] Press Wiliam H. et al., Numerical Recipes in C, The Art of


Scientific Computing, 2 ed., Cambridge University Press, Cam-
bridge, 1993.

[Pre02] Press Wiliam H. et al., Numerical Recipes in C++, The Art


of Scientific Computing, 2 ed., Cambridge University Press, Cam-
bridge, 2002.

[ReD90] Reverchon Alain y Ducamp Marc, Analyse numrique en C,


Armand Colin, Pars, 1990.

[ReD93] Reverchon Alain y Ducamp Marc, M athematical Software Tools


in C++, Wiley, Chichester, 1993.

[Sch91] Schatzman Michelle, Analyse numrique, Cours et exercises


pour la licence, InterEditions, Pars, 1991.

[Sch92] Schildt Herbert, Turbo CjC++, Manual de referencia, McGraw-


Hill, Madrid, 1993.

[StB93] Stoer J. y Bulirsch R., Introductian ta Numerical Analysis, 2a.


ed., Springer-Verlag, Nueva York, 1993.

[Str02] Stroustrup Bjarne, El lenguaje de programacin C++, ed. espe-


cial, Addison Wesley, Madrid, 2002.

[Str86] Strang Gilbert, lgebra lineal y sus aplicaciones, Addison-


Wesley Iberoamericana, Wilmington, 1986.

[YanOl] Yang Daoqi, C++ and Object-Oriented Numeric Computing far


Scientists and Engineers, Springer, Nueva York, 2001.

[YoG72] Young David M. y Gregory Rober T., A Survey of Numerical


Mathematics, vols. I y 11, Addison-Wesley, Reading, 1974.

387
Apndice A

Estilo en e
Para que la lectura de un programa en e sea ms fcil 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 ms claros y dicientes que
otros. Algunos son ventajosos en ciertos aspectos y desventajosos en
otros. Otros son diferentes pero comparables. Algunas "reglas" son ms
universales y populares que otras.

Las siguientes normas sirven de modelo o referencia y fueron utiliza-


das en la elaboracin de los ejemplos en e de este libro.

A.l Generalidades
El corchete { de inicio del cuerpo de una funcin debe ir en la
primera columna y no debe haber nada ms en la lnea.
El corchete } de finalizacin de una funcin debe ir en la primera
columna y no debe haber nada ms en la lnea. Si se desea escri-
bir un comentario, ste se puede colocar en la lnea anterior. Por
ejemplo:

double factorialC ... )


{

389
APNDICE A. ESTILO EN C

II fin de factorial
}

El corchete de inicio de un bloque dentro de una estructura de


control debe ir en la misma lnea de la condicin.

En la lnea de corchete correspondiente al final de un bloque en una


estructura de control no debe haber nada ms, salvo un comentario
indicando qu tipo de estructura finaliza o cul variable de control
se us, cuando la estructura de control tiene muchas lneas. Por
ejemplo:

fore i ... ){

whileC ... ){

for( j ... ){

} II fin while

} II fin i

No escribir ms all de la columna 72 (excepcionalmente, hasta la


80).

Las estructuras de control anidadas dentro de otras deben incre-


mentar la sangra. Cada vez que hay incremento en la sangra, sta
debe estar dada siempre por un nmero 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.l. GENERALIDADES

Las declaraciones de variables van al principio de las funciones l .

Antes de estas declaraciones puede haber solamente comentarios.

Dejar una interlnea despus de las declaraciones de variables.

Utilizar una lnea para cada una de las variables importantes, co-
locando un comentario explicativo. Por ejemplo,

double *factPrim;11 apuntador para los factores primos


int maxFactPrim; II numero maximo de factores primos
int nFactPrim; II numero de factores primos

Las variables menos importantes pueden ser declaradas en una sola


lnea, por ejemplo:

int i, j, k;
double templ, temp2;

Separar de manera clara las funciones entre s, por ejemplo con


una lnea como

11----------------------------------------------------
Dejar un espacio despus de cada coma, por ejemplo,

int i, j, k;

x = maximo(a, b, c, d);

En las asignaciones, dejar un espacio antes y despus del signo = ,


pero la abreviacin += ( Y las anlogas) debe permanecer pegada.
Por ejemplo:

a = b+3;
d += a;

lLibros importantsimos de C++ como [Str02] (libro obligado de referencia), acon-


sejan justamente lo contrario, es decir, sugieren declarar las variables en el momento
que se van a necesitar, por ejemplo, for( int i = O; i <n; i++) ...

391
APNDICE A. ESTILO EN C

Los nombres de las variables, deben ser indicativos de su significa-


do. Cuando hay varias palabras, stas se separan con el signo _
o por medio de una mayscula al empezar la nueva palabra. Por
ejemplo, para el peso especfico:

pe no es muy diciente
peso_esp puede ser
pesoEsp puede ser

Colocar comentarios adecuados para cada funcin. Deben indicar


la accin de la funcin y el significado de cada parmetro.

void prodComplC double a, double b, double x,


double y, double &u, double &v)
{
II producto de dos complejos
II u + iv = Ca + ib)Cx + iy)

El orden para el programa puede ser:


comentarios iniciales
include ...
prototipos
define
typedef
variables globales
main
definiciones de las funciones

392
A.2. EJEMPLO

A.2 Ejemplo

II Este programa calcula ....


II

#include < ... >


#include < ... >

#define N 20
#define

void funcionl( ..... );


double funcion2( ... );

int nMax = 10; II indica


double abc; II es el ....

11================================================
int main(void)
{
int i, j, k;
double x, y;

fore. .. ){

fore. .. ){

if e. .. ){

}
else{

393
APNDICE A. ESTILO EN C

if( ... H

}
}
}
}

11================================================
void funcionl( ... )
{
II comentarios
II mas comentarios

int m, n;
float u; II indica ...

11------------------------------------------------
double funcion2( ...
{
II comentarios
II mas comentarios

int i, j;
double x; II x indica .. .
double zz; II indica .. .

394
A.3. ESTRUCTURAS DE CONTROL

A.3 Estructuras de control


if ( ) {

}
el se {

i f ( ... ) ...
else ... ;

if( ... ) ...


el se {

if ( ){

}
else ...

if ( ){

395
APNDICE A. ESTILO EN C

for( ... ) {

for( ... ) ... ,

while( ... ) {

while( ... ) ...

do {

} while ( ... );

switch( i ) {
case 1:

break;
case 4:

396
A.3. ESTRUCTURAS DE CONTROL

break;
case 8: case 9:

break;
default:

397
,
Indice analtico

11,45 %e, 31
&, 31, 78, 79, 109 %f,31
&&, 45 %i, 31
'\0',98 %lf,31
(double), 36 %p, 31, 110
(float), 36 %s, 31, 99
(int),36 %u, 31
*, 22, 78, 109 \n, 7
**, 116 a, 145
*=, 27 abreviaciones, 26
+, 22
acos, 29
++, 22, 23
Adams-Bashforth
+=, 27 frmula de, 363
-, 22, 23 Adams-Moulton
--, 22, 24 frmula de, 367
-=, 27 adicin, 22
/,22 algoritmo
/=, 27 de Euclides, 54
<,45 alloc.h,85
, 8 mbito
<=, 45 global, 82
=, 21 local, 82
==, 45 ANSI e, 70
>, 45 aproximacin, 285
>=, 45 aproximacin por mnimos cua-
, 33 drados, 306
?, 171, 173 apuntador, 78
%, 22, 23 apuntadores, 109
%c, 31 a apuntadores, 116
%d, 31 a estructuras, 177, 180

398
NDICE ANALTICO

a funciones, 165 bloque, 43


dobles, 116 bloque de sentencias, 43
dobles y matrices, 135 Borland,70
y arreglos bidimensionales, 116 break, 17, 58
y arreglos unidimensionales, bucle, 48
111 burbuja, mtodo, 194
archivo
de texto, 145 %c, 31
texto, 145 cadena de formato, 31
argc, 172, 173 cadenas, 98
argumento, 68 cambio de signo, 23
argumentos de main, 171 caracteres, 19
argv, 172, 173 case, 17, 57
arreglos, 87 catch,17
a partir de 1, 139 ceil, 29
aleatorios, 129 char, 17, 19, 20, 31, 158
bidimensionales, 87, 94 cin, 33
Y apuntadores, 116 class, 17
como parmetros, 94, 97 cdigo, 5
como parmetros, 88 comentario, 15
de estructuras, 177, 180 compilador, 5
multidimensionales, 94 complejo, 175
unidimensionales, 87 complejos, 176
y apuntadores, 111 complex.h,85
y matrices, 117 condiciones de frontera
ecuaciones diferenciales con,
ASCII, 5
asignacin dinmica de memo- 376
ecuaciones diferenciales linea-
ria, 131
para estructuras, 177, 180 les con, 379
asin, 29 conio.h,70
const, 17, 159
asm, 17
asociatividad, 25 continue, 17,60
de derecha a izquierda, 25 control del paso, 353
de izquierda a derecha, 25 convergencia
cuadrtica, 262
atan, 29
lineal, 262
auto, 17
conversiones de tipo en expresio-
base, 287, 307 nes mixtas, 35
biblioteca estndar, 85 cos, 29

399
NDICE ANALTICO

coseno, 53 %e, 31
cosh, 29 ecuacin cuadrtica, 43
cout, 8, 33 ecuaciones
ctype.h,85 diferenciales ordinarias, 337
cuadratura ecuaciones diferenciales
de Gauss, 326 con condiciones de frontera,
de Gauss-Legendre, vase cua- 376
dratura de Gauss de orden superior, 373
cuerpo de una funcin, 69 lineales con condiciones de
frontera, 379
%d, 31 sistemas de, 371
decremento, 24 ecuaciones normales, 247
default, 17 else, 17, 41
#define, 164 encadenamiento, 6
delete, 17, 132 endl, 8
densidad, 254 enlace, 6
derivacin entrada de datos, 30
numrica, 332 enum, 17
derivadas parciales, 246 EOF, 34, 148
desviacin estndar, 148 errno.h,85
determinante, 229 error, 331
diagonal estrictamente dominan- de compilacin, 5
te por filas, 242 de ejecucin, 6
diferencias global, 317, 318, 320, 323,
divididas de Newton, 293 339
finitas, 302 orden del, 359
diferencias finitas, 379 local, 317, 320, 339
diferente, 45 mtodo de Euler, 360
distancia entre dos vectores, 183 mtodo de Heun, 360
divisin, 22 mtodo del punto medio,
entre enteros, 23 360
sinttica, 134 mtodo RK4, 360
do, 17 mtodo RK5, 360
do while, 54, 58, 60 mtodo RK6, 360
doble precisin, 19 orden del, 359
double, 17, 19, 20, 31, 35, 158 mtodo de Euler, 339
double( ),37 orden del, 359
(double), 36 escritura

400
NDICE ANALTICO

de un vector, 89, 91, 117, 120 formato, 31


en un archivo, 150-152 frmula
de una matriz, 94, 97, 117, de Adams-Bashforth, 363
120 de Simpson, 319
en un archivo, 152, 154 deAdams-Moulton, 367
en archivos, 143 del trapecio, 314
esquema de Horner, 134 formulas
estructura de Newton-Cotes, 314, 325
devuelta por una funcin, 177, frmulas
180 de Newton-Cotes, 319
estructuras, 175 abiertas, 325
como parmetros, 177, 180 cerradas, 325
estructuras de control, 41 Fortran, 1
Euler fprintf, 143, 144
mtodo de, 338, 348 free, 131, 132
orden del mtodo de, 360 friend, 17
exit, 61 fscanf, 143, 144
exp, 29 funcin
extern, 17, 173 exponencial, 51
funciones, 67
%f,31 elementales, 183
fabs, 29 en lnea, 169
factores primos de un entero, 92, matemticas, 27
94 recurrentes, 75
factorial, 50, 67, 75 funciones de la base, 287, 307
factorizacin
de Cholesky, 229, 235, 237 Gauss, vase mtodo de Gauss
LU,215 Gauss-Seidel, vase mtodo de
PA=LU, 223 Gauss-Seidel
fclose, 143, 144 getch, 70
feof, 143 getchar, 71
feof, 148-150 gets, 147, 148
FILE, 144, 145 goto, 17, 61
float, 17, 19, 20, 31, 35, 158
(float), 36 Heun
float.h,85 mtodo de, 341, 348
floor, 29 orden del mtodo de, 360
fopen, 143-145
for, 17,48,58,60 %i,31

401
NDICE ANALTICO

identificador, 16 Matlab, 200


if,17,41 matrices
igual, 45 ortogonales, 250
#inelude, 7, 161 y apuntadores dobles, 135
incremento, 23 y arreglos unidimensionales,
inicializacin de arreglos, 103 117
inline, 17, 170 matriz
int, 17, 19, 20, 31, 35, 158 banda, 253
int ( ), 37 de diagonal estrictamente do-
(int),36 minante por filas, 242
integracin numrica, 313 de Givens, 250
intercambio, 78 de Householder, 250
de vectores, 183 definida positiva, 227, 229,
interpolacin, 285-287 243
de Lagrange, 289 dispersa, 254
por diferencias divididas, 298 jacobiana, 280
por diferencias finitas, 304 positivamente definida, vase
iostream.h, 8, 85 matriz definida positiva
mximo comn divisor, 54
Lagrange, vase interpolacin de
mximo de un vector, 183
Lagrange
mayor, 45
lectura
mayor o igual, 45
de un vector, 89, 91
menor, 45
en un archivo, 150-152
menor o igual, 45
de una matriz, 94, 97, 117,
mtodo
120
en un archivo, 152, 154 burbuja, 194
en archivos, 143 de Cholesky, 227, 237-239
%lf,31 de colocacin, 286
limi ts. h, 85 de Euler, 338, 348
log, 29 de Gauss, 206
log10, 29 de Gauss con pivoteo par-
long, 17,20 cial, 217, 222, 223
long double, 21, 35, 158 de Gauss-Seidel, 239
long int, 21, 35, 158 de Heun, 341, 348
de la biseccin, 71, 79, 267
main, 7, 171 de la secante, 263
malloe, 131, 132 de Newton, 257, 278
math.h, 27, 85 de Newton en ]Rn, 279, 280

402
NDICE ANALTICO

de punto fijo, 272, 278 \n, 7


de Regula Falsi, 268 new, 17, 132
de Regula Falsi modificado, no, 45
270 norma
de Runge-Kutta (RK), 347 de un complejo, 177, 180
de Runge-Kutta-Fehlberg, 354, notacin de Matlab, 200
356 notacin de Scilab, 200
del disparo (shooting), 376, NULL, 131, 132, 145
377 nmero
del punto medio, 344, 348 complejo, 175
del trapecio, 341 de cifras decimales, 32
multipaso abierto, 363 de columnas, 32
multipaso cerrado, 367 de operaciones, 203, 211, 235
multipaso explcito, 363 nmeros
multipaso implcito, 367 enteros, 19
reales, 19
orden del, 359
predictor-corrector, 367 0,45
RK,347 operaciones elementales con vec-
RK2, 351 tores, 183
deduccin del, 350 operador
RK4, 348 de asignacin, 21
RK5,354 unario, 23
RK6, 354 operadores
RKF,354 lgicos, 45
mtodos relacionales, 45
de Runge-Kutta, 347 operadores aritmticos, 22
indirectos, 239 operator,17
iterativos, 239 orden
multipaso explcitos, 362 del error, 359
multipaso implcitos, 366 verificacin numrica, 360
RK,347 del error global, 359
mnimos cuadrados, vase solu- del error local, 359
cin por ... del mtodo, 359
modificadores, 20 de Euler, 360
modificadores de formato, 32 de Heun, 360
molde funcional, 37 del punto medio, 360
moldes, 36 RK4, 360
multiplicacin, 22 RK5, 360

403
NDICE ANALTICO

RK6,360 prototipo, 68
orden de convergencia, 262, 264 public, 17
ordenamiento, 194 punteros, vase apuntadores
overflow, 75 punto flotante, 19
punto medio
%p, 31, 110 mtodo del, 344, 348
palabra clave, 16 orden del mtodo de, 360
parmetro, 68
por defecto, 81 r,145
por referencia, 76-78, 88 r+, 145
por valor, 76, 77 RAND_MAX, 130
pausa, 70 randO, 130
pivote, 217 Raphson, vase mtodo de Newton-
pivoteo Raphson
parcial, 217 register,17
total, 218 residuo entero, 23
polinomios return,17
de Legendre, 331 RK, vase mtodo de Runge-Kutta
polinomios de Lagrange, 290 RK4, vase mtodo RK4
pow, 29 RKF, vase Runge-Kutta-Fehlberg
precedencia de los operadores Runge-Kutta
aritmticos, 24 mtodo de, 347
precisin Runge-K u tta-Fehlberg
doble, 19 mtodo de, 354, 356
sencilla, 19
printf, 7 %s, 31, 99
prioridad de los operadores arit- salida de resultados, 30
mticos, 24 scanf, 30, 34
private,17 Scilab, 200
producto Seidel, vase mtodo de Gauss-
de complejos, 177, 180 Seidel
de matrices, 94, 97, 117, 120- serie de Taylor, 51, 53
123, 125, 128, 129 seudosolucin, 248
escalar, 126, 128, 183 short, 17
programa short int, 35, 158
ejecutable, 6 signed, 17
fuente, 5 sin, 29
promedio, 89, 91, 113, 115, 148 sinh, 29
protected,17 sistema

404
NDICE ANALTICO

diagonal, 202 throw,17


triangular inferior, 206 time.h,85
triangular superior, 202 tipos de datos, 19
sistemas triangularizacin, 206, 209, 211
de ecuaciones diferenciales , try, 17
371 typedef, 17, 159
sizeof, 17, 132, 157, 158
sobrecarga de funciones, 83 %u, 31
solucin union, 17
de ecuaciones, 255 unsigned, 17, 20
de sistemas lineales, 199 unsigned int, 21
de un sistema
valor
diagonal, 202
devuelto, 69
triangular inferior, 206
dominante, 70
triangular superior, 202
propio, 228
por mnimos cuadrados, 245
variables
sparse, 254
globales, 82
sqrt, 27, 29
locales, 82
static, 17, 173
vectores
stddef.h,85
almacenados con salto, 184,
stdio.h,7
190
stdio .h, 85
virtual, 17
stdlib. h, 85, 130
void, 7, 17
strcat, 101, 102
vOlatile, 17
strcpy, 101
string . h, 85, 101 w,145
strlen, 101 while, 17, 51, 58, 60
struct, 17, 175
sustraccin, 22 y,45
switch, 17, 57

tabla
de diferencias divididas, 296
de diferencias finitas, 302
tan, 29
tanh, 29
tasa de convergencia, 262
template, 17
this, 17

405
Introduccin a e
y a mtodos numricos
SE TERMIN DE IMPRIMIR
EN BOGOT EL MES DE
ABRIL DE 2004 EN LAS
PRENSAS EDITORIALES DE
UNIBIBLOS, UNIVERSIDAD
NACIONAL DE COLOMBIA

Das könnte Ihnen auch gefallen