P. 1
prog

prog

|Views: 46|Likes:
Published by Romina Ballesteros

More info:

Published by: Romina Ballesteros on Nov 08, 2011
Copyright:Attribution Non-commercial

Availability:

Read on Scribd mobile: iPhone, iPad and Android.
download as PDF, TXT or read online from Scribd
See more
See less

02/16/2012

pdf

text

original

Departamento de F´ ısica, Facultad de Ciencias, Universidad de Chile. ˜ n Las Palmeras 3425, Nu˜oa.

Casilla 653, Correo 1, Santiago fono: 562 978 7276 fax: 562 271 2973 e-mail: secretaria@fisica.ciencias.uchile.cl

Apuntes de un curso de

´ ´ PROGRAMACION Y METODOS ´ NUMERICOS
S´ptima edici´n, revisi´n 061107-14 e o o

Jos´ Rogan C. e V´ ıctor Mu˜oz G. n

ii

Agradecimientos:
Xavier Andrade. Denisse Past´n. e De la promoci´n del 2004 a: Daniel Asenjo y Max Ram´ o ırez. De la promoci´n del 2005 a: Alejandro Varas y Mar´ Daniela Cornejo. o ıa De la promoci´n del 2006 a: Nicol´s Verschueren y Paulina Chac´n, o a o Sergio Valdivia y Elizabeth Villanueva.

iv

´ Indice
I Computaci´n o
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

1
3 3 4 4 5 5 6 6 7 9 9 10 11 11 12 12 13 16 23 23 23 24 25 26 27 27 27 29 29 29 31 31 33 33

1. Elementos del sistema operativo unix. 1.1. Introducci´n. . . . . . . . . . . . . . . . . . . . . o 1.2. Ingresando al sistema. . . . . . . . . . . . . . . . 1.2.1. Terminales. . . . . . . . . . . . . . . . . . 1.2.2. Login. . . . . . . . . . . . . . . . . . . . . 1.2.3. Passwords. . . . . . . . . . . . . . . . . . . 1.2.4. Cerrando la sesi´n. . . . . . . . . . . . . . o 1.3. El Proyecto Debian. . . . . . . . . . . . . . . . . 1.4. Archivos y directorios. . . . . . . . . . . . . . . . ´ 1.5. Ordenes b´sicas. . . . . . . . . . . . . . . . . . . a ´ 1.5.1. Ordenes relacionadas con archivos. . . . . ´ 1.5.2. Ordenes relacionadas con directorios. . . . 1.5.3. Visitando archivos. . . . . . . . . . . . . . 1.5.4. Copiando, moviendo y borrando archivos. 1.5.5. Espacio de disco. . . . . . . . . . . . . . . 1.5.6. Links. . . . . . . . . . . . . . . . . . . . . 1.5.7. Protecci´n de archivos. . . . . . . . . . . . o 1.5.8. Filtros. . . . . . . . . . . . . . . . . . . . . 1.5.9. Otros usuarios y m´quinas . . . . . . . . . a 1.5.10. Fecha . . . . . . . . . . . . . . . . . . . . 1.5.11. Diferencias entre sistemas. . . . . . . . . . 1.6. Shells. . . . . . . . . . . . . . . . . . . . . . . . . 1.6.1. Variables de entorno. . . . . . . . . . . . 1.6.2. Redirecci´n. . . . . . . . . . . . . . . . . . o 1.6.3. Ejecuci´n de comandos. . . . . . . . . . . o 1.6.4. Aliases. . . . . . . . . . . . . . . . . . . . 1.6.5. La shell bash. . . . . . . . . . . . . . . . . 1.6.6. Archivos de script. . . . . . . . . . . . . . 1.7. Ayuda y documentaci´n. . . . . . . . . . . . . . . o 1.8. Procesos. . . . . . . . . . . . . . . . . . . . . . . . 1.9. Editores. . . . . . . . . . . . . . . . . . . . . . . . 1.9.1. El editor vi. . . . . . . . . . . . . . . . . . 1.9.2. Editores modo emacs. . . . . . . . . . . . 1.10. El sistema X Windows. . . . . . . . . . . . . . . .
v

vi

´ INDICE 1.11. Uso del rat´n. . . . . . . . . o 1.12. Internet. . . . . . . . . . . . 1.12.1. Acceso a la red. . . . 1.12.2. El correo electr´nico. o 1.12.3. Ftp anonymous. . . . 1.12.4. WWW. . . . . . . . 1.13. Impresi´n. . . . . . . . . . . o 1.14. Compresi´n. . . . . . . . . . o . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35 35 36 37 39 39 39 40 43 43 43 43 44 44 45 45 46 46 46 46 47 48 49 49 49 50 50 50 52 52 52 53 53 53 54 54 54 55 55 55 56 56 57

2. Introducci´n a programaci´n. o o 2.1. ¿Qu´ es programar? . . . . . . . . . . . . . . . e 2.2. Lenguajes de programaci´n. . . . . . . . . . . o 2.2.1. C´digo de M´quina binario. . . . . . . o a 2.2.2. Lenguaje de Ensamblador (Assembler). 2.2.3. Lenguaje de alto nivel. . . . . . . . . . 2.2.4. Lenguajes interpretados. . . . . . . . . 2.2.5. Lenguajes especializados. . . . . . . . . 2.3. Lenguajes naturales y formales. . . . . . . . . 2.3.1. Lenguajes naturales. . . . . . . . . . . 2.3.2. Lenguajes formales. . . . . . . . . . . . 2.4. Desarrollando programas. . . . . . . . . . . . 2.5. La interfaz con el usuario. . . . . . . . . . . . 2.6. Sacar los errores de un programa. . . . . . . . 3. Una breve introducci´n a Python. o 3.1. Python. . . . . . . . . . . . . . . . . . . . . . 3.1.1. Interactivo versus scripting. . . . . . . 3.1.2. Creando un script. . . . . . . . . . . . 3.2. Lenguaje Python. . . . . . . . . . . . . . . . . 3.2.1. Algunos tipos b´sicos. . . . . . . . . . a 3.2.2. Imprimiendo en la misma l´ ınea. . . . . 3.2.3. Imprimiendo un texto de varias l´ ıneas. 3.2.4. Variables. . . . . . . . . . . . . . . . . 3.2.5. Asignaci´n de variables. . . . . . . . . o 3.2.6. Reciclando variables. . . . . . . . . . . 3.2.7. Operaciones matem´ticas. . . . . . . . a 3.2.8. Operaciones con strings. . . . . . . . . 3.2.9. Composici´n. . . . . . . . . . . . . . . o 3.2.10. Comentarios. . . . . . . . . . . . . . . 3.2.11. Entrada (input). . . . . . . . . . . . . 3.3. Condicionales. . . . . . . . . . . . . . . . . . . 3.3.1. Posibles condicionales. . . . . . . . . . 3.3.2. El if. . . . . . . . . . . . . . . . . . . 3.3.3. El if. . . else. . . . . . . . . . . . . . . 3.3.4. El if...elif...else. . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . .

´ INDICE 3.3.5. La palabra clave pass. . . . . . . . . . . . 3.3.6. Operadores l´gicos. . . . . . . . . . . . . . o 3.3.7. Forma alternativa. . . . . . . . . . . . . . 3.4. Funciones Pre-hechas. . . . . . . . . . . . . . . . 3.4.1. Algunas funciones incorporadas. . . . . . . 3.4.2. Algunas funciones del m´dulo math. . . . . o 3.4.3. Algunas funciones del m´dulo string. . . o 3.4.4. Algunas funciones del m´dulo random. . . o 3.4.5. Algunos otros m´dulos y funciones. . . . . o 3.5. Funciones hechas en casa. . . . . . . . . . . . . . 3.5.1. Receta para una funci´n. . . . . . . . . . . o 3.5.2. Variables globales. . . . . . . . . . . . . . 3.5.3. Pasando valores a la funci´n. . . . . . . . o 3.5.4. Valores por defecto de una funci´n. . . . . o 3.6. Argumentos Claves. . . . . . . . . . . . . . . . . . 3.7. DocStrings. . . . . . . . . . . . . . . . . . . . . . 3.7.1. La palabra clave return. . . . . . . . . . . 3.7.2. Funciones que tienen un valor de retorno. . 3.7.3. Recursi´n. . . . . . . . . . . . . . . . . . . o 3.8. Par´metros desde la l´ a ınea de comando. . . . . . . 3.9. Iteraciones con while. . . . . . . . . . . . . . . . 3.10. Los strings. . . . . . . . . . . . . . . . . . . . . . 3.10.1. ´ Indice negativos. . . . . . . . . . . . . . . 3.10.2. ¿Cu´n largo es un string? . . . . . . . . . a 3.10.3. Recorriendo un string. . . . . . . . . . . . 3.10.4. El ciclo for. . . . . . . . . . . . . . . . . . 3.10.5. Comparando strings. . . . . . . . . . . . . 3.11. Listas. . . . . . . . . . . . . . . . . . . . . . . . . 3.11.1. Rebanando listas. . . . . . . . . . . . . . . 3.11.2. Mutabilidad. . . . . . . . . . . . . . . . . 3.11.3. Agregando a una lista. . . . . . . . . . . . 3.11.4. Operaciones con listas. . . . . . . . . . . . 3.11.5. Borrando items de una lista. . . . . . . . . 3.11.6. ¿Qu´ contiene una lista? . . . . . . . . . . e 3.11.7. Un ciclo for y las listas. . . . . . . . . . . 3.11.8. Otros trucos con listas. . . . . . . . . . . . 3.11.9. Generando listas de n´meros. . . . . . . . u 3.12. Tuplas. . . . . . . . . . . . . . . . . . . . . . . . . 3.13. El comando break. . . . . . . . . . . . . . . . . . 3.14. Trabajando con archivos. . . . . . . . . . . . . . . 3.14.1. Funciones del m´dulo os. . . . . . . . . . . o 3.14.2. Funciones del m´dulo os.path. . . . . . . o 3.14.3. Ejemplo de un c´digo. . . . . . . . . . . . o 3.14.4. Abriendo un archivo. . . . . . . . . . . . . 3.14.5. Leyendo un archivo. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

vii

57 57 58 58 59 60 60 60 60 61 61 62 62 62 63 64 64 65 65 66 67 67 68 68 68 68 69 69 70 70 71 71 71 71 72 72 72 73 73 74 74 74 75 75 75

viii

´ INDICE 3.14.6. Escribiendo a un archivo. . . . . . . . . . . . 3.14.7. Cerrando un archivo. . . . . . . . . . . . . . 3.14.8. Archivos temporales. . . . . . . . . . . . . . 3.14.9. Ejemplo de lectura escritura. . . . . . . . . . 3.15. Excepciones. . . . . . . . . . . . . . . . . . . . . . . 3.16. Diccionarios. . . . . . . . . . . . . . . . . . . . . . . 3.16.1. Editando un diccionario. . . . . . . . . . . . 3.16.2. Un ejemplo de c´digo, un men´. . . . . . . . o u 3.16.3. Tuplas y diccionarios como argumentos. . . 3.17. Modules y Shelve. . . . . . . . . . . . . . . . . . . . 3.17.1. Partiendo el c´digo. . . . . . . . . . . . . . . o 3.17.2. Creando un m´dulo. . . . . . . . . . . . . . o 3.17.3. Agregando un nuevo directorio al path. . . . 3.17.4. Haciendo los m´dulos f´ciles de usar. . . . . o a 3.17.5. Usando un m´dulo. . . . . . . . . . . . . . . o 3.17.6. Trucos con m´dulos. . . . . . . . . . . . . . o 3.17.7. Preservando la estructura de la informaci´n. o 3.17.8. ¿C´mo almacenar? . . . . . . . . . . . . . . o 3.17.9. Ejemplo de shelve. . . . . . . . . . . . . . . 3.17.10.Otras funciones de shelve. . . . . . . . . . . 3.18. Clases y m´todos. . . . . . . . . . . . . . . . . . . . e 3.18.1. Clase de muestra LibretaNotas. . . . . . . . 3.18.2. Valores por defecto. . . . . . . . . . . . . . . 3.19. Sobrecarga de Operadores. . . . . . . . . . . . . . . 3.19.1. Funci´n driver. . . . . . . . . . . . . . . . . o 3.19.2. Atributos de las clases. . . . . . . . . . . . . 3.19.3. Ejemplo de clase vectores. . . . . . . . . . . 3.20. Algunos m´dulos interesantes. . . . . . . . . . . . . o 3.20.1. El m´dulo Numeric. . . . . . . . . . . . . . o 3.20.2. El m´dulo Tkinter. . . . . . . . . . . . . . o 3.20.3. El m´dulo Visual. . . . . . . . . . . . . . . o . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75 76 76 76 77 77 78 79 79 79 79 79 80 80 80 81 81 81 82 82 82 83 84 84 85 85 86 86 86 87 87 89 89 89 90 92 92 94 95 95 95 96 98 98

4. Una breve introducci´n a C++. o 4.1. Estructura b´sica de un programa en C++. a 4.1.1. El programa m´s simple. . . . . . . . a 4.1.2. Definici´n de funciones. . . . . . . . o 4.1.3. Nombres de variables. . . . . . . . . 4.1.4. Tipos de variables. . . . . . . . . . . 4.1.5. Ingreso de datos desde el teclado. . . 4.1.6. Operadores aritm´ticos. . . . . . . . e 4.1.7. Operadores relacionales. . . . . . . . 4.1.8. Asignaciones. . . . . . . . . . . . . . 4.1.9. Conversi´n de tipos. . . . . . . . . . o 4.2. Control de flujo. . . . . . . . . . . . . . . . . 4.2.1. if, if... else, if... else if. . .

. . . . . . . . . . . .

. . . . . . . . . . . .

. . . . . . . . . . . .

. . . . . . . . . . . .

. . . . . . . . . . . .

. . . . . . . . . . . .

. . . . . . . . . . . .

. . . . . . . . . . . .

. . . . . . . . . . . .

. . . . . . . . . . . .

. . . . . . . . . . . .

. . . . . . . . . . . .

. . . . . . . . . . . .

. . . . . . . . . . . .

. . . . . . . . . . . .

. . . . . . . . . . . .

. . . . . . . . . . . .

. . . . . . . . . . . .

. . . . . . . . . . . .

´ INDICE 4.2.2. Expresi´n condicional. . . . . . . . . . . . . . . o 4.2.3. switch. . . . . . . . . . . . . . . . . . . . . . . 4.2.4. for. . . . . . . . . . . . . . . . . . . . . . . . . 4.2.5. while. . . . . . . . . . . . . . . . . . . . . . . . 4.2.6. do... while. . . . . . . . . . . . . . . . . . . . 4.2.7. goto. . . . . . . . . . . . . . . . . . . . . . . . 4.3. Funciones. . . . . . . . . . . . . . . . . . . . . . . . . . 4.3.1. Funciones tipo void. . . . . . . . . . . . . . . . 4.3.2. return. . . . . . . . . . . . . . . . . . . . . . . 4.3.3. Funciones con par´metros. . . . . . . . . . . . . a 4.3.4. Par´metros por defecto. . . . . . . . . . . . . . a 4.3.5. Ejemplos de funciones: ra´ cuadrada y factorial. ız 4.3.6. Alcance, visibilidad, tiempo de vida. . . . . . . 4.3.7. Recursi´n. . . . . . . . . . . . . . . . . . . . . . o 4.3.8. Funciones internas. . . . . . . . . . . . . . . . . 4.4. Punteros. . . . . . . . . . . . . . . . . . . . . . . . . . 4.5. Matrices o arreglos. . . . . . . . . . . . . . . . . . . . . 4.5.1. Declaraci´n e inicializaci´n. . . . . . . . . . . . o o 4.5.2. Matrices como par´metros de funciones. . . . . a 4.5.3. Asignaci´n din´mica. . . . . . . . . . . . . . . . o a 4.5.4. Matrices multidimensionales. . . . . . . . . . . . 4.5.5. Matrices de caracteres: cadenas (strings). . . . . 4.6. Manejo de archivos. . . . . . . . . . . . . . . . . . . . . 4.6.1. Archivos de salida. . . . . . . . . . . . . . . . . 4.6.2. Archivos de entrada. . . . . . . . . . . . . . . . 4.6.3. Archivos de entrada y salida. . . . . . . . . . . 4.7. main como funci´n. . . . . . . . . . . . . . . . . . . . . o 4.7.1. Tipo de retorno de la funci´n main. . . . . . . . o 4.8. Clases. . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.8.1. Definici´n. . . . . . . . . . . . . . . . . . . . . . o 4.8.2. Miembros. . . . . . . . . . . . . . . . . . . . . . 4.8.3. Miembros p´blicos y privados. . . . . . . . . . . u 4.8.4. Operador de selecci´n (.). . . . . . . . . . . . . o 4.8.5. Implementaci´n de funciones miembros. . . . . o 4.8.6. Constructor. . . . . . . . . . . . . . . . . . . . . 4.8.7. Destructor. . . . . . . . . . . . . . . . . . . . . 4.8.8. Arreglos de clases. . . . . . . . . . . . . . . . . 4.9. Sobrecarga. . . . . . . . . . . . . . . . . . . . . . . . . 4.9.1. Sobrecarga de funciones. . . . . . . . . . . . . . 4.9.2. Sobrecarga de operadores. . . . . . . . . . . . . 4.9.3. Coerci´n. . . . . . . . . . . . . . . . . . . . . . o 4.10. Herencia. . . . . . . . . . . . . . . . . . . . . . . . . . . 4.11. Ejemplo: la clase de los complejos. . . . . . . . . . . . . 4.12. Compilaci´n y debugging. . . . . . . . . . . . . . . . . o 4.12.1. Compiladores. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

ix

100 100 101 103 104 104 104 104 105 106 109 110 113 115 116 117 119 119 119 120 121 123 125 125 128 129 130 132 133 134 134 134 135 136 136 137 138 138 139 139 139 140 141 145 145

x

´ INDICE 147 . 147 . 148 . 148 . 149 . 149 . 150 . 151 153 . 153 . 153 . 154 . 154 . 154 . 155 . 155 . 156 . 157 . 157 . 157 . 158 . 159 . 160 . 160 . 161 . 162 . 163 . 164 . 164 . 164 . 165 . 165 . 166 . 166 . 166 . 168 . 169 . 171 . 172 . 172 . 172 . 173 . 173 . 174

5. Gr´fica. a 5.1. Visualizaci´n de archivos gr´ficos. . . o a 5.2. Modificando im´genes . . . . . . . . a 5.3. Conversi´n entre formatos gr´ficos. . o a 5.4. Captura de pantalla. . . . . . . . . . 5.5. Creando im´genes. . . . . . . . . . . a 5.6. Graficando funciones y datos. . . . . 5.7. Graficando desde nuestros programas.

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

6. El sistema de preparaci´n de documentos TEX . o 6.1. Introducci´n. . . . . . . . . . . . . . . . . . . . . o 6.2. Archivos. . . . . . . . . . . . . . . . . . . . . . . . 6.3. Input b´sico. . . . . . . . . . . . . . . . . . . . . a 6.3.1. Estructura de un archivo. . . . . . . . . . 6.3.2. Caracteres. . . . . . . . . . . . . . . . . . 6.3.3. Comandos. . . . . . . . . . . . . . . . . . 6.3.4. Algunos conceptos de estilo. . . . . . . . . 6.3.5. Notas a pie de p´gina. . . . . . . . . . . . a 6.3.6. F´rmulas matem´ticas. . . . . . . . . . . . o a 6.3.7. Comentarios. . . . . . . . . . . . . . . . . 6.3.8. Estilo del documento. . . . . . . . . . . . . 6.3.9. Argumentos de comandos. . . . . . . . . . 6.3.10. T´ ıtulo. . . . . . . . . . . . . . . . . . . . . 6.3.11. Secciones. . . . . . . . . . . . . . . . . . . 6.3.12. Listas. . . . . . . . . . . . . . . . . . . . . 6.3.13. Tipos de letras. . . . . . . . . . . . . . . . 6.3.14. Acentos y s´ ımbolos. . . . . . . . . . . . . . 6.3.15. Escritura de textos en castellano. . . . . . 6.4. F´rmulas matem´ticas. . . . . . . . . . . . . . . . o a 6.4.1. Sub y supra´ ındices. . . . . . . . . . . . . . 6.4.2. Fracciones. . . . . . . . . . . . . . . . . . . 6.4.3. Ra´ ıces. . . . . . . . . . . . . . . . . . . . . 6.4.4. Puntos suspensivos. . . . . . . . . . . . . . 6.4.5. Letras griegas. . . . . . . . . . . . . . . . . 6.4.6. Letras caligr´ficas. . . . . . . . . . . . . . a 6.4.7. S´ ımbolos matem´ticos. . . . . . . . . . . . a 6.4.8. Funciones tipo logaritmo. . . . . . . . . . 6.4.9. Matrices. . . . . . . . . . . . . . . . . . . . 6.4.10. Acentos. . . . . . . . . . . . . . . . . . . . 6.4.11. Texto en modo matem´tico. . . . . . . . . a 6.4.12. Espaciado en modo matem´tico. . . . . . . a 6.4.13. Fonts. . . . . . . . . . . . . . . . . . . . . 6.5. Tablas. . . . . . . . . . . . . . . . . . . . . . . . . 6.6. Referencias cruzadas. . . . . . . . . . . . . . . . . 6.7. Texto centrado o alineado a un costado. . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

´ INDICE 6.8. Algunas herramientas importantes . . . . . . 6.8.1. babel . . . . . . . . . . . . . . . . . A 6.8.2. AMS-L TEX . . . . . . . . . . . . . . 6.8.3. fontenc . . . . . . . . . . . . . . . . 6.8.4. enumerate . . . . . . . . . . . . . . . 6.8.5. Color. . . . . . . . . . . . . . . . . . 6.9. Modificando el estilo de la p´gina. . . . . . . a 6.9.1. Estilos de p´gina. . . . . . . . . . . . a 6.9.2. Corte de p´ginas y l´ a ıneas. . . . . . . 6.10. Figuras. . . . . . . . . . . . . . . . . . . . . 6.10.1. graphicx.sty . . . . . . . . . . . . . 6.10.2. Ambiente figure. . . . . . . . . . . . 6.11. Cartas. . . . . . . . . . . . . . . . . . . . . . A 6.12. L TEX y el formato pdf. . . . . . . . . . . . . A 6.13. Modificando L TEX. . . . . . . . . . . . . . . 6.13.1. Definici´n de nuevos comandos. . . . o 6.13.2. Creaci´n de nuevos paquetes y clases o 6.14. Errores y advertencias. . . . . . . . . . . . . 6.14.1. Errores. . . . . . . . . . . . . . . . . 6.14.2. Advertencias. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

xi

175 175 176 179 179 179 180 180 181 184 185 185 187 189 190 190 195 202 202 205

II

M´todos Num´ricos. e e
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

207
209 . 209 . 221 . 221 . 223 225 225 225 227 228 229 229 230 232 232 234 235 237 241 241

7. Preliminares. 7.1. Programas y funciones. . . . 7.2. Errores num´ricos. . . . . . e 7.2.1. Errores de escala. . . 7.2.2. Errores de redondeo.

8. EDO: M´todos b´sicos. e a 8.1. Movimiento de un proyectil. . . . . . . . . . . . . . . . . . . 8.1.1. Ecuaciones b´sicas. . . . . . . . . . . . . . . . . . . . a 8.1.2. Derivada avanzada. . . . . . . . . . . . . . . . . . . . 8.1.3. M´todo de Euler. . . . . . . . . . . . . . . . . . . . . e 8.1.4. M´todos de Euler-Cromer y de Punto Medio. . . . . e 8.1.5. Errores locales, errores globales y elecci´n del paso de o 8.1.6. Programa de la pelota de baseball. . . . . . . . . . . . 8.2. P´ndulo simple. . . . . . . . . . . . . . . . . . . . . . . . . . e 8.2.1. Ecuaciones b´sicas. . . . . . . . . . . . . . . . . . . . a 8.2.2. F´rmulas para la derivada centrada. . . . . . . . . . . o 8.2.3. M´todos del “salto de la rana” y de Verlet. . . . . . . e 8.2.4. Programa de p´ndulo simple. . . . . . . . . . . . . . e 8.3. Listado de los programas en python. . . . . . . . . . . . . . 8.3.1. balle.py . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . tiempo. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . .

. . . . . . . . . . . . . .

. . . . . . . . . . . . . .

. . . . . . . . . . . . . .

. . . . . . . . . . . . . .

xii

´ INDICE 8.3.2. pendulo.py . . . 8.4. Listado de los programas 8.4.1. balle.cc . . . . 8.4.2. pendulo.cc . . . . . . . . en c++. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 243 245 245 246

9. EDO II: M´todos Avanzados. e ´ 9.1. Orbitas de cometas. . . . . . . . . . . . . . . . . . 9.1.1. Ecuaciones b´sicas. . . . . . . . . . . . . . a 9.1.2. Programa orbita. . . . . . . . . . . . . . 9.2. M´todos de Runge-Kutta. . . . . . . . . . . . . . e 9.2.1. Runge-Kutta de segundo orden. . . . . . . 9.2.2. F´rmulas generales de Runge-Kutta. . . . o 9.2.3. Runge-Kutta de cuarto orden. . . . . . . . 9.2.4. Pasando funciones a funciones. . . . . . . 9.3. M´todos adaptativos . . . . . . . . . . . . . . . . e 9.3.1. Programas con paso de tiempo adaptativo. 9.3.2. Funci´n adaptativa de Runge-Kutta. . . . o 9.4. Listados del programa. . . . . . . . . . . . . . . . 9.4.1. orbita.cc . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

249 . 249 . 249 . 251 . 255 . 255 . 257 . 258 . 259 . 260 . 260 . 261 . 264 . 264 271 . 271 . 271 . 272 . 273 . 275 . 275 . 276 . 278 . 278 . 280 . 281 . 282 . 282 . 283 . 284 . 285 . 287 . 287 . 288 . 292 . 293 . 293 . 295

10.Resolviendo sistemas de ecuaciones. 10.1. Sistemas de ecuaciones lineales. . . . . . . . . . . . . . . . . . . 10.1.1. Estado estacionario de EDO. . . . . . . . . . . . . . . . . 10.1.2. Eliminaci´n Gaussiana. . . . . . . . . . . . . . . . . . . . o 10.1.3. Pivoteando. . . . . . . . . . . . . . . . . . . . . . . . . . 10.1.4. Determinantes. . . . . . . . . . . . . . . . . . . . . . . . 10.1.5. Eliminaci´n Gaussiana en Octave. . . . . . . . . . . . . . o 10.1.6. Eliminaci´n Gaussiana con C++ de objetos matriciales. o 10.2. Matriz inversa. . . . . . . . . . . . . . . . . . . . . . . . . . . . 10.2.1. Matriz inversa y eliminaci´n Gaussiana. . . . . . . . . . o 10.2.2. Matrices singulares y patol´gicas. . . . . . . . . . . . . . o 10.2.3. Osciladores arm´nicos acoplados. . . . . . . . . . . . . . o 10.3. Sistemas de ecuaciones no lineales. . . . . . . . . . . . . . . . . 10.3.1. M´todo de Newton en una variable. . . . . . . . . . . . . e 10.3.2. M´todo de Newton multivariable. . . . . . . . . . . . . . e 10.3.3. Programa del m´todo de Newton. . . . . . . . . . . . . . e 10.3.4. Continuaci´n. . . . . . . . . . . . . . . . . . . . . . . . . o 10.4. Listados del programa. . . . . . . . . . . . . . . . . . . . . . . . 10.4.1. Definici´n de la clase Matrix. . . . . . . . . . . . . . . . o 10.4.2. Implementaci´n de la clase Matrix. . . . . . . . . . . . . o 10.4.3. Funci´n de eliminaci´n Gaussiana ge. . . . . . . . . . . . o o 10.4.4. Funci´n para inversi´n de matrices inv. . . . . . . . . . o o 10.4.5. Programa newtn en Octave. . . . . . . . . . . . . . . . . 10.4.6. Programa newtn en c++. . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . .

´ INDICE 11.An´lisis de datos. a 11.1. Ajuste de curvas. . . . . . . . . . . . . . . . . . . . 11.1.1. El calentamiento global. . . . . . . . . . . . 11.1.2. Teor´ general. . . . . . . . . . . . . . . . . ıa 11.1.3. Regresi´n lineal. . . . . . . . . . . . . . . . . o 11.1.4. Ajuste general lineal de m´ ınimos cuadrados. 11.1.5. Bondades del ajuste. . . . . . . . . . . . . . 12.Integraci´n num´rica b´sica o e a 12.1. Definiciones . . . . . . . . . . . . . . 12.2. Regla trapezoidal . . . . . . . . . . . 12.3. Interpolaci´n con datos equidistantes. o 12.4. Reglas de cuadratura . . . . . . . . . 12.5. Integraci´n de Romberg . . . . . . . o 12.6. Cuadratura de Gauss. . . . . . . . . 12.7. Bibliograf´ . . . . . . . . . . . . . . ıa 12.8. Listados del programa. . . . . . . . . 12.8.1. trapecio.cc . . . . . . . . . 12.8.2. romberg.cc . . . . . . . . . .

xiii

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

299 . 299 . 299 . 300 . 301 . 304 . 305 307 307 308 309 310 312 314 316 317 317 317

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

III

Ap´ndices. e

321
323

A. Transferencia a diskettes.

B. Las shells csh y tcsh. 325 B.1. Comandos propios. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 325 B.2. Variables propias del shell. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 326 C. Editores tipo emacs. D. Una breve introducci´n a Octave/Matlab o D.1. Introducci´n . . . . . . . . . . . . . . . . . . . . . . . o D.2. Interfase con el programa . . . . . . . . . . . . . . . . D.3. Tipos de variables . . . . . . . . . . . . . . . . . . . . D.3.1. Escalares . . . . . . . . . . . . . . . . . . . . . D.3.2. Matrices . . . . . . . . . . . . . . . . . . . . . D.3.3. Strings . . . . . . . . . . . . . . . . . . . . . . D.3.4. Estructuras . . . . . . . . . . . . . . . . . . . D.4. Operadores b´sicos . . . . . . . . . . . . . . . . . . . a D.4.1. Operadores aritm´ticos . . . . . . . . . . . . . e D.4.2. Operadores relacionales . . . . . . . . . . . . . D.4.3. Operadores l´gicos . . . . . . . . . . . . . . . o D.4.4. El operador : . . . . . . . . . . . . . . . . . D.4.5. Operadores de aparici´n preferente en scripts o D.5. Comandos matriciales b´sicos . . . . . . . . . . . . . a 329 337 . 337 . 337 . 338 . 338 . 338 . 340 . 340 . 341 . 341 . 342 . 342 . 342 . 343 . 343

. . . . . . . . . . . . . .

. . . . . . . . . . . . . .

. . . . . . . . . . . . . .

. . . . . . . . . . . . . .

. . . . . . . . . . . . . .

. . . . . . . . . . . . . .

. . . . . . . . . . . . . .

. . . . . . . . . . . . . .

. . . . . . . . . . . . . .

. . . . . . . . . . . . . .

. . . . . . . . . . . . . .

. . . . . . . . . . . . . .

. . . . . . . . . . . . . .

xiv

´ INDICE D.6. Comandos . . . . . . . . . . . . . . . . . . D.6.1. Comandos generales . . . . . . . . D.6.2. Como lenguaje de programaci´n . . o D.6.3. Matrices y variables elementales . . D.6.4. Polinomios . . . . . . . . . . . . . . ´ D.6.5. Algebra lineal (matrices cuadradas) D.6.6. An´lisis de datos y transformada de a D.6.7. Gr´ficos . . . . . . . . . . . . . . . a D.6.8. Strings . . . . . . . . . . . . . . . . D.6.9. Manejo de archivos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Fourier . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 343 343 344 347 349 350 350 351 355 356

E. Asignaci´n din´mica. o a 361 E.1. Arreglos din´micos bidimensionales. . . . . . . . . . . . . . . . . . . . . . . . . 362 a F. make & Makefile. G. Herramientas b´sicas en el uso de L.A.M.P. a G.1. Objetivo. . . . . . . . . . . . . . . . . . . . . . . . . G.2. Prerequisitos . . . . . . . . . . . . . . . . . . . . . G.3. Breve referencia sobre paginas web. . . . . . . . . . G.3.1. Ejemplos . . . . . . . . . . . . . . . . . . . . G.4. Administrador de Bases de datos. . . . . . . . . . . G.5. Servidor Web. . . . . . . . . . . . . . . . . . . . . . G.6. P´ginas B´sicas en html. . . . . . . . . . . . . . . . a a G.6.1. Estructura de una p´gina en html. . . . . . . a G.6.2. Algo de estilo. . . . . . . . . . . . . . . . . . G.6.3. Formularios. . . . . . . . . . . . . . . . . . . G.7. MySql. . . . . . . . . . . . . . . . . . . . . . . . . . G.7.1. Iniciando sesi´n. . . . . . . . . . . . . . . . o G.7.2. Creando una base de datos. . . . . . . . . . G.7.3. Creando tablas. . . . . . . . . . . . . . . . . G.7.4. Interactuando con la Tabla. . . . . . . . . . G.8. Programaci´n en PHP. . . . . . . . . . . . . . . . . o G.8.1. Lenguaje PHP. . . . . . . . . . . . . . . . . G.8.2. Variables. . . . . . . . . . . . . . . . . . . . G.8.3. Recuperando variables desde un formulario. G.8.4. Control de flujo. . . . . . . . . . . . . . . . . G.8.5. Funci´n require. . . . . . . . . . . . . . . . . o G.8.6. Sesi´n. . . . . . . . . . . . . . . . . . . . . . o G.8.7. PHP interactuando con MySql. . . . . . . . G.9. Ejemplo Final. . . . . . . . . . . . . . . . . . . . . G.9.1. Paso I: Estructura de las tablas. . . . . . . . G.9.2. Paso II: ´rbol de p´ginas. . . . . . . . . . . a a G.10.Conclusiones. . . . . . . . . . . . . . . . . . . . . . G.10.1.Mejoras al Ejemplo final. . . . . . . . . . . . 363 367 . 367 . 367 . 367 . 368 . 369 . 369 . 369 . 370 . 370 . 373 . 376 . 376 . 376 . 377 . 377 . 380 . 380 . 381 . 381 . 382 . 383 . 383 . 385 . 387 . 387 . 388 . 392 . 392

. . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . .

´ INDICE

xv

G.11.Tabla de Colores en html. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 393

xvi

´ INDICE

´ Indice de figuras
6.1. Un sujeto caminando. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 186 7.1. Salida gr´fica del programa interp. . . . . . . . . . . . . . . . . . . . . . . . . 216 a 7.2. Salida gr´fica del programa interp. . . . . . . . . . . . . . . . . . . . . . . . . 219 a 7.3. Error absoluto ∆(h), ecuaci´n (7.9), versus h para f (x) = x2 y x = 1. . . . . . 224 o 8.1. 8.2. 8.3. 8.4. 8.5. 8.6. 8.7. 9.1. 9.2. 9.3. 9.4. 9.5. 9.6. 9.7. 9.8. Trayectoria para un paso de tiempo con Euler. . . . Movimiento de proyectil sin aire. . . . . . . . . . . Movimiento de proyectil con aire. . . . . . . . . . . M´todo de Euler para θm = 10◦ . . . . . . . . . . . . e M´todo de Euler con paso del tiempo m´s peque˜o. e a n M´todo de Verlet para θm = 10◦ . . . . . . . . . . . e M´todo de Verlet para θm = 170◦ . . . . . . . . . . . e . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 229 231 232 239 240 240 241 250 253 254 254 255 260 263 263

´ Orbita el´ ıptica alrededor del Sol. . . . . . . . . . . . . . . . . . . . . . . . . . . Trayectoria y energ´ usando el m´todo de Euler. . . . . . . . . . . . . . . . . ıa e Trayectoria y energ´ usando el m´todo de Euler-Cromer. . . . . . . . . . . . . ıa e Trayectoria y energ´ usando el m´todo de Euler-Cromer. . . . . . . . . . . . . ıa e Trayectoria y energ´ con el paso de tiempo m´s peque˜o en Euler-Cromer. . . ıa a n Trayectoria y energ´ usando el m´todo de Runge-Kutta. . . . . . . . . . . . . ıa e Trayectoria y energ´ usando el m´todo de Runge-Kutta adaptativo. . . . . . . ıa e Paso de tiempo en funci´n de la distancia radial del Runge-Kutta adaptativo. o

10.1. Sistema de bloques acoplados por resortes anclados entre paredes. . . . . . . . 281 10.2. Representaci´n gr´fica del m´todo de Newton. . . . . . . . . . . . . . . . . . . 283 o a e 11.1. Di´xido de carbono medido en Hawai. . . . . . . . . . . . . . . . . . . . . . . . 300 o 11.2. Ajuste de datos a una curva. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 301 12.1. Subintervalos. . . . . . . . . . . . . . . . . . . . . 12.2. Sucesi´n de l´ o ıneas rectas como curva aproximante. 12.3. Aproximaciones, (a) lineal, (b) cuadr´tica. . . . . a 12.4. Regla trapezoidal versus cuadratura de Gauss . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 307 308 310 314

D.1. Gr´fico simple. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 352 a D.2. Curvas de contorno. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 353 D.3. Curvas de contorno. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 354
xvii

xviii

´ INDICE DE FIGURAS G.1. Esquema de una tabla en html, utilizando los elementos de una matriz. . . . . 373 G.2. Los 256 colores posibles de desplegar en una p´gina en html, con su respectivo a c´digo. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 393 o

Parte I Computaci´n o

1

Cap´ ıtulo 1 Elementos del sistema operativo unix.
versi´n revisada 7.1, 31 de Julio del 2007 o

1.1.

Introducci´n. o

En este cap´ ıtulo se intentar´ dar los elementos b´sicos para poder trabajar en un ama a biente unix. Sin pretender cubrir todos los aspectos del mismo, nuestro inter´s se centra en e entregar las herramientas al lector para que pueda realizar los trabajos del curso bajo este sistema operativo. Como comentario adicional, conscientemente se ha evitado la traducci´n o de gran parte de la terminolog´ t´cnica teniendo en mente que documentaci´n disponible ıa e o se encuentre, por lo general, en ingl´s y nos interesa que el lector sea capaz de reconocer los e t´rminos. e El sistema operativo unix es el m´s usado en investigaci´n cient´ a o ıfica, tiene una larga historia y muchas de sus ideas y m´todos se encuentran presentes en otros sistemas operativos. e Algunas de las caracter´ ısticas relevantes del unix moderno son: Multitarea (Multitasking): Cada programa tiene asignado su propio “espacio” de memoria. Es imposible que un programa afecte a otro sin usar los servicios del sistema operativo. Si dos programas escriben en la misma direcci´n de memoria cada uno mano tiene su propia “idea” de su contenido. Multiusuario: M´s de una persona puede usar la m´quina al mismo tiempo. Programas a a de otros usuarios contin´an ejecut´ndose a pesar de que un nuevo usuario entre a la u a m´quina. a Memoria grande, lineal y virtual: Un programa en una m´quina de 32 Bits puede acceder a y usar direcciones hasta los 4 GB en una m´quina de s´lo 4 MB de RAM. El sistema a o s´lo asigna memoria aut´ntica cuando le hace falta, en caso de falta de memoria de o e RAM, se utiliza el disco duro (swap). Casi todo tipo de dispositivo puede ser accedido como un archivo. Existen muchas aplicaciones dise˜adas para trabajar desde la l´ n ınea de comandos. Adem´s, a la mayor´ de las aplicaciones permiten que la salida de una pueda ser la entrada de la ıa otra. Permite compartir dispositivos (como disco duro) entre una red de m´quinas. a 3

4

CAP´ ITULO 1. ELEMENTOS DEL SISTEMA OPERATIVO UNIX.

Por su naturaleza de multiusuario, nunca se deber´ apagar impulsivamente una m´quina ıa a 1 unix , ya que una m´quina apagada sin raz´n puede matar trabajos de d´ perder los a o ıas, ultimos cambios de tus archivos e ir degradando el sistema de archivos en dispositivos como ´ el disco duro. Entre los sistemas operativos unix actuales cabe destacar: Linux fue originalmente desarrollado primero para computadores personales PCs basados en x86 de 32 bits (386 o superiores). Hoy Linux corre sobre Intel x86/IA64, Motorola 68k, Sun SPARC, Alpha, Motorola/IBM PowerPC, Arm, MISP CPUs, HP PA-RISC, IA-64, ibm S/390, AMD64, ppc64, Hitachi SuperH, armeb y arquitecturas Renesas M32R. SunOS2 : disponible para la familia 68K as´ como para la familia sparc de estaciones ı de trabajo sun Solaris3 : disponible para la familia sparc de Sun as´ como para la familia x86. ı OSF14 : disponible para Alpha. Ultrix: disponible para vax de Digital SYSVR45 : disponible para la familia x86, vax. IRIX: disponible para mips. AIX6 : disponible para RS6000 de IBM y PowerPC.

1.2.

Ingresando al sistema.

En esta secci´n comentaremos las operaciones de comienzo y fin de una sesi´n en unix o o as´ como la modificaci´n de la contrase˜a (que a menudo no es la deseada por el usuario, y ı o n que por lo tanto puede olvidar con facilidad).

1.2.1.

Terminales.

Para iniciar una sesi´n es necesario poder acceder a un terminal. Pueden destacarse dos o tipos de terminales: Terminal de texto: consta de una pantalla y de un teclado. Como indica su nombre, en la pantalla s´lo es posible imprimir caracteres de texto. o Terminal gr´fico: Consta de pantalla gr´fica, teclado y mouse. Dicha pantalla suele ser a a de alta resoluci´n. En este modo se pueden emplear ventanas que emulan el comportao miento de un terminal de texto (xterm o gnome-terminal).
1

Incluyendo el caso en que la m´quina es un PC normal corriendo Linux u otra versi´n de unix. a o SunOS 4.1.x tambi´n se conoce como Solaris 1. e 3 Tambi´n conocido como SunOS 5.x, solaris 2 o Slowaris :-). e 4 Tambi´n conocido como Dec Unix. e 5 Tambi´n conocido como Unixware y Novell-Unix. e 6 Tambi´n conocido como Aches. e
2

1.2. INGRESANDO AL SISTEMA.

5

1.2.2.

Login.

El primer paso es encontrar un terminal libre donde aparezca el login prompt del sistema: Debian GNU/Linux 4.0 hostname tty2 hostname login: Tambi´n pueden ocurrir un par de cosas: e La pantalla no muestra nada. • Comprobar que la pantalla est´ encendida. e • Pulsar alguna tecla o mover el mouse para desactivar el protector de pantalla. Otra persona ha dejado una sesi´n abierta. En este caso existe la posibilidad de intentar o en otra m´quina o bien finalizar la sesi´n de dicha persona (si ´sta no se halla en las a o e proximidades). Una vez que se haya superado el paso anterior de encontrar el login prompt se procede con la introducci´n del Username al prompt de login y despu´s la contrase˜a (password) o e n adecuada.

1.2.3.

Passwords.

El password puede ser cualquier secuencia de caracteres a elecci´n. Deben seguirse las o siguientes pautas: Debe ser f´cil de recordar por uno mismo. Si se olvida, deber´ pasarse un mal rato a a dici´ndole al administrador de sistema que uno lo ha olvidado. e Para evitar que alguna persona no deseada obtenga el password y tenga libre acceso a los archivos de tu cuenta: • Las may´sculas y min´sculas no son equivalentes, sin embargo se recomienda que u u se cambie de una a otra. • Los caracteres num´ricos y no alfab´ticos tambi´n ayudan. Debe tenerse sin eme e e bargo la precauci´n de usar caracteres alfanum´ricos que se puedan encontrar en o e todos los terminales desde los que se pretenda acceder. • Las palabras de diccionario deben ser evitadas. Debe cambiarlo si cree que su password es conocido por otras personas, o descubre que alg´n intruso7 est´ usando su cuenta. u a El password debe ser cambiado con regularidad.
7

Intruso es cualquier persona que no sea el usuario.

6

CAP´ ITULO 1. ELEMENTOS DEL SISTEMA OPERATIVO UNIX.

La instrucci´n para cambiar el password en unix es passwd. A menudo, cuando existen o varias m´quinas que comparten recursos (disco duro, impresora, correo electr´nico, . . . ), para a o facilitar la administraci´n de dicho sistema se unifican los recursos de red (entre los que se o hayan los usuarios de dicho sistema) en una base de datos com´n. Dicho sistema se conoce u 8 como NIS (Network Information Service) . Si el sistema empleado dispone de este servicio, la modificaci´n de la contrase˜a en una m´quina supone la modificaci´n en todas las m´quinas o n a o a que constituyan el dominio NIS.

1.2.4.

Cerrando la sesi´n. o

Es importante que nunca se deje abierta una sesi´n, pues alg´n “intruso” podr´ tener o u ıa libre acceso a archivos de propiedad del usuario y manipularlos de forma indeseable. Para evitar todo esto basta teclear logout o exit y habr´s acabado la sesi´n de unix en dicha a o m´quina9 . a

1.3.

El Proyecto Debian.

El proyecto Debian es una asociaci´n de personas que han creado un sistema operativo o gratis y de c´digo abierto (free). Este sistema operativo se denomina Debian GNU/Linux o o simplemente Debian. Actualmente Debian ocupa el kernel Linux desarrollado por Linus Torvalds apoyado por miles de programadores de todo el mundo. Tambi´n est´n implementados otros kernels como e a Hurd, desarrollado por GNU, NetBSD y FreeBSD. La mayor´ de las herramientas del sistema operativo Debian provienen del proyecto ıa GNU y por ende son free. Cabe destacar que actualmente Debian tiene un total de m´s de a 18733 paquetes (por paquetes entendemos software precompilado, para la versi´n estable, o en un formato que permite su f´cil instalaci´n en nuestra m´quina). Entre estos paquetes a o a encontramos desde las herramientas b´sicas para procesar texto, hojas de c´lculo, edici´n de a a o im´genes, audio, video, hasta aplicaciones de gran utilidad cient´ a ıfica. Es importante recordar que todo este software es free y por lo tanto est´ al alcance de todos sin la necesidad de a comprar licencias ni pagar por actualizaciones. Tambi´n existe la posibilidad de modificar el e software ya que tenemos acceso al c´digo fuente de los programas. Debian siempre mantiene o activas al menos tres versiones que tienen las siguientes clasificaciones: stable (estable): Es la ultima versi´n oficial de Debian que ha sido probada para asegurar ´ o su estabilidad. Actualmente corresponde a la versi´n 4.0r0 cuyo nombre c´digo es etch. o o testing (en prueba): Esta es la versi´n que se est´ probando para asegurar su estabilidad o a y para luego pasar a ser versi´n estable. Nombre c´digo lenny. o o unstable (inestable): Aqu´ es donde los programadores verdaderamente desarrollan Deı bian y por esto no es muy estable y no se recomienda para el uso diario. Esta versi´n o se denomina siempre sid. Para informaci´n sobre Debian y c´mo bajarlo visite la p´gina oficial http://www.debian.org. o o a
Antiguamente se conoc´ como YP (Yellow Pages), pero debido a un problema de marca registrada de ıa United Kingdom of British Telecomunications se adoptaron las siglas nis. 9 En caso que se estuviera trabajando bajo X-Windows debes cerrar la sesi´n con Log Out Usuario de o Gnome.
8

1.4. ARCHIVOS Y DIRECTORIOS.

7

1.4.

Archivos y directorios.

Aunque las diferentes distribuciones ubiquen sus programas en diferentes partes, la estructura b´sica de directorios en una m´quina Linux es m´s o menos la misma: a a a /-|--> |--> |--> |--> |--> |--> |--> |--> |--> |--> |--> |--> |--> |--> |--> |--> |--> |--> |--> |--> |--> bin boot cdrom dev emul etc home initrd lib lib32 lib64 media mnt opt proc root sbin selinux sys tmp usr--|--> |--> |--> |--> |--> |--> |-->

|--> |--> |--> |--> |--> var--|... |--> |--> |--> |--> |...

bin games include lib lib32 lib64 local -|--> bin |--> include |--> lib |... sbin share src --> linux X11R6 lock log mail www

8

CAP´ ITULO 1. ELEMENTOS DEL SISTEMA OPERATIVO UNIX.

El ´rbol que observamos muestra el t´ a ıpico ´rbol de directorios en Linux. Pueden haber a peque˜as variaciones en algunos de los nombres de estos directorios dependiendo de la distrin buci´n o versi´n de Linux que se est´ usando. Entre los directorios m´s destacados tenemos: o o e a /home - Espacio reservado para las cuentas de los usuarios. /bin, /usr/bin - Binarios (ejecutables) b´sicos de unix. a /etc, aqu´ se encuentran los archivos de configuraci´n de todo los diferentes softwares ı o de la m´quina. a /proc, es un sistema de archivos virtuales. Contiene archivos que residen en memoria y no en el disco duro. Hace referencia a los programas que est´n corriendo en este a momento en el sistema. /dev (device) (dispositivo). Aqu´ se guardan los archivos asociados a los dispositivos. ı Se usan para acceder los dispositivos f´ ısicos del sistema y recursos tales como discos duros, modems, memoria, mouse, etc. Algunos dispositivos: • hd: hda1 ser´ el disco duro IDE, primario (a), y la primera partici´n (1). a o • fd: los archivos que empiecen con las letras fd se referir´n a los controladores de a las disketteras: fd0 ser´ la primera diskettera, fd1 ser´ la segunda y as´ sucesiıa ıa ı vamente. • ttyS: se usan para acceder a los puertos seriales como por ejemplo ttyS0, que es el puerto conocido como com1. • sd: son los dispositivos SCSI y/o SATA. Su uso es muy similar al del hd. Tambi´n e se usa para denominar a los dispositivos de almacenamiento conectados v´ USB ıa (pendrives). • lp: son los puertos paralelos. lp0 es el puerto conocido como LPT1. • null: ´ste es usado como un agujero negro, ya que todo lo que se dirige all´ desae ı parece. • tty: hacen referencia a cada una de las consolas virtuales. Como es de suponer, tty1 ser´ la primera consola virtual, tty2 la segunda, etc. a /usr/local - Zona con las aplicaciones no comunes a todos los sistemas unix, pero no por ello menos utilizadas. /usr/share/doc aqu´ se puede encontrar informaci´n relacionada con aplicaciones (en ı o forma de p´ginas de manual, texto, html o bien archivos dvi, Postscript o pdf). Tambi´n a e encontramos archivos de ejemplo, tutoriales, HOWTO, etc.

´ ´ 1.5. ORDENES BASICAS.

9

1.5.

´ Ordenes b´sicas. a

Para ejecutar un comando, basta con teclear su nombre (tambi´n debes tener permiso para e hacerlo). Las opciones o modificadores empiezan normalmente con el caracter - (p. ej. ls -l). Para especificar m´s de una opci´n, se pueden agrupar en una sola cadena de caracteres a o (ls -l -h es equivalente a ls -lh). Algunos comandos aceptan tambi´n opciones dadas por e palabras completas, en cuyo caso usualmente comienzan con -- (ls --color=auto).

1.5.1.

´ Ordenes relacionadas con archivos.

En un sistema computacional la informaci´n se encuentra en archivos que la contienen o (tabla de datos, texto ASCII, fuente en lenguaje Python, Fortran o C++, ejecutable, imagen, mp3, figura, resultados de simulaci´n, . . . ). Para organizar toda la informaci´n se dispone de o o una entidad denominada directorio, que permite el almacenamiento en su interior tanto de archivos como de otros directorios10 . Se dice que la estructura de directorios en unix es jer´rquica o arborescente, debido a a que todos los directorios nacen en un mismo punto (denominado directorio ra´ De hecho, ız). la zona donde uno trabaja es un nodo de esa estructura de directorios, pudiendo uno a su vez generar una estructura por debajo de ese punto. Un archivo se encuentra situado siempre en ´ un directorio y su acceso se realiza empleando el camino que conduce a ´l en el Arbol de e Directorios del Sistema. Este camino es conocido como el path. El acceso a un archivo se puede realizar empleando:

Path Absoluto, aqu´l que empieza con / e Por ejemplo : /etc/printcap Path Relativo, aqu´l que no empieza con / e Por ejemplo : ../examples/rc.dir.01 Los nombres de archivos y directorios pueden usar un m´ximo de 255 caracteres, cuala quier combinaci´n de letras y s´ o ımbolos (el caracter / no se permite).

Los caracteres comod´ (wildcard ) pueden ser empleados para acceder a un conjunto ın de archivos con caracter´ ısticas comunes. El signo * puede sustituir cualquier conjunto de caracteres11 y el signo ? a cualquier caracter individual. Por ejemplo:12
Normalmente se acude a la imagen de una carpeta que puede contener informes, documentos o bien otras carpetas, y as´ sucesivamente. ı 11 Incluido el punto ‘.’, unix no es dos. 12 bash$ es el prompt en todos los ejemplos.
10

10

CAP´ ITULO 1. ELEMENTOS DEL SISTEMA OPERATIVO UNIX.

bash$ ls f2c.1 flexdoc.1 rcmd.1 rptp.1 zforce.1 face.update.1 ftptool.1 rlab.1 rxvt.1 zip.1 faces.1 funzip.1 robot.1 zcat.1 zipinfo.1 flea.1 fvwm.1 rplay.1 zcmp.1 zmore.1 flex.1 rasttoppm.1 rplayd.1 zdiff.1 znew.1 bash$ ls rp* rplay.1 rplayd.1 rptp.1 bash$ ls *e?? face.update.1 zforce.1 zmore.1 Los archivos cuyo nombre comiencen por . se denominan ocultos, as´ por ejemplo en el ı directorio de partida de un usuario. bash$ ls -a user . .alias .fvwmrc .login .xinitrc .. .cshrc .joverc .profile .Xdefaults .enviroment .kshrc .tcshrc Algunos caracteres especiales para el acceso a archivos son: . Directorio actual .. Directorio superior en el ´rbol a ~ Directorio $HOME ~user Directorio $HOME del usuario user

1.5.2.

´ Ordenes relacionadas con directorios.

ls (LiSt) Este comando permite listar los archivos de un determinado directorio. Si no se le suministra argumento, lista los archivos y directorios en el directorio actual. Si se a˜ade el nombre de n un directorio el listado es del directorio suministrado. Existen varias opciones que modifican su funcionamiento entre las que destacan: -l (Long listing) proporciona un listado extenso, que consta de los permisos13 de cada archivo, el usuario, el tama˜o del archivo, . . . , etc. Adicionalmente la opci´n -h imprime n o los tama˜os en un formato f´cil de leer (Human readable). n a -a (list All) lista tambi´n los archivos ocultos. e -R (Recursive) lista recursivamente el contenido de todos los directorios que encuentre. -t ordena los archivos por tiempo de modificaci´n. o -S ordena los archivos por tama˜o. n -r invierte el sentido de un ordenamiento. -p agrega un caracter al final de cada nombre de archivo, indicando el tipo de archivo (por ejemplo, los directorios son identificados con un / al final).
13

Se comentar´ posteriormente este concepto. a

´ ´ 1.5. ORDENES BASICAS.

11

pwd (Print Working Directory) Este comando proporciona el nombre del directorio actual. cd (Change Directory) Permite moverse a trav´s de la estructura de directorios. Si no se le proporciona argumento se e provoca un salto al directorio $HOME. El argumento puede ser un nombre absoluto o relativo de un directorio. cd - vuelve al ultimo directorio visitado. ´ mkdir (MaKe DIRectory) Crea un directorio con el nombre (absoluto o relativo) proporcionado. rmdir (ReMove DIRectory) Elimina un directorio con el nombre (absoluto o relativo) suministrado. Dicho directorio debe de estar vac´ ıo.

1.5.3.

Visitando archivos.

Este conjunto de ´rdenes permite visualizar el contenido de un archivo sin modificar su o contenido. cat Muestra por pantalla el contenido de un archivo que se suministra como argumento. more Este comando es an´logo al anterior, pero permite la paginaci´n. a o less Es una versi´n mejorada del anterior. Permite moverse en ambas direcciones. Otra ventaja o es que no lee el archivo entero antes de arrancar.

1.5.4.

Copiando, moviendo y borrando archivos.

cp (CoPy) Copia un archivo(s) con otro nombre y/o a otro directorio, por ejemplo, el comando para copiar el archivo1.txt con el nombre archivo2.txt es: cp archivo1.txt archivo2.txt Veamos algunas opciones: -a copia en forma recursiva, no sigue los link simb´licos y preserva los atributos de lo o copiado. -i (interactive), impide que la copia provoque una p´rdida del archivo destino si ´ste e e existe14 . -R (recursive), copia un directorio y toda la estructura que cuelga de ´l. e mv (MoVe) Mueve un archivo(s) a otro nombre y/o a otro directorio, por ejemplo, el comando para mover el archivo1.txt al nombre archivo2.txt es:
14

Muchos sistemas tienen esta opci´n habilitada a trav´s de un alias, para evitar equivocaciones. o e

12

CAP´ ITULO 1. ELEMENTOS DEL SISTEMA OPERATIVO UNIX. mv archivo1.txt archivo2.txt

Este comando dispone de opciones an´logas al anterior. a rm (ReMove) Borra un archivo(s). En caso de que el argumento sea un directorio y se haya suministrado la opci´n -r, es posible borrar el directorio y todo su contenido. La opci´n -i pregunta antes o o de borrar.

1.5.5.

Espacio de disco.

El recurso de almacenamiento en el disco es siempre limitado. A continuaci´n se comentan o un par de comandos relacionados con la ocupaci´n de este recurso: o du (Disk Usage) Permite ver el espacio de disco ocupado (en bloques de disco15 ) por el archivo o directorio suministrado como argumento. La opci´n -s impide que cuando se aplique recursividad en o un directorio se muestren los subtotales. La opci´n -h imprime los tama˜os en un formato o n f´cil de leer (Human readable). a df (Disk Free) Muestra los sistemas de archivos que est´n montados en el sistema, con las cantidades totales, a usadas y disponibles para cada uno. df -h muestra los tama˜os en formato f´cil de leer. n a

1.5.6.

Links.

ln (LiNk) Permite realizar un enlace (link) entre dos archivos o directorios. Un enlace puede ser: hard link : se puede realizar s´lo entre archivos del mismo sistema de archivos. El archivo o enlazado apunta a la zona de disco donde se ubica el archivo original. Por tanto, si se elimina el archivo original, el enlace sigue teniendo acceso a dicha informaci´n. Es el o enlace por omisi´n. o symbolic link : permite enlazar archivos/directorios16 de diferentes sistemas de archivos. El archivo enlazado apunta al nombre del original. As´ si se elimina el archivo original ı el enlace apunta hacia un nombre sin informaci´n asociada. Para realizar este tipo de o enlace debe emplearse la opci´n -s. o Un enlace permite el uso de un archivo en otro directorio distinto del original sin necesidad de copiarlo, con el consiguiente ahorro de espacio. Veamos un ejemplo. Creemos un enlace cl´sico en Linux, al directorio existente linux-2.6.12.5 nombr´moslo sencillamente linux. a e mitarro:/usr/src# ln -s linux-2.6.12.5 linux
15 16

1 bloque normalmente es 1 Kbyte. Debe hacerse notar que los directorios s´lo pueden ser enlazados simb´licamente. o o

´ ´ 1.5. ORDENES BASICAS.

13

1.5.7.

Protecci´n de archivos. o

Dado que el sistema de archivos unix es compartido por un conjunto de usuarios, surge el problema de la necesidad de privacidad. Sin embargo, dado que existen conjuntos de personas que trabajan en com´n, es necesaria la posibilidad de que un conjunto de usuarios puedan u tener acceso a una serie de archivos (que puede estar limitado para el resto de los usuarios). Cada archivo y directorio del sistema dispone de un propietario, un grupo al que pertenece y unos permisos. Existen tres tipos fundamentales de permisos: lectura (r-Read ): en el caso de un archivo, significa poder examinar el contenido del mismo; en el caso de un directorio significa poder entrar en dicho directorio. escritura (w-Write): en el caso de un archivo significa poder modificar su contenido; en el caso de un directorio es crear un archivo o directorio en su interior. ejecuci´n (x-eXecute): en el caso de un archivo significa que ese archivo se pueda o ejecutar (binario o archivo de procedimientos); en el caso de un directorio es poder ejecutar alguna orden dentro de ´l. e Se distinguen tres grupos de personas sobre las que se deben especificar permisos: user: el usuario propietario del archivo. group: el grupo propietario del archivo (excepto el usuario). Como ya se ha comentado, cada usuario puede pertenecer a uno o varios grupos y el archivo generado pertenece a uno de los mismos. other: el resto de los usuarios (excepto el usuario y los usuarios que pertenezcan al grupo) Tambi´n se puede emplear all que es la uni´n de todos los anteriores. Para visualizar las e o protecciones de un archivo o directorio se emplea la orden ls -l, cuya salida es de la forma: -rw-r--r-- ...otra informaci´n... nombre o Los 10 primeros caracteres muestran las protecciones de dicho archivo: El primer caracter indica el tipo de archivo de que se trata: • archivo • d directorio • l enlace (link ) • c dispositivo de caracteres (p.e. puerta serial) • b dispositivo de bloques (p.e. disco duro) • s socket (conexi´n de red) o Los caracteres 2, 3, 4 son los permisos de usuario Los caracteres 5, 6, 7 son los permisos del grupo

14

CAP´ ITULO 1. ELEMENTOS DEL SISTEMA OPERATIVO UNIX. Los caracteres 8, 9, 10 son los permisos del resto de usuarios As´ en el ejemplo anterior -rw-r--r-- se trata de un archivo donde el usuario puede ı leer y escribir, mientras que el grupo y el resto de usuarios s´lo pueden leer. Estos suelen o ser los permisos por omisi´n para un archivo creado por un usuario. Para un directorio o los permisos por omisi´n suelen ser: drwxr-xr-x, donde se permite al usuario “entrar” o en el directorio y ejecutar ´rdenes desde ´l. o e chmod (CHange MODe) Esta orden permite modificar los permisos de un archivo. Con opci´n -R es recursiva. o chmod permisos files Existen dos modos de especificar los permisos: Modo absoluto o modo num´rico. Se realiza empleando un n´mero que resulta de la OR e u binario de los siguientes modos: 400 200 100 040 020 010 004 002 001 4000 lectura por el propietario. escritura por el propietario. ejecuci´n (b´squeda) por el propietario. o u lectura por el grupo. escritura por el grupo. ejecuci´n (b´squeda) por el grupo. o u lectura por el resto. escritura por el resto. ejecuci´n (b´squeda) por el resto. o u Set User ID, cuando se ejecuta el proceso corre con los permisos del due˜o del archivo. n

Por ejemplo: chmod 640 *.txt Permite la lectura y escritura por el usuario, lectura para el grupo y ning´n permiso u para el resto, de un conjunto de archivos que acaban en .txt Modo simb´lico o literal. Se realiza empleando una cadena (o cadenas separadas por o comas) para especificar los permisos. Esta cadena se compone de los siguientes tres elementos: who operation permission

• who : es una combinaci´n de: o ◦ ◦ ◦ ◦ u g o a : : : : user group others all (equivalente a ugo)

Si se omite este campo se supone a, con la restricci´n de no ir en contra de la o m´scara de creaci´n (umask). a o • operation: es una de las siguientes operaciones: ◦ + : a˜adir permiso. n

´ ´ 1.5. ORDENES BASICAS. ◦ - : eliminar permiso. ◦ = : asignar permiso, el resto de permisos de la misma categor´ se anulan. ıa • permission: es una combinaci´n de los caracteres: o ◦ r : read. ◦ w : write. ◦ x : execute. ◦ s : en ejecuci´n fija el usuario o el grupo. o Por ejemplo: chmod u+x tarea Permite la ejecuci´n por parte del usuario17 del archivo tarea. o

15

chmod u=rx, go=r *.txt Permite la lectura y ejecuci´n del usuario, y s´lo la lectura por parte del grupo y el o o resto de usuarios. umask Esta es una orden intr´ ınseca del Shell que permite asignar los permisos que se desea tengan los archivos y directorios por omisi´n. El argumento que acompa˜a a la orden es un n´mero o n u octal que aplicar´ una xor sobre los permisos por omisi´n (rw-rw-rw-) para archivos y a o (rwxrwxrwx) para directorios. El valor por omisi´n de la m´scara es 022 que habilita al o a usuario para lectura-escritura, al grupo y al resto para lectura. Sin argumentos muestra el valor de la m´scara. a chgrp (CHange GRouP) Cambia el grupo propietario de una serie de archivos/directorios chgrp grupo files El usuario que efect´a esta orden debe pertenecer al grupo mencionado. u chown (CHange OWNer) Cambia el propietario y el grupo de una serie de archivos/directorios chown user:group files La opci´n -r hace que la orden se efect´e recursivamente. o u id Muestra la identificaci´n del usuario18 , as´ como el conjunto de grupos a los que el usuario o ı pertenece. user@hostname:~$ id uid=1000(user) gid=1000(group) groups=1000(group),25(floppy),29(audio) user@hostname:~$
Un error muy frecuente es la creaci´n de un archivo de ´rdenes (script file) y olvidar permitir la ejecuci´n o o o del mismo. 18 A pesar de que el usuario se identifica por una cadena denominada username, tambi´n existe un n´mero e u denominado uid que es un identificativo num´rico de dicho usuario. e
17

16

CAP´ ITULO 1. ELEMENTOS DEL SISTEMA OPERATIVO UNIX.

1.5.8.

Filtros.

Existe un conjunto de ´rdenes en unix que permiten el procesamiento de archivos de texto. o Se denominan filtros (Unix Filters), porque normalmente se trabaja empleando redirecci´n o 19 20 recibiendo datos por su stdin y retorn´ndolos modificados por su stdout . a Para facilitar la comprensi´n de los ejemplos siguientes supondremos que existen tres o archivos llamados mylist.txt, yourlist.txt y tercero.txt que tienen en su interior: mylist.txt 1 190 2 280 3 370 yourlist.txt 1 190 2 281 3 370 tercero.txt 11 b 33 c 222 a

echo ´ Este no es propiamente un filtro, pero nos ser´ muy util m´s adelante. Despliega sobre la a ´ a pantalla un mensaje, sin argumento despliega una l´ ınea en blanco. La opci´n -n elimina el o cambio de l´ ınea al final del mensaje. user@hostname:~$ echo Hola Mundo Hola Mundo user@hostname:~$ echo ; echo chao; echo chao user@hostname:~$ Varias instrucciones pueden ser separadas por ; cat Es el filtro m´s b´sico, copia la entrada a la salida. a a user@hostname:~$ cat 1 190 2 280 3 370 user@hostname:~$ mylist.txt

Tambi´n lo podemos usar para crear un archivo e user@hostname:~$ cat Este es mi archivo con muchas lineas ^d user@hostname:~$
19 20

> myfile.txt

Entrada est´ndar. a Salida est´ndar. a

´ ´ 1.5. ORDENES BASICAS. El caracter final ^d corresponde a fin de archivo y termina el ingreso. seq Genera una secuencia de n´meros naturales consecutivos. u user@hostname:~$ seq 4 8 4 5 6 7 8

17

cut Para un archivo compuesto por columnas de datos, permite escribir sobre la salida cierto intervalo de columnas. La opci´n -b N-M permite indicar el intervalo en bytes que se escribir´n o a en la salida. user@hostname:~$ cut -b 3-4 mylist.txt 19 28 37 user@hostname:~$ paste Mezcla l´ ıneas de distintos archivos. Escribe l´ ıneas en el stdout pegando secuencialmente las l´ ıneas correspondientes de cada uno de los archivo separadas por tab. Ejemplo, supongamos que tenemos nuestros archivos mylist.txt y yourlist.txt y damos el comando user@hostname:~$ paste mylist.txt yourlist.txt 1 190 1 190 2 280 2 281 3 370 3 370 user@hostname:~$ sed Es un editor de flujo. Veamos algunos ejemplos user@hostname:~$ sed = mylist.txt 1 1 190 2 2 280 3 3 370 user@hostname:~$ Numera las l´ ıneas. user@hostname:~$ sed -n -e ’3p’ mylist.txt 3 370 user@hostname:~$

18

CAP´ ITULO 1. ELEMENTOS DEL SISTEMA OPERATIVO UNIX.

S´lo muestra la l´ o ınea 3. El modificador -n suprime la impresi´n de todas las l´ o ıneas excepto aquellas especificadas por p. El modificador -e corre un script, secuencia de comandos. Separando por coma damos un rango en el n´mero de l´ u ıneas. user@hostname:~$ sed -e ’2q’ mylist.txt 1 190 2 280 user@hostname:~$ Muestra hasta la l´ ınea 2 y luego se sale de sed. user@hostname:~$ sed -e ’s/0/a/g’ mylist.txt 1 19a 2 28a 3 37a user@hostname:~$ ´ Reemplaza todos los 0 del archivo por la letra a. Este es uno de los usos m´s comunes. a user@hostname:~$ sed -e ’/2 2/s/0/a/g’ mylist.txt 1 190 2 28a 3 370 user@hostname:~$ Busca las l´ ıneas con la secuencia 2 2 y en ellas reemplaza todos los 0 por la letra a. user@hostname:~$ sed -e ’s/1/XX/2’ mylist.txt 1 XX90 2 280 3 370 user@hostname:~$ Reemplaza la segunda aparici´n de un 1 en una l´ o ınea por los caracteres XX. A continuaci´n mostramos otras posibilidades del comando sed o Para remover una l´ ınea especifica (X) de un archivo (file.txt) user@hostname:~$ sed -e ’Xd’ file.txt Para remover un intervalo de l´ ıneas de un archivo user@hostname:~$ sed -e ’X,Yd’ file.txt Para mostrar s´lo las l´ o ıneas X e Y de un archivo

´ ´ 1.5. ORDENES BASICAS. user@hostname:~$ sed -n -e ’Xp;Yp’ file.txt Para mostrar un archivo salvo las l´ ıneas que contengan key user@hostname:~$ sed -e ’/key/d’ file.txt Para mostrar de un archivo s´lo las l´ o ıneas que contengan key user@hostname:~$ sed -n -e ’/key/p’ file.txt Para mostrar un archivo salvo las l´ ıneas que comienzan con # user@hostname:~$ sed -e ’/^#/d’ file.txt Expresiones regulares: ^ Matches al comienzo de la l´ ınea $ Matches al final de la l´ ınea, se pone despu´s del caracter a buscar. e . Matches cualquier caracter. [] Matches con todos los caracteres dentro de los par´ntesis e diff Permite comparar el contenido de dos archivos o directorios user@hostname:~$ diff mylist.txt yourlist.txt 2c2 < 2 280 --> 2 281 user@hostname:~$ Hay una diferencia entre los archivos en la segunda fila. sort Permite ordenar alfab´ticamente e user@hostname:~$ sort tercero.txt 11 b 222 a 33 c user@hostname:~$ user@hostname:~$ sort -r tercero.txt 33 c 222 a 11 b user@hostname:~$

19

20

CAP´ ITULO 1. ELEMENTOS DEL SISTEMA OPERATIVO UNIX.

user@hostname:~$ sort -n tercero.txt 11 b 33 c 222 a user@hostname:~$ user@hostname:~$ sort -k 2 tercero.txt 222 a 11 b 33 c user@hostname:~$ La opci´n -n considera los valores num´ricos y la opci´n -r invierte el orden. La opci´n -k o e o o permite especificar la columna a usar para hacer el sort. find Permite la b´squeda de un archivo en la estructura de directorios u find . -name file.dat -print Comenzando en el directorio actual(.) recorre la estructura de directorios buscando el archivo file.dat, cuando lo encuentre imprime el path al mismo, actualmente es innecesaria la opci´n print. o find . -name ’*~’ -exec rm ’{}’ \; Esta es otra aplicaci´n de find que busca en la estructura de directorios un archivo que o termine en ~ y lo borra. El comando xargs ordena repetir orden para cada argumento que se lea desde stdin. Este lo podemos combinar con find. find . -name ’*.dat’ -print | xargs mv ../data \; Logrando un comando que busca en la estructura de directorios todos los archivos que termines en .dat, y los mueve a un directorio ../data. grep Permite la b´squeda de una cadena de caracteres en uno o varios archivos, imprimiendo el u nombre del archivo y la l´ ınea en que se encuentra la cadena. user@hostname:~$ grep 1 *list.txt mylist.txt:1 190 yourlist.txt:1 190 yourlist.txt:2 281 user@hostname:~$ Algunas opciones utiles ´ -c Elimina la salida normal y s´lo cuenta el n´mero de apariciones de la cadena en o u cada archivo. -i Ignora para la comparaci´n entre la cadena dada y el archivo, si la cadena est´ en o a may´sculas o min´sculas. u u -n Incluye el n´mero de l´ u ıneas en que aparece la cadena en la salida normal.

´ ´ 1.5. ORDENES BASICAS. -r Hace la b´squeda recursiva. u

21

-v Invierte la b´squeda mostrando todas las l´ u ıneas donde no aparece la cadena pedida. head Muestra las primeras diez l´ ıneas de un archivo. head -30 file Muestra las 30 primeras l´ ıneas de file. user@hostname:~$ head -1 1 190 user@hostname:~$ mylist.txt

tail Muestra las diez ultimas l´ ´ ıneas de un archivo. tail -30 file Muestra las 30 ultimas l´ ´ ıneas de file. tail +30 file Muestra desde la l´ ınea 30 en adelante de file. user@hostname:~$ tail -1 3 370 user@hostname:~$ mylist.txt

La opci´n -f permite que se actualice la salida cuando el archivo crece. o awk Es un procesador de archivos de texto que permite la manipulaci´n de las l´ o ıneas de forma tal que tome decisiones en funci´n del contenido de la misma. Ejemplo, supongamos que tenemos o nuestro archivo mylist.txt con sus dos columnas user@hostname:~$ awk ’{print }’ 1 190 2 280 3 370 user@hostname:~$ Funciona como el comando cat user@hostname:~$ awk ’{print $2, $1 }’ 190 1 280 2 370 3 user@hostname:~$ Imprime esas dos columnas en orden inverso. user@hostname:~$ awk ’{print ‘‘a’’, 8*$1, $2-1 }’ a 8 189 a 16 279 a 24 369 user@hostname:~$ mylist.txt mylist.txt mylist.txt

22

CAP´ ITULO 1. ELEMENTOS DEL SISTEMA OPERATIVO UNIX.

Permite operar sobre las columnas. user@hostname:~$ awk ’{ if (NR>1 && NR < 3) print}’ mylist.txt 2 280 user@hostname:~$ S´lo imprime la l´ o ınea 2. tar Este comando permite la creaci´n/extracci´n de archivos contenidos en un unico archivo o o ´ denominado tarfile (o tarball). Este tarfile suele ser luego comprimido con gzip, la versi´n de compresi´n gnu,21 o bien con bzip2. o o La acci´n a realizar viene controlada por el primer argumento: o c (Create) creaci´n o x (eXtract) extracci´n o t (lisT) mostrar contenido r a˜adir al final n u (Update) a˜adir aquellos archivos que no se hallen en el tarfile o que hayan sido n modificados con posterioridad a la versi´n que aparece. o A continuaci´n se colocan algunas de las opciones: o v Verbose (indica qu´ archivos son agregados a medida que son procesados) e z Comprimir o descomprimir el contenido con gzip. j Comprimir o descomprimir el contenido con bzip2. f File: permite especificar el archivo para el tarfile. Veamos algunos ejemplos: tar cvf simul.tar *.dat Genera un archivo simul.tar que contiene todos los archivos que terminen en .dat del directorio actual. A medida que se va realizando indica el tama˜o en bloques de cada archivo n a˜adido modo verbose. n tar czvf simul.tgz *.dat Igual que en el caso anterior, pero el archivo generado simul.tgz ha sido comprimido empleando gzip. tar tvf simul.tar Muestra los archivos contenidos en el tarfile simul.tar. tar xvf simul.tar Extrae todos los archivos contenidos en el tarfile simul.tar.
gnu es un acr´nimo recursivo, significa: gnu’s Not unix! gnu es el nombre del producto de la Free o Software Foundation, una organizaci´n dedicada a la creaci´n de programas compatibles con unix algunos o o mejorado respecto a los est´ndars, y de libre distribuci´n. La distribuci´n de Linux gnu es debian. a o o
21

´ ´ 1.5. ORDENES BASICAS. wc (Word Count) Contabiliza el n´mero de l´ u ıneas, palabras y caracteres de un archivo. user@hostname:~$ wc 3 6 user@hostname:~$ mylist.txt 18 mylist.txt

23

El archivo tiene 3 l´ ıneas, 6 palabras, considerando cada n´mero como una palabra i.e. 1 es la u primera palabra y 190 la segunda, y finalmente 18 caracteres. ¿Cu´les son los 18 caracteres? a

1.5.9.

Otros usuarios y m´quinas a

users who w Para ver qui´n est´ conectado en la m´quina. e a a ping Verifica si una m´quina est´ conectada a la red y si el camino de Internet hasta la misma a a funciona correctamente. finger finger user, muestra informaci´n22 sobre el usuario user en la m´quina local. o a finger user@hostname, muestra informaci´n sobre un usuario llamado user en una m´quina o a hostname. finger @hostname, muestra los usuarios conectados de la m´quina hostname. a Este comando suele estar desabilitado en las m´quinas actuales. a

1.5.10.

Fecha

cal Muestra el calendario del mes actual. Con la opci´n -y y el a˜o presenta el calendario del o n a˜o completo. n date Muestra el d´ y la hora actual. ıa

1.5.11.

Diferencias entre sistemas.

Cuando se transfieren archivos de texto entre windows y unix sin las precauciones adecuadas pueden aparecer los siguientes problemas: En unix no existe obligatoriedad respecto a que los archivos llevan extensi´n. Incluso o pueden tener m´s de una extensi´n algo.v01.tar.gz, esto puede complicar a otros a o sistemas que usan s´lo una extensi´n de tres caracteres. o o
La informaci´n proporcionada es el nombre completo del usuario, las ultimas sesiones en dicha m´quina, o ´ a si ha le´ o no su correo y el contenido de los archivos .project y .plan del usuario. ıdo
22

24

CAP´ ITULO 1. ELEMENTOS DEL SISTEMA OPERATIVO UNIX. El cambio de l´ ınea en un archivo de texto windows se compone de Carriage Return y Line Feed. Sin embargo, en unix s´lo existe el Carriage Return. As´ un archivo de o ı unix visto desde windows parece una unica l´ ´ ınea. El caso inverso es la aparici´n del o caracter ^M al final de cada l´ ınea. Adem´s, el fin de archivo en windows es ^Z y en a unix es ^D.

Usando el comando tr se puede transformar un archivo con cambios de l´ ıneas para DOS en uno para unix. Sabiendo que ^M es ascii 13 decimal, pero 15 en octal: tr -d ’\015’ < datafile > TEMPFILE mv -f TEMPFILE datafile En Debian, instalando el paquete sysutils, queda instalado el comando dos2unix que tambi´n lo hace. e

1.6.

Shells.

El sistema operativo unix soporta varios int´rpretes de comandos o shells, que ayudan a e que la interacci´n con el sistema sea lo m´s c´moda y amigable posible. La elecci´n de cu´l o a o o a es la shell m´s c´moda es algo personal; en este punto s´lo indicaremos algunos de los m´s a o o a populares: sh : Bourne SHell, el shell b´sico, no pensado para uso interactivo. a csh : C-SHell, shell con sintaxis como el lenguaje “C”. El archivo de configuraci´n es o .cshrc (en el directorio $HOME). ksh : Korn-SHell, shell dise˜ada por David Korn en los Laboratorios AT&T Bell. Es n un intento para una shell interactiva y para uso en script. Su lenguaje de comandos es un superconjunto de el lenguaje de shell sh. tcsh : alTernative C-Shell (Tenex-CSHell), con editor de l´ ınea de comando. El archivo de configuraci´n es .tcshrc, o en caso de no existir, .cshrc (en el directorio $HOME). o bash : Bourne-Again Shell, con lo mejor de sh, ksh y tcsh. El archivo de configuraci´n o es .bash_profile cuando se entra a la cuenta por primera vez, y despu´s el archivo de e configuraci´n es .bashrc siempre en el directorio $HOME. La l´ o ınea de comando puede ser editada usando comandos (secuencias de teclas) del editor emacs. Es el shell por defecto de Linux. Si queremos cambiar de shell en un momento dado, s´lo ser´ necesario que tecleemos el o a nombre del mismo y estaremos usando dicho shell. Si queremos usar de forma permanente otro shell del que tenemos asignado por omisi´n23 podemos emplear la orden chsh que permite o realizar esta acci´n. o En los archivos de configuraci´n se encuentran las definiciones de las variables de entorno o (enviroment variables) como camino de b´squeda PATH, los aliases y otras configuraciones u personales. Veamos unos caracteres con especial significado para el Shell:
23

Por omisi´n se asigna bash. o

1.6. SHELLS.

25

‘ 24 permite que el output de un comando reemplace al nombre del comando. Por ejemplo: echo ‘pwd‘ imprime por pantalla el nombre del directorio actual. user@hostname:~$ echo ‘pwd‘ /home/user user@hostname:~$ ’ 25 preserva el significado literal de cada uno de los caracteres de la cadena que delimita. user@hostname:~$ echo ’Estoy en ‘pwd‘’ Estoy en ‘pwd‘ user@hostname:~$ ” 26 preserva el significado literal de todos los caracteres de la cadena que delimita, salvo $, ‘, \. user@hostname:~$ echo "Estoy en ‘pwd‘" Estoy en /home/user user@hostname:~$ ; permite la ejecuci´n de m´s de una orden en una sola l´ o a ınea de comando. user@hostname:~$ mkdir textos; cd textos; cp ../*.txt . ; cd .. user@hostname:~$

1.6.1.

Variables de entorno.

Las variables de entorno permiten la configuraci´n, por defecto, de muchos programas o cuando ellos buscan datos o preferencias. Se encuentran definidas en los archivos de configuraci´n anteriormente mencionados. Para referenciar a las variables se debe poner el s´ o ımbolo $ delante, por ejemplo, para mostrar el camino al directorio por defecto del usuario user: user@hostname:~$ echo $HOME /home/user user@hostname:~$ Las variables de entorno m´s importantes son: a HOME - El directorio por defecto del usuario. PATH - El camino de b´squeda, una lista de directorios separados con ‘:’ para buscar u programas.
Acento agudo o inclinado hacia atr´s, backquote. a Acento usual o inclinado hacia adelante, single quote. 26 double quote.
25 24

26

CAP´ ITULO 1. ELEMENTOS DEL SISTEMA OPERATIVO UNIX. EDITOR - El editor por defecto del usuario. DISPLAY - Bajo el sistema de X windows, el nombre de m´quina y pantalla que est´ usana a do. Si esta variable toma el valor :0 el despliegue es local. TERM - El tipo de terminal. En la mayor´ de los casos bajo el sistema X windows se ıa trata de xterm y en la consola en Linux es linux. En otros sistemas puede ser vt100. SHELL - La shell por defecto. MANPATH - Camino para buscar p´ginas de manuales. a PAGER - Programa de paginaci´n de texto (less o more). o TMPDIR - Directorio para archivos temporales.

1.6.2.

Redirecci´n. o

Cuando un programa espera que se teclee algo, aquello que el usuario teclea se conoce como el Standard Input: stdin. Los caracteres que el programa retorna por pantalla es lo que se conoce como Standard Output: stdout (o Standard Error : stderr27 ). El signo < permite que un programa reciba el stdin desde un archivo en vez de la interacci´n con el usuario. o Por ejemplo: mail root < file, invoca el comando mail con argumento (destinatario del mail) root, siendo el contenido del mensaje el contenido del archivo file en vez del texto que usualmente teclea el usuario. M´s a menudo aparece la necesidad de almacenar en un archivo a la salida de un comando. Para ello se emplea el signo >. Por ejemplo, man bash > file, invoca el comando man con argumento (informaci´n deseada) bash pero indicando que la o informaci´n debe ser almacenada en el archivo file en vez de ser mostrada por pantalla. o En otras ocasiones uno desea que la salida de un programa sea la entrada de otro. Esto se logra empleando los denominados pipes, para ello se usa el signo |. Este signo permite que el stdout de un programa sea el stdin del siguiente. Por ejemplo: zcat manual.gz | more Invoca la orden de descompresi´n de zcat y conduce el flujo de caracteres hacia el paginador o more, de forma que podamos ver p´gina a p´gina el archivo descomprimido. A parte de los a a s´ ımbolos mencionados existen otros que permiten acciones tales como: >> A˜adir el stdout al final del archivo indicado (append ).28 n >& o &> (s´lo csh, tcsh y bash) Redireccionar el stdout y stderr. Con 2> redireco cion´ s´lo el stderr. o o >>& Igual que >& pero en modo append.
27 28

Si estos mensajes son de error. En bash, si el archivo no existe, es creado.

1.6. SHELLS.

27

1.6.3.

Ejecuci´n de comandos. o

Si el comando introducido es propio del shell (built-in), se ejecuta directamente. En caso contrario: • Si el comando contiene /, el shell lo considera un PATH e intenta resolverlo (entrar en cada directorio especificado para encontrar el comando). • En caso contrario el shell busca en una tabla hash table que contiene los nombres de los comandos que se han encontrado en los directorios especificados en la variable PATH, cuando ha arrancado el shell.

1.6.4.

Aliases.

Para facilitar la entrada de algunas ´rdenes o realizar operaciones complejas, los shells o interactivos permiten el uso de aliases. La orden alias permite ver qu´ aliases hay definidos e y tambi´n definir nuevos. Es corriente definir el alias rm =‘rm -i’, de esta forma la orden e siempre pide confirmaci´n para borrar un archivo. Si alguna vez quieres usar rm sin alias, s´lo o o hace falta poner delante el s´ ımbolo \, denominado backslash . Por ejemplo \rm elimina los alias aplicados a rm. Otro ejemplo, bastante frecuente podr´ ser (debido a la complejidad de la ıa orden): alias ffind =’find . -name \!*’. Para emplearlo: ffind tema.txt, el resultado es la b´squeda recursiva a partir del directorio actual de un archivo que se llame tema.txt, u mostrando el camino hasta el mismo.

1.6.5.

La shell bash.

S´lo bash puede considerarse un shell interactivo, permitiendo la edici´n de la l´ o o ınea de comandos, y el acceso a la historia de ´rdenes (readline). En uso normal (historia y editor o de l´ ınea de comandos) bash es compatible con otras shells como tcsh y ksh, ver ap´ndice. e En bash el modo de completado (file completion) es autom´tico (usando TAB s´lo) si el shell a o est´ en modo interactivo. a Comandos del shell. help Ayuda interna sobre los comandos del shell. set Muestra el valor de todas las variables. VARIABLE=VALUE Permite asignar el valor de una variable de entorno. Para que dicha variable sea “heredada” es necesario emplear: export VARIABLE o bien combinarlas: export VARIABLE=VALUE. for var in wordlist do comandos done A la variable var, que puede llamarse de cualquier modo, se le asignan sucesivamente los

28

CAP´ ITULO 1. ELEMENTOS DEL SISTEMA OPERATIVO UNIX.

valores de la cadena wordlist, y se ejecuta el conjunto de comandos. El contenido de dicha variable puede ser empleado en los comandos: $var. Ejemplo: $ for i in 1 2 tres 4; do echo $i; done 1 2 tres 4 alias En bash, alias s´lo sirve para substituci´n simple de una cadena por otra. Por ejemplo: o o alias ls=’ls -F’. Para crear alias con argumentos se usan funciones, ver la documentaci´n. o unalias name Elimina un alias asignado. history Muestra las ultimas ´rdenes introducidas en el shell. Algunos comandos relacionados con el ´ o Command history son: !! Repite la ultima orden. ´ !n Repite la orden n-´sima. e !string Repite la orden m´s reciente que empiece por la cadena string. a !?string Repite la orden m´s reciente que contenga la cadena string. a str1∧ str2 o !!:s/str1/str2/ (substitute) Repite la ultima orden reemplanzando la primera ocurrencia de la cadena ´ str1 por la cadena str2. !!:gs/str1/str2/ (global substitute) Repite la ultima orden reemplazando todas las ocurrencias de la ´ cadena str1 por la cadena str2. !$ Es el ultimo argumento de la orden anterior que se haya tecleado. ´ source file Ejecuta las ´rdenes del fichero file en el shell actual. o umask value

´ 1.7. AYUDA Y DOCUMENTACION. Asigna la m´scara para los permisos por omisi´n. a o Los comandos umask , source , history , unalias y hash shell tcsh.

29

29

, funcionan igual en la

1.6.6.

Archivos de script.

Un archivo de script es una sucesi´n de comandos de la shell que se ejecutan secuencialo mente. Veamos un ejemplo simple: #!/bin/bash variable=’’/home/yo’’ cp $1 /tmp/$2 rm $1 cd $variable # Hecho por mi La primera l´ ınea declara la shell espec´ ıfica que se quiere usar. En la segunda l´ ınea hay una declaraci´n de una variable interna. La tercera contiene los dos primeros argumentos con que o fue llamado el script. Por ejemplo, si el anterior script est´ en un archivo llamado ejemplo, a el comando ejemplo file1 file2 asocia $1 a file1 y $2 a file2. La l´ ınea 5 hace uso de la variable interna dentro de un comando. La ultima l´ ´ ınea, que comienza con un # corresponde a un comentario. Notemos que la primera tambi´n es un comentario, pero la combinaci´n #! e o en la primera l´ ınea fuerza a que se ejecute esa shell. Esto s´lo es una m´ o ınima pincelada de una herramienta muy poderosa y util. Los comandos ´ disponibles en la shell conforman un verdadero lenguaje de programaci´n en s´ y los scripts o ı, ´ pueden dise˜arse para realizar tareas mon´tonas y complejas. Este es un tema que le ser´ util n o a´ profundizar.

1.7.

Ayuda y documentaci´n. o

Para obtener ayuda sobre comandos de unix, se puede emplear la ayuda on-line, en la forma de p´ginas de manual. As´ man comando proporciona la ayuda sobre el comando dea ı seado. Por ejemplo, para leer el manual de los shells, puedes entrar: man sh csh tcsh bash, la orden formatea las p´ginas y te permite leer los manuales en el orden pedido. En el caso a de bash se puede usar el comando help, por ejemplo, help alias. Adem´s, para muchos a comandos y programas se puede obtener informaci´n tipeando info comando. Finalmeno te, algunos comandos tienen una opci´n de ayuda (--help), para recordar r´pidamente las o a opciones m´s comunes disponibles (ls --help). a

1.8.

Procesos.

En una m´quina existen una multitud de procesos que pueden estar ejecut´ndose sia a mult´neamente. La mayor´ de ellos no corresponden a ninguna acci´n realizada por el usuaa ıa o
En bash y sh la hash table se va generando din´micamente a medida que el usuario va empleando las a o ´rdenes. As´ el arranque del shell es m´s r´pido, y el uso de orden equivalente hash -r casi nunca hace falta. ı a a
29

30

CAP´ ITULO 1. ELEMENTOS DEL SISTEMA OPERATIVO UNIX.

rio y no merecen que se les preste mayor atenci´n. Estos procesos corresponden a programas o ejecutados en el arranque del sistema y tienen que ver con el funcionamiento global del servidor. En general, los programas suelen tener uno de estos dos modos de ejecuci´n: o foreground: Son aquellos procesos que requieren de la interacci´n y/o atenci´n del o o usuario mientras se est´n ejecutando, o bien en una de sus fases de ejecuci´n (i.e. a o introducci´n de datos). As´ por ejemplo, la consulta de una p´gina de manual es un o ı a proceso que debe ejecutarse claramente en foreground. background: Son aquellos procesos que no requieren de la interacci´n con el usuario o para su ejecuci´n. Si bien el usuario desear´ estar informado cuando este proceso o ıa termine. Un ejemplo de este caso ser´ la impresi´n de un archivo. ıa o Sin embargo, esta divisi´n que a primera vista pueda parecer tan clara y concisa, a menudo o en la pr´ctica aparece la necesidad de conmutar de un modo al otro, detenci´n de tareas a o indeseadas, etc. As´ por ejemplo, puede darse el caso de que estemos leyendo una p´gina de ı a manual y de repente necesitemos ejecutar otra tarea. Un proceso viene caracterizado por: process number job number Veamos algunas de las ´rdenes m´s frecuentes para la manipulaci´n de procesos: o a o comando & Ejecuci´n de un comando en el background. o
30

Ctrl-Z Detiene el proceso que estuviera ejecut´ndose en el foreground y lo coloca a detenido en el background. Ctrl-C Termina un proceso que estaba ejecut´ndose en foreground. a Ctrl-\ Termina de forma definitiva un proceso que estaba ejecut´ndose en foreground. a ps x Lista todos los procesos que pertenezcan al usuario, incluyendo los que no est´n a asociados a un terminal. jobs Lista los procesos que se hayan ejecutado desde el shell actual, mostrando el job number. fg (job number) Pasa a ejecuci´n en foreground un proceso que se hallase en backo ground. bg (job number) Pasa a ejecuci´n en background un proceso que se hallase detenido o con Ctrl-Z. kill (process number) Env´ una se˜al31 a un proceso unix. En particular, para ıa n enviar la se˜al de t´rmino a un programa, damos el comando kill -KILL, pero no n e hace falta al ser la se˜al por defecto. n
30 31

Por omisi´n un comando se ejecuta siempre en el foreground. o Para ver las se˜ales disponibles entra la orden kill -l (l por list). n

1.9. EDITORES.

31

Cuando se intenta abandonar una sesi´n con alg´n proceso a´n detenido en el background o u u del shell, se informa de ello con un mensaje del tipo: There are stopped jobs si no importa, el usuario puede intentar abandonar de nuevo el shell y ´ste matar´ los jobs, o puedes utilizar e a fg para traerlos al foreground y ah´ terminar el mismo. ı

1.9.

Editores.

Un editor es un programa que permite crear y/o modificar un archivo. Existen una multitud de editores diferentes, y al igual que ocurre con los shells, cada usuario tiene alguno de su predilecci´n. Mencionaremos algunos de los m´s conocidos: o a vi - El editor standard de unix. emacs (xemacs) - Editor muy configurable escrito en lenguaje Lisp. Existen muchos modos para este editor (lector de mail, news, www,. . . ) que lo convierten en un verdadero shell para multitud de usuarios. Las ultimas versiones del mismo permiten la ´ ejecuci´n desde X-windows o terminal indistintamente con el mismo binario. Posee un o tutorial en l´ ınea, comando C-H t dentro del editor. El archivo de configuraci´n persoo nalizada es: $HOME/.emacs. jove - Basado en Emacs, (Jonathan’s Own Version of Emacs). Posee tutorial en una utilidad asociada: teachjove. El archivo de configuraci´n personalizada es: $HOME/.joverc. o jed - Editor configurable escrito en S-Lang. Permite la emulaci´n de editores como o emacs y Wordstar. Posee una ayuda en l´ ınea C-H C-H. El archivo de configuraci´n o personalizada es: $HOME/.jedrc. gedit - Un peque˜o y liviano editor de texto para Gnome n xjed - Versi´n de jed para el X-windows system. Presenta como ventaja que es capaz o de funcionar en muchos modos: lenguaje C, Fortran, TeX, etc., reconociendo palabras clave y signos de puntuaci´n, empleando un colorido distinto para ellos. El archivo de o configuraci´n personalizada es el mismo que el de jed. o Dado que los editores del tipo de gedit disponen de men´s auto explicativos, daremos a u continuaci´n unas ligeras nociones s´lo de vi y emacs. o o

1.9.1.

El editor vi.

El vi es un editor de texto muy poderoso pero un poco dif´ de usar. Lo importante ıcil de este editor es que se puede encontrar en cualquier sistema unix y s´lo hay unas pocas o diferencias entre un sistema y otro. Explicaremos lo b´sico solamente. Comencemos con el a comando para invocarlo: localhost:/# vi

32

CAP´ ITULO 1. ELEMENTOS DEL SISTEMA OPERATIVO UNIX.

~ ~ ~ /tmp/vi.9Xdrxi: new file: line 1 La sintaxis para editar un archivo es: localhost:/# vi nombre.de.archivo ~ ~ ~ nombre.de.archivo: new file: line 1

Insertar y borrar texto en vi. Cuando se inicia el vi, editando un archivo, o no, se entra en un modo de ´rdenes, es decir, o que no se puede empezar a escribir directamente. Si se quiere entrar en modo de inserci´n o de texto se debe presionar la tecla i. Entrando en el modo de inserci´n, se puede empezar a o escribir. Para salir del modo de inserci´n de texto y volver al modo de ´rdenes se apreta ESC. o o Aqui ya estamos escribiendo porque apretamos la tecla ’i’ al estar en modo ordenes. ~ ~

La tecla a en el modo de ´rdenes tambi´n entra en modo de inserci´n de texto, pero en o e o vez de comenzar a escribir en la posici´n del cursor, empieza un espacio despu´s. o e La tecla o en el modo de ´rdenes inserta texto pero desde la l´ o ınea que sigue a la l´ ınea donde se est´ ubicado. a Para borrar texto, hay que salir al modo ´rdenes, y presionar la tecla x que borrar´ el o a texto que se encuentre sobre el cursor. Si se quiere borrar las l´ ıneas enteras, entonces se debe presionar dos veces la tecla d sobre la l´ ınea que deseo eliminar. Si se presionan las teclas dw se borra la palabra sobre la que se est´ ubicado. a La letra R sobre una palabra se puede escribir encima de ella. Esto es una especie de modo de inserci´n de texto pero s´lo se podr´ modificar la palabra sobre la que se est´ situado. La o o a a tecla ~ cambia de may´scula a min´scula la letra sobre la que se est´ situado. u u a Moverse dentro de vi. Estando en modo ´rdenes podemos movernos por el archivo que se est´ editando usando o a las flechas hacia la izquierda, derecha, abajo o arriba. Con la tecla 0 nos movemos al comienzo de la l´ ınea y con la tecla $ nos movemos al final de la misma.

1.10. EL SISTEMA X WINDOWS.

33

Con las teclas w y b nos movemos al comienzo de la siguiente palabra o al de la palabra anterior respectivamente. Para moverme hacia la pantalla siguiente la combinaci´n de teclas o CTRL F y para volver a la pantalla anterior CTRL B. Para ir hasta el principio del archivo se presiona la tecla G. Opciones de comandos. Para entrar al men´ de comandos se debe presionar la tecla : en el modo de ´rdenes. u o Aparecer´n los dos puntos (:). Aqu´ se pueden ingresar ordenes para guardar, salir, cambiar a ı de archivo entre otras cosas. Veamos algunos ejemplos: :w Guardar los cambios. :w otherfile.txt Guardar con el nuevo nombre otherfile.txt :wq Guardar los cambios y salir. :q! Salir del archivo sin guardar los cambios. :e file1.txt Si deseo editar otro archivo al que se le pondr´ por nombre file1.txt. a :r file.txt Si se quiere insertar un archivo ya existente, por ejemplo file.txt. :r! comando Si se quiere ejecutar alg´n comando del shell y que su salida aparezca en u el archivo que se est´ editando. a

1.9.2.

Editores modo emacs.

El editor GNU Emacs, escrito por Richard Stallman de la Free Software Foundation, es uno de los que tienen mayor aceptaci´n entre los usuarios de unix, estando disponible bajo o 32 e o licencia GNU GPL para una gran cantidad de arquitecturas. Tambi´n existe otra versi´n de emacs llamada XEmacs totalmente compatible con la anterior pero presentando mejoras significativas respecto al GNU Emacs. Dentro de los “inconvenientes” que presenta es que no viene por defecto incluido en la mayor´ de los sistemas unix. Las actuales distribuciones ıa de Linux y en particular Debian GNU/Linux contienen ambas versiones de emacs, tanto GNU Emacs como XEmacs, como tambi´n versiones de jove, jed, xjed y muchos otros editores. e Para mayor informaci´n ver Ap´ndice. o e

1.10.

El sistema X Windows.

El X Windows system es el sistema est´ndar de ventanas en las estaciones de trabajo. Lo a usual actualmente es que el sistema de ventanas sea arrancado autom´ticamente cuando la a m´quina parte. En el sistema X Windows deben distinguirse dos conceptos: a
La licencia de GNU, da el permiso de libre uso de los programas con sus fuentes, pero los autores mantienen el Copyright y no es permitido distribuir los binarios sin acceso a sus fuentes. Los programas derivados de dichos fuentes heredan la licencia GNU.
32

34

CAP´ ITULO 1. ELEMENTOS DEL SISTEMA OPERATIVO UNIX. server : Es un programa que se encarga de escribir en el dispositivo de video y de capturar las entradas (por teclado, rat´n, etc.). Asimismo se encarga de mantener o los recursos y preferencias de las aplicaciones. S´lo puede existir un server para cada o pantalla. client : Es cualquier aplicaci´n que se ejecute en el sistema X Windows. No hay l´ o ımite (en principio) en el n´mero de clientes que pueden estarse ejecutando simult´neamente. u a Los clientes pueden ser locales o remotos.

Window Manager (WM) Es un cliente con “privilegios especiales”: controla el comportamiento (forma, tama˜o,. . . ) del resto de clientes. Existen varios, destacando: n icewm : Ice Window Manager, uno de los window managers gnome compatible. sawfish : Window managers gnome compatible, altamente configurable y muy integrado al gnome desktop. Metacity : Window managers gnome 2 compatible. El look and feel (o GUI) de X Windows es extremadamente configurable, y puede parecer que dos m´quinas son muy distintas, pero esto se debe al WM que se est´ usando y no a que a e las aplicaciones sean distintas. Para configurar tu sesi´n es necesario saber qu´ programas est´s usando y ver las p´ginas o e a a de manual. Los archivos principales son: .xinitrc o .xsession archivo le´ al arrancar X Windows. Aqu´ se pueden definir ıdo ı los programas que aparecen al inicio de tu sesi´n. o .fvwmrc archivo de configuraci´n del fvwm. Ver las p´ginas del manual de fvwm. o a .olwmrc archivo de configuraci´n del olwm. Ver las p´ginas del manual de olwm. o a .Xdefaults Configuraci´n general de las aplicaciones de X Windows. Aqu´ puedes o ı definir los resources que encontrar´s en los manuales de las aplicaciones de X. a En caso de que tengas que correr una aplicaci´n de X que no est´ disponible en la m´quina o e a que est´s usando, eso no representa ning´n problema. Las ´rdenes necesarias son (por ejemplo, a u o para arrancar un gnome-terminal remoto): user@hostname1:~$ ssh -XC userB@hostname2 userB@hostname2’s password: userB@hostname2:~$ gnome-terminal & Las opciones XC en el comando ssh corresponden a que exporte el DISPLAY y que comprima, respectivamente. La forma antigua

´ 1.11. USO DEL RATON. userA@hostname1:~$ xhost +hostname2 hostname2 being added to access control list user@hostname1:~$ ssh userB@hostname2 userB@hostname2’s password: userB@hostname2:~$ export DISPLAY=hostname1:0 userB@hostname2:~$ gnome-terminal &

35

Si todo est´ previamente configurado, es posible que no haga falta dar el password. a Cuando quieres salir, normalmente puedes encontrar un ´ ıcono con la opci´n Log out, en o un men´ o panel de la pantalla. u

1.11.

Uso del rat´n. o

El rat´n es un dispositivo esencial en el uso de programas X, sin embargo, la funci´n que o o realiza en cada uno de ellos no est´ normalizada. a Comentaremos la pauta seguida por la mayor´ de las aplicaciones, pero debe tenerse ıa presente que es muy frecuente encontrar aplicaciones que no las respetan.33 Bot´n izquierdo (LB): Seleccionar. Comienza el bloque de selecci´n. o o Bot´n central (MB): Pegar. Copia la selecci´n en la posici´n del cursor. o o o Bot´n derecho (RB): Habitualmente ofrece un men´ para partir aplicaciones. o u Existen dos modos para determinar cu´l es la ventana activa, aqu´lla que recibe las a e entradas de teclado: Focus Follows Mouse: La ventana que contenga al rat´n es la que es activa. No usado o por defecto actualmente. Click To Focus: La ventana seleccionada es la activa. El modo que est´ activo depende e de la configuraci´n del Window Manager. o

1.12.

Internet.

En esta secci´n denominaremos unix1 a la m´quina local (desde donde ejecutamos la o a orden) y unix2 a la m´quina remota (con la que interaccionamos). Ambos son los hostnames a de las respectivas m´quinas. Existen algunos conceptos que previamente debemos comentar: a IP-number: es un conjunto de 4 n´meros separados por puntos (p.e. 200.89.74.6) que u se asocia a cada m´quina. No puede haber dos m´quinas conectadas en la misma red a a con el mismo n´mero. u
Las aplicaciones que son conscientes de un uso anormal y est´n realizadas por programadores inteligentes, a muestran en pantalla la funci´n de cada bot´n cuando son posibles varias alternativas. o o
33

36

CAP´ ITULO 1. ELEMENTOS DEL SISTEMA OPERATIVO UNIX. hostname: es el nombre que tiene asociada la m´quina (p.e. macul). A este nombre se a le suelen a˜adir una serie de sufijos separados por puntos que constituye el denominado n dominio (p.e. macul.ciencias.uchile.cl). Una m´quina por tanto puede tener m´s a a de un nombre reconocido (se habla en este caso de alias). Se denomina resoluci´n o a la identificaci´n entre un hostname y el IP-number correspondiente. La consulta o se realiza inicialmente en el archivo /etc/hosts, donde normalmente se guardan las identificaciones de las m´quinas m´s com´nmente empleadas. En caso de que no se a a u logre se accede al servicio DNS (Domain Name Service), que permite la identificaci´n o (resoluci´n) entre un hostname y un IP-number. o mail-address: es el nombre que se emplea para enviar correo electr´nico. Este nombre o puede coincidir con el nombre de una m´quina, pero se suele definir como un alias, con a objeto de que la direcci´n no deba de cambiarse si la m´quina se estropea o se cambia o a por otra.

1.12.1.

Acceso a la red.

Existen muchos programas para la conexi´n de la red, los m´s usados son: o a telnet unix2, hace un login en la m´quina unix2, debe ingresarse el usuario y su a respectiva passwd. Adem´s, permite especificar el puerto en conexi´n en la m´quina a o a remota. ssh nombre@unix2, muy similar a telnet pero se puede especificar el usuario, si no se especifica se usa el nombre de la cuenta local. Adem´s, el passwd pasa encriptado a a trav´s de la red. ssh nombre@unix2 comando, muy similar a rsh, el passwd pasa e encriptado y ejecuta el comando en la m´quina remota, mostrando el resultado en la a m´quina local. a scp file1 usuario2@unix2:path/file, copia el archivo file1, del usuario1, que se encuentra en el directorio local en la m´quina unix1, en la cuenta del usuario2 en la a m´quina unix2 en $HOME/path/file. Si no se especifica el nombre del usuario se usa el a nombre de la cuenta local. Si se quiere copiar el archivo file2 del usuario3 en unix2 en la cuenta actual de unix1 el comando ser´ scp usuario3@unix2:file2 .. Antes ıa: de realizar cualquiera de las copias el sistema preguntar´ por el passwd del usuario en a cuesti´n en la m´quina unix2. Nuevamente, el passwd pasa encriptado a trav´s de la o a e red. talk usuario1@unix2, intenta hacer una conexi´n para hablar con el usuario1 en la o m´quina unix2. Existen varias versiones de talk en los diferentes sistemas operativos, a de forma que no siempre es posible establecer una comunicaci´n entre m´quinas con o a sistemas operativos diferentes. ftp unix2, (file transfer protocol) aplicaci´n para copiar archivos entre m´quinas de o a una red. ftp exige un nombre de cuenta y password para la m´quina remota. Algunas a de las opciones m´s empleadas (una vez establecida la conexi´n) son: a o

1.12. INTERNET.

37

• bin: Establece el modo de comunicaci´n binario. Es decir, transfiere una imagen o exacta del archivo. • asc: Establece el modo de comunicaci´n ascii. Realiza las conversiones necesarias o entre las dos m´quinas en comunicaci´n. Es el modo por defecto. a o • cd: Cambia directorio en la m´quina remota. a • lcd: Cambia directorio en la m´quina local. a • ls: Lista el directorio remoto. • !ls: Lista el directorio local. • prompt : No pide confirmaci´n para transferencia m´ltiple de archivos. o u • get rfile [lfile]: transfiere el archivo rfile de la m´quina remota a la m´quia a na local denomin´ndolo lfile. En caso de no suministrarse el segundo argumento a supone igual nombre en ambas m´quinas. a • put lfile [rfile] : transfiere el archivo lfile de la m´quina local a la m´quina a a remota denomin´ndolo rfile. En caso de no suministrarse el segundo argumento a supone igual nombre en ambas m´quinas. Tambi´n puede usarse send. a e • mget rfile : igual que get, pero con m´s de un archivo (rfile puede contener a caracteres comodines). • mput lfile : igual que put, pero con m´s de un archivo (lfile puede contener a caracteres comodines). Existen versiones mejoradas de ftp con muchas m´s posibilidades, por ejemplo, ncftp. a Tambi´n existen versiones gr´ficas de clientes ftp donde la elecci´n de archivo, el sentido e a o de la transferencia y el modo de ´sta, se elige con el mouse (p.e. wxftp). e rlogin -l nombre unix2, (remote login), hace un login a la m´quina unix2 como el a usuario nombre por defecto, sin los argumentos -l nombre rlogin usa el nombre de la cuenta local. Normalmente rlogin pide el password de la cuenta remota, pero con el uso del archivo .rhosts o /etc/hosts.equiv esto no es siempre necesario. rsh -l nombre unix2 orden, (remote shell ), ejecuta la orden en la m´quina unix2 a como usuario nombre. Es necesario que pueda entrar en la m´quina remota sin password a para ejecutar una orden remota. Sin especificar orden act´a como rlogin. u

1.12.2.

El correo electr´nico. o

El correo electr´nico (e-mail) es un servicio para el env´ de mensajes entre usuarios, o ıo tanto de la misma m´quina como de diferentes m´quinas. a a Direcciones de correo electr´nico. o Para mandar un e-mail es necesario conocer la direcci´n del destinatario. Esta direcci´n o o consta de dos campos que se combinan intercalando entre ellos el @ (at): user@domain

38

CAP´ ITULO 1. ELEMENTOS DEL SISTEMA OPERATIVO UNIX. user : es la identificaci´n del usuario (i.e. login) en la m´quina remota. o a domain : es la m´quina donde recibe correo el destinatario. A menudo, es frecuente a que si una persona tiene acceso a un conjunto de m´quinas, su direcci´n de correo no a o corresponda con una m´quina sino que corresponda a un alias que se resolver´ en un a a nombre espec´ ıfico de m´quina en forma oculta para el que env´ a ıa. Si el usuario es local, no es necesario colocar el campo domain (ni tampoco el @).

Nomenclatura. Veamos algunos conceptos relacionados con el correo electr´nico: o Subject : Es una parte de un mensaje que piden los programas al comienzo y sirve como t´ ıtulo para el mensaje. Cc (Carbon Copy) : Permite el env´ de copias del mensaje que est´ siendo editado a ıo a terceras personas. Reply : Cuando se env´ un mensaje en respuesta a otro se suele a˜adir el comienzo ıa n del subject: Re:, con objeto de orientar al destinatario sobre el tema que se responde. Es frecuente que se incluya el mensaje al que se responde para facilitar al destinatario la comprensi´n de la respuesta. o Forward : Permite reenviar un mensaje completo (con modificaciones o sin ellas) a una tercera persona. Notando que Forward env´ tambi´n los archivos adjuntos, mientras ıa e que la opci´n Reply no lo hace. o Forwarding Mail : Permite a un usuario que disponga de cuentas en varias m´quinas a 34 no relacionadas, de concentrar su correo en una cuenta unica . Para ello basta con ´ tener un archivo $HOME/.forward que contenga la direcci´n donde desea centralizar su o correo. Mail group : Un grupo de correo es un conjunto de usuarios que reciben el correo dirigido a su grupo. Existen ´rdenes para responder a un determinado correo recibido o por esa v´ de forma que el resto del grupo sepa lo que ha respondido un miembro del ıa mismo. In-Box : Es el archivo donde se almacena el correo que todav´ no ha sido le´ por el ıa ıdo usuario. Suele estar localizado en /var/spool/mail/user. Mailer-Daemon : Cuando existe un problema en la transmisi´n de un mensaje se o recibe un mensaje proveniente del Mailer-Daemon que indica el problema que se ha presentado.
Este comando debe usarse con conocimiento pues en caso contrario podr´ provocar un loop indefinido y ıa no recibir nunca correo.
34

´ 1.13. IMPRESION. Aplicaci´n mail. o

39

Es posiblemente la aplicaci´n m´s simple. Para la lectura de mail teclear simplemente: o a mail y a continuaci´n aparece un ´ o ındice con los diferentes mensajes recibidos. Cada mensaje tiene una l´ ınea de identificaci´n con n´mero. Para leer un mensaje basta teclear su n´mero y a o u u continuaci´n return. Para enviar un mensaje: mail (address) se pregunta por el Subject: o y a continuaci´n se introduce el mensaje. Para acabar se teclea s´lo un punto en una l´ o o ınea o bien Ctr-D. Por ultimo, se pregunta por Cc:. Es posible personalizar el funcionamiento me´ diante el archivo $HOME/.mailrc. Para enviar un archivo de texto a trav´s del correo se suele e emplear la redirecci´n de entrada: mail (address) < file. Si queremos enviar un archivo o binario en forma de attach en el mail, el comando es mpack archivo-binario address.

1.12.3.

Ftp anonymous.

Existen servidores que permiten el acceso por ftp a usuarios que no disponen de cuenta en dichas m´quinas. Para ello se emplea como login de entrada el usuario anonymous y como a passwd la direcci´n de e-mail personal. Existen servidores que no aceptan conexiones desde o m´quinas que no est´n declaradas correctamente en el servicio de nombre (dns), as´ como a a ı algunas que no permiten la entrada a usuarios que no se identifican correctamente. Dada la sobrecarga que existe, muchos de los servidores tienen limitado el n´mero de usuarios que u pueden acceder simult´neamente. a

1.12.4.

WWW.

WWW son las siglas de World-Wide Web. Este servicio permite el acceso a informaci´n o entrelazada (dispone de un texto donde un t´rmino puede conducir a otro texto): hyperlinks. e Los archivos est´n realizados en un lenguaje denominado html. Para acceder a este servicio a es necesario disponer de un lector de dicho lenguaje conocido como browser o navegador. Destacan actualmente: Iceweasel, Iceape, Opera, Camino (para MAC) y el simple pero muy r´pido Lynx. a

1.13.

Impresi´n. o

Cuando se quiere obtener una copia impresa de un archivo se emplea el comando lpr. lpr file - Env´ el archivo file a la cola de impresi´n por defecto. Si la cola est´ activaıa o a da, la impresora lista y ning´n trabajo por encima del enviado, nuestro trabajo ser´ procesado u a de forma autom´tica. a A menudo existen varias posibles impresoras a las que poder enviar los trabajos. Para seleccionar una impresora en concreto (en vez de la por defecto) se emplea el modificador: lpr -Pimpresora, siendo impresora el nombre l´gico asignado a esta otra impresora. Para o recibir una lista de las posibles impresoras de un sistema, as´ como su estado, se puede emı plear el comando /usr/sbin/lpc status. La lista de impresoras y su configuraci´n tambi´n o e est´ disponible en el archivo /etc/printcap. a Otras ´rdenes para la manipulaci´n de la cola de impresi´n son: o o o

40

CAP´ ITULO 1. ELEMENTOS DEL SISTEMA OPERATIVO UNIX. lpq [-Pimpresora], permite examinar el estado de una determinada cola (para ver la cantidad de trabajos sin procesar de ´sta, por ejemplo). e lprm [-Pimpresora] jobnumber, permite eliminar un trabajo de la cola de impresi´n. o

Uno de los lenguajes de impresi´n gr´fica m´s extendidos en la actualidad es PostScript. o a a La extensi´n de los archivos PostScript empleada es .ps. Un archivo PostScript puede ser o visualizado e impreso mediante los programas: gv, gnome-gv o ghostview. Por ello muchas de las impresoras actuales s´lo admiten la impresi´n en dicho formato. o o En caso de desear imprimir un archivo ascii deber´ previamente realizarse la conversi´n a o a PostScript empleando la orden a2ps: a2ps file.txt Esta orden env´ a la impresora ıa el archivo ascii file.txt formateado a 2 p´ginas por hoja. Otro programa que permite a convertir un archivo ascii en postscript es enscript. Otro tipo de archivos ampliamente difundido y que habitualmente se necesita imprimir es el conocido como Portable Document Format. Este tipo de archivo poseen una extensi´n o .pdf y pueden ser visualizados e impresos usando aplicaciones tales como: xpdf, acroread o gv.

1.14.

Compresi´n. o

A menudo necesitamos comprimir un archivo para disminuir su tama˜o, o bien crear un n respaldo (backup) de una determinada estructura de directorios. Se comentan a continuaci´n o una serie de comandos que permiten ejecutar dichas acciones. u El compresor compress est´ relativamente fuera de uso35 pero a´n podemos encontrarnos a con archivos comprimidos por ´l. e uncompress file.Z : descomprime el archivo, creando el archivo file. Destruye el archivo original. zcat file.Z : muestra por el stdout el contenido descomprimido del archivo (sin destruir el original). compress file : comprime el archivo, creando el archivo file.Z. Destruye el archivo original. Otra alternativa de compresor mucho m´s usada es gzip, el compresor de GNU que posee a una mayor raz´n de compresi´n que compress. Veamos los comandos: o o gzip file : comprime el archivo, creando el archivo file.gz. Destruye el archivo original. gunzip file.gz : descomprime el archivo, creando el archivo file. Destruye el archivo original. zless file.gz : muestra por el stdout el contenido descomprimido del archivo paginado por less.
35

Este comando no se incluye en la instalaci´n b´sica. Debemos cargar el paquete ncompress para tenerlo o a

´ 1.14. COMPRESION.

41

La extensi´n empleada en los archivos comprimidos con gzip suele ser .gz, pero a veces o se usa .gzip. Adicionalmente el programa gunzip tambi´n puede descomprimir archivos e creados con compress. La opci´n con mayor tasa de compresi´n que gzip es bzip2 y su descompresor bunzip2. o o bzip2 file : comprime el archivo, creando el archivo file.bz2. Destruye el archivo original. bunzip2 file.bz2 : descomprime el archivo, creando el archivo file. Destruye el archivo original. bzcat file.bz2 : muestra por el stdout el contenido descomprimido del archivo. Debemos usar un paginador, adicionalmente, para verlo por p´ginas. a La extensi´n usada en este caso es .bz2. El kernel de Linux se distribuye en formao to bzip2. Tambi´n existe una versi´n paralelizada llamada pbzip2. Uno de los mejores e o algoritmos de compresi´n est´ disponible para Linux en el programa p7zip. Veamos un o a ejemplo: un archivo linux-2.6.18.tar que contiene el kernel 2.6.18 de Linux que tiene un tama˜o de 230 Mb. Los resultados al comprimirlo con compress, gzip, bzip2 y 7za son: n linux-2.6.18.tar.Z 91 Mb, linux-2.6.18.tar.gz 51 Mb, linux-2.6.18.tar.bz2 40 Mb y linux-2.6.18.tar.7z 33 Mb.36 Existen tambi´n versiones de los compresores compatibles con otros sistemas operativos: e zip, unzip, unarj, lha, rar y zoo. En caso que se desee crear un archivo comprimido con una estructura de directorios debe ejecutarse la orden: tar cvzf nombre.tgz directorio o bien tar cvjf nombre.tbz directorio En el primer caso comprime con gzip y en el segundo con bzip2. Para descomprimir y restablecer la estructura de directorio almacenada se usan los comandos: tar xvzf nombre.tgz directorio si se realiz´ la compresi´n con gzip o bien o o tar xvjf nombre.tbz directorio si se realiz´ la compresi´n con bzip2. o o

Los comandos gzip y bzip2 fueron dados con la opci´n --best para lograr la mayor compresi´n. El o o comando usado para la compresi´n con 7z fue: 7za a -t7z -m0=lzma -mx=9 -mfb=64 -md=32m -ms=on o file.tar.7z file.tar, note la nueva extensi´n 7z. Para descomprimir con 7z basta 7z e file.tar.7z o

36

42

CAP´ ITULO 1. ELEMENTOS DEL SISTEMA OPERATIVO UNIX.

Cap´ ıtulo 2 Introducci´n a programaci´n. o o
versi´n 1.0, 30 de Agosto del 2007 o

En este cap´ ıtulo se intentar´ dar los elementos b´sicos de lo que es un lenguaje de proa a gramaci´n y lo que es programar. o

2.1.

¿Qu´ es programar? e

A continuaci´n, presentamos algunas alternativas de respuesta a esta pregunta: o Hacer un programa. Hacer que un computador haga una secuencia de instrucciones que uno le pide. Darle, de alguna forma, una secuencia de pasos l´gicos para que un computador los o ejecute con la intenci´n de alcanzar alg´n objetivo. o u Escribir una precisa secuencia de comandos o instrucciones, en alg´n lenguaje que el u computador entienda (a este tipo de lenguaje lo llamaremos lenguaje de programaci´n) o para que luego el computador las realice exactamente, paso a paso. Un programa es un archivo que puede ser tan corto como una sola l´ ınea de c´digo, o tan o largo como varios millones de l´ ıneas de c´digo. o

2.2.

Lenguajes de programaci´n. o

Existen diferentes tipos de lenguajes de programaci´n, algunos m´s cercanos a la m´quina o a a y menos al programador; otros m´s cercanos al programador y distantes de la m´quina. a a Realmente existe toda una jerarqu´ entre los lenguajes de programaci´n. Veamos algunos ıa o ejemplos:

2.2.1.

C´digo de M´quina binario. o a

Es el lenguaje de la CPU, y el lenguaje de m´s bajo nivel. Compuesto de 0 y 1 binario, a lo que est´ muy cerca de la m´quina pero muy lejos del programador. Una de sus grandes a a desventajas es que no es f´cil de escribir o de leer para el programador. a Un programa simple, como Hola mundo, se ver´ en c´digo binario algo as´ como: ıa o ı 43

44 10001010101010011110010 10001011010101000111010 11000101000101010000111 00101010101010010110000 11110010101010101000011 10001010010101010101001 00101010101101010101001

´ ´ CAP´ ITULO 2. INTRODUCCION A PROGRAMACION.

2.2.2.

Lenguaje de Ensamblador (Assembler).

El paso siguiente es reeplazar los 1 y 0 por una secuencia de abreviaturas del lenguaje de m´quina, este tipo de lenguaje se conoce como lenguaje de Ensamblador o Assembler. a Est´ cerca de la m´quina pero no tanto como el anterior y esta un poco m´s cerca del a a a programador. Veamos el programa Hola mundo en lenguaje de Ensamblador para la familia de procesadores X86. title Programa Hola Mundo (hello.asm) ; Este programa muestra "Hola, Mundo!" dosseg .model small .stack 100h .data hello_message db ’Hola, Mundo!’, 0dh, 0ah, ’$’ .code main proc mov ax, @ .data mov ds,ax mov ah,9 mov dx, offset hello_message int 21h mov ax,4C00h int 21h main endp end main

2.2.3.

Lenguaje de alto nivel.

Utilizan declaraciones en los programas, sentencias como palabras y expresiones algebraicas. Estos lenguajes fueron desarrollados en las d´cadas del 50 y 60. Son lenguajes que est´n e a m´s cerca del programador que de la m´quina, por lo tanto, necesitan una etapa de traduci´n a a o para que los entienda la m´quina. Este proceso se puede hacer de dos maneras: compilando a o interpretando el programa fuente. Lenguajes Compilados. En este caso, otro programa (el compilador) lee el programa fuente, un archivo en ASCII donde se encuentran el listado de instruciones y lo reescribe en un archivo binario, en lenguaje de m´quina para que la CPU pueda entenderlo. Esto se hace de una sola vez y el programa a final se guarda en esta nueva forma (un ejecutable). El ejecutable de un programa que es compilado se estima que ser´ considerablemente m´s largo que el original, programa fuente. a a

´ 2.2. LENGUAJES DE PROGRAMACION.

45

Algunos de los lenguajes compilados m´s notables son Fortran, C y C++. Un ejemplo del a programa Hola mundo escrito en C++ es dado a continuaci´n: o // // Programa Hola Mundo // #include <iostream> using namespace std; int main() { cout << "Hola mundo" << endl; return 0; }

2.2.4.

Lenguajes interpretados.

En este caso otro programa (el int´rprete) traduce las declaraciones del programa original e a lenguaje de m´quina, l´ a ınea por l´ ınea, a medida que va ejecutando el programa original. Un programa interpretado suele ser m´s peque˜o que uno compilado pero tardar´ m´s tiempo en a n a a ser ejecutado. Existe gran cantidad de este tipo de lenguajes, Python, Perl, Bash, por nombrar algunos. Un ejemplo del programa Hola mundo escrito en Python es dado a continuaci´n: o # Programa Hola mundo print "Hola Mundo"

2.2.5.

Lenguajes especializados.

Desde el punto de vista de la funcionalidad de los lenguajes podemos separarlos en lenguajes de car´cter general y lenguajes especializados. Los lenguajes de car´cter general son a a aquellos que sirven para programar una gran n´mero de problemas, por ejemplo C o C++, u Python. Los lenguajes especializados han sido dise˜ados para realizar tareas espec´ n ıficas. Ejemplos de ello son PHP y JavaScript, especializados en crear p´ginas web, o SQL, creado para a manipular informaci´n en bases de datos. o Una lista de lenguajes. A continuaci´n, damos una lista, probablemente muy incompleta, de los lenguajes de o programaci´n m´s comunes en la actualidad: o a ABC, Ada, ASP, Awk, BASIC, C, C++, C#, Caml, Cobol, c´digo de m´quina, Corba, o a Delphi, Eiffel, Erlang, Fortran, Haskell, Java, JavaScript, Lisp, Logo, Modula, Modula 2, Mozart, Mumps, Oberon, Objetive C, Oz, Pascal, Perl, PHP, Python, Realbasic, Rebol, Rexx, RPG, Ruby, Scheme, Smaltalk, SQL, Squeak, TCL, Visual Basic.

46

´ ´ CAP´ ITULO 2. INTRODUCCION A PROGRAMACION.

2.3.
2.3.1.

Lenguajes naturales y formales.
Lenguajes naturales.

Son lenguajes hablados por la gente (por ejemplo: Espa˜ol, Ingl´s, Alem´n o Japon´s). n e a e Una de sus caracteristicas es que son ambiguos, por ejemplo: “Dame esa cosa” o “¡Oh, seguro, Grande!”. En ambos ejemplos no es claro a que se est´n refiriendo y se necesita un contexto a para entenderlos. Muchas veces estos lenguajes son redundantes y est´n llenos de expresiones a idiom´ticas las cuales no deben ser tomadas literalmente, por ejemplo: “Me podr´ comer a ıa ´ una vaca”, “Me mataste”, o “Andate a la punta del cerro”.

2.3.2.

Lenguajes formales.

Hecho por el hombre, como las matem´ticas, la notaci´n en qu´ a o ımica o los lenguajes de programaci´n de computadores. Se caracterizan por ser inambiguos. Por ejemplo, una o expresi´n matem´tica: 1 + 4 = 5; o una expresi´n en qu´ o a o ımica: CH4 +2O2 → 2H2 O+CO2 ; o, finalmente, una expresi´n en lenguaje de programaci´n print "Hola mundo". Los lenguajes o o formales son adem´s concisos y estrictamente literales. a Sintaxis. Los lenguajes, tanto naturales como formales, tienen reglas de sintaxis. Por una parte, est´n los tokens, que corresponden a los elementos b´sicos (i.e. letras, palabras, s´ a a ımbolos) del lenguaje: Tokens correctos: 1+3=4; gato, H2 O. Tokens incorrectos: 2@+#=!;C;Hh O. Por otro lado, tenemos las estructuras, esto es la manera en que los tokens son organizados: Estructuras correctas: 1 + 3 = 4, gato, H2 O. Estructuras incorrectas: 13+ = 4, gtoa, 2 HO.

2.4.

Desarrollando programas.

Para desarrollar sus primeros programas parta escribiendo en sus propias palabras lo que el programa deber´ hacer. Convierta esta descripci´n en una serie de pasos en sus propias ıa o palabras. Para cada uno de los pasos propuestos traduzca sus palabras en un c´digo (Python o o C++). Dentro del c´digo incluya instrucciones que impriman los valor de las variables para o probar que el programa est´ haciendo lo que usted esperaba. a

2.5. LA INTERFAZ CON EL USUARIO.

47

2.5.

La interfaz con el usuario.

Siempre que escriba un programa debe tener presente que alguien, que puede no ser usted mismo, lo puede usar alguna vez. Lo anterior significa, en particular, que el programa debe tener documentaci´n, ya que un programa sin documentaci´n es muy dif´ de usar. Pero o o ıcil adem´s es importante cuidar la parte del programa con la que el usuario interact´a, es decir a u la interfaz con el usuario. Esta interfaz podr´ ser tanto mensajes simples de texto como soıan fisticadas ventanas gr´ficas. Lo importante es que ayuden al usuario a ejecutar correctamente a el programa. Revisemos una mala interfaz con el usuario. Tenemos un programa que no sabemos lo que hace, pero al ejecutarse resulta lo siguiente: Entre un numero 5 Entre otro numero 7 La respuesta es 12 Hay una evidente falta de instrucciones de parte del programador para el usuario, que primero no sabe para qu´ se le pide cada n´mero, y luego no sabe qu´ hizo con ellos, s´lo la respuesta, e u e o 12, sin mayor explicaci´n de lo que significa. o Como contraparte, una buena interfaz con el usuario tiene documentaci´n anexa, o bien, o alguna ayuda en el mismo programa. Esta documentaci´n debiera explicar que hace el proo grama, los datos que necesitar´ y el o los resultados que entregar´ cuando finalice. a a Cada vez que se le pide algo al usuario deber´ estar claras las siguientes preguntas: ıan ¿qu´ es exactamente lo que se supone que yo tipee?; ¿los n´meros que ingreso deben tener e u decimales?; ¿o deben ser sin decimales?; ¿en qu´ unidades de medidas debo ingresarlos?; ¿los e n´meros que se piden son grandes o son n´meros peque˜os? Si se trata de palabras, ¿debo u u n ingresarlas en min´sculas o may´sculas? u u Algunos lineamientos b´sicos que deber´ observar para construir interfaces con el usuario a ıa que sea claras son los siguientes: Parta con un t´ ıtulo e indicaciones dentro del programa. Cuando pregunte por un dato que quiere que el usuario ingrese, dele la ayuda necesaria, por ejemplo Entre el largo en metros (0-100): Que las preguntas tengan sentido. Use espacios y caracteres especiales para mantener la pantalla despejada. Ind´ ıquele al usuario que el programa termin´. o Una versi´n mejorada del programa anterior podr´ ser la siguiente: o ıa Calculo Ingrese Ingrese La suma de la suma de dos numeros un numero entero: 5 otro numero entero: 7 es 12

48

´ ´ CAP´ ITULO 2. INTRODUCCION A PROGRAMACION.

2.6.

Sacar los errores de un programa.

Los errores en un programa son llamados bugs. Al proceso de rastrear los errores y corregirlos se le conoce como debugging. Un programa especializado en hacer debugging es llamado debugger. El debugging es una de las m´s importantes habilidades en programaa ci´n. Los tres principales tipos de errores o bugs y sus consecuencias para la ejecuci´n del o o programa son: 1. Errores de sintaxis Usar un token o estructuralos en forma incorrecta El programa termina con un mensaje de error. 2. Errores de ejecuci´n (run-time error ) o Errores que ocurren durante la ejecuci´n. o El programa deja de correr abruptamente. 3. Errores l´gicos o Errores en c´mo el programa est´ l´gicamente construido. o a o El programa corre, pero hace cosas mal.

Cap´ ıtulo 3 Una breve introducci´n a Python. o
versi´n 2.1, 23 de Octubre del 2007 o

En este cap´ ıtulo se intentar´ dar los elementos m´s b´sicos del lenguaje de programaci´n a a a o Python. No se pretende m´s que satisfacer las m´ a ınimas necesidades del curso, sirviendo como un ayuda de memoria de los t´picos abordados, para futura referencia. Se debe consignar que o no se consideran todas las posibilidades del lenguaje y las explicaciones est´n reducidas al a m´ ınimo.

3.1.

Python.

El Lenguaje Python fue inventado alrededor de 1990 por el cient´ ıfico en computaci´n o holand´s Guido van Rossem y su nombre es un tributo a la grupo c´mico Monty Python del e o cual Guido es admirador. El sitio oficial del lenguage en la web es http://www.python.org.

3.1.1.

Interactivo versus scripting.

El programa Python (como programa, no como lenguaje) posee un ambiente interactivo que nos permite ejecutar instrucciones del lenguaje Python directamente. Para ello, basta dar el comando: username@host:~$ python Python 2.4.4 (#2, Apr 5 2007, 20:11:18) [GCC 4.1.2 20061115 (prerelease) (Debian 4.1.1-21)] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> El programa ofrece un prompt (>>>), esperando instrucciones del usuario. Las instrucciones son interpretadas y ejecutadas de inmediato. Esta forma de usar Python tiene la ventaja de la retroalimentaci´n inmediata; de inmediato el programador sabe si la instrucci´n o o est´ correcta o incorrecta. Sin embargo, tiene la desventaja de que el c´digo no es guardado, a o y no puede por tanto ser reutilizado. Por otra parte, cuando escribimos un archivo de instrucciones en Python (script), tenemos la ventaja de que el c´digo s´ es almacenado, pudiendo ser reutilizado. En este caso las o ı desventajas son que la retroalimentaci´n no es inmediata y que habitualmente requiere m´s o a debugging para que el c´digo funcione correctamente. o 49

50

´ CAP´ ITULO 3. UNA BREVE INTRODUCCION A PYTHON.

3.1.2.

Creando un script.

Para crear un script de Python requerimos de un editor (vi, jed, xemacs, gedit. . . elija su favorito). Para ser ordenado, gr´belo con extensi´n (supongamos que lo grabamos como a o archivo.py), para poder identificarlo r´pidamente m´s adelante. Recuerde darle los permia a sos de ejecuci´n adecuados (chmod u+x archivo.py). Para ejecutarlo basta ubicarse en el o directorio donde est´ el archivo y dar el comando a jrogan@manque:~/InProgress/python$ ./archivo.py

3.2.
3.2.1.

Lenguaje Python.
Algunos tipos b´sicos. a

Cadenas de caracteres (strings): Usualmente un conjunto de caracteres, i.e. un texto. Est´n delimitados por "comillas" simples o dobles. a N´ meros enteros: Los n´meros, que pertenecen al conjunto Z, es decir, sin decimales. u u No pueden ser mayores que un tama˜o fijo, en torno a dos billones (2 × 1012 ) en un n sistema de 32 bits usando signo ±. Cuando se dividen entre ellos s´lo dan valores o enteros. Por ejemplo: 4/3=1. N´ meros con punto flotante: Los n´meros, que pertenecen al conjunto R, es decir, u u con decimales (un n´mero finito de ellos). u Enteros largos: N´meros enteros mayores que 2 × 1012 . Los distinguimos por una L u al final del n´mero, por ejemplo: 23434235234L. u Varios de los otros tipos ser´n explicados m´s adelante en el cap´ a a ıtulo Tipo bool int long int float complex str tuple list dict file Descripci´n o booleano entero entero largos n´mero con punto flotante u n´mero complejo u string tuplas listas diccionario archivo Ejemplo True o False 117 23434235234L 1.78 0.5 +2.0j ’abc’ (1, ’hum’, 2.0) [1, ’hum’, 2.0] ’a’:7.0, 23: True file(’stuff.dat’, ’w’)

Cuadro 3.1: Los tipos del lenguaje Python.

3.2. LENGUAJE PYTHON. Trabajando con n´ meros. u

51

Use el tipo de n´mero en el cual quiere obtener su resultado. Es decir, si usted desea un u valor con decimales, use al menos un n´mero con decimales en el c´lculo. Por ejemplo: 15/2.0 u a producir´ 7.5 y 15/2 producir´ 7, porque son ambos enteros. Si desea enteros largos, use al a a menos un entero largo en su expresi´n, por ejemplo: 23434235234L/2. o N´ mero complejos. u Los n´meros complejos son tambi´n soportados en Python. Los n´meros imaginarios puros u e u son escritos con un sufijo j o J. Los n´meros complejos con parte real no nula son escritos u como real +imagj, o pueden ser creados con la funci´n complex(real,imag). Ejemplos o >>> 1j*1J (-1+0j) >>> 1j*complex(0,1) (-1+0j) >>> 3+1j*3 (3+3j) >>> (1+2j)/(1+1j) (1.5+0.5j) >>> a=1.5+0.5j >>> a.real 1.5 >>> a.imag 0.5 Cadenas de caracteres (strings). Una cadena de caracteres debe estar entre ap´strofes o comillas simples o dobles. Por o ejemplo: nombre = "Este es tu nombre" nombre2= ‘Este es tambien su nombre’ Si una cadena de caracteres necesita un ap´strofe dentro de ella, anteponga un \ al o ap´strofe extra. Ejemplos: o titulo = "Ella dijo: \"Te amo\"" titulo2 = ‘I\’m a boy’ Algunas cadenas de caracteres con significado especial empiezan con el caracter \ (String Backslash Characters). \\ = Incluya \. \’ = Ap´strofe simple. o

52

´ CAP´ ITULO 3. UNA BREVE INTRODUCCION A PYTHON. \" = Ap´strofe doble. o \n = L´ ınea nueva.

3.2.2.

Imprimiendo en la misma l´ ınea.

Agregando una coma (,) al final de una instrucci´n print har´ que el pr´ximo comando o a o print aparezca en la misma l´ ınea. Ejemplo print num1,"+", num2, "=", print respuesta

3.2.3.

Imprimiendo un texto de varias l´ ıneas.

Si queremos imprimir un texto que tenga varias l´ ıneas podemos usar dos formas distintas de la funci´n print usando el caracter \n o bien usando un texto entre triple comilla o >>> print "primera linea\nsegunda linea" primera linea segunda linea >>> print """primera linea ... segunda linea""" primera linea segunda linea

3.2.4.

Variables.

Las variable son un nombre, usado dentro del programa, para referirse a un objeto o valor. Las limitaciones y consideraciones que hay que tener en cuenta para darle nombre a una variable son: No puede ser una palabra reservada del lenguaje (i.e. print, and, or, not). No puede comenzar por un n´mero. u Las may´sculas y las min´sculas son diferentes. u u No puede incluir caracteres ilegales (i.e. $,%,+,=). Cree variables cuyos nombres signifiquen algo: MAL : diy=365 BIEN: days_in_year=365

3.2. LENGUAJE PYTHON.

53

3.2.5.

Asignaci´n de variables. o

Para asignarle un valor a una variable, digamos num, basta poner el nombre de la variable a la izquierda un signo igual y al lado derecho el valor o expresi´n que queremos asignarle o num=8.0 num=pi*3.0**2 Un mismo valor puede ser asignado a varias variables simultaneamente >>> x=y=z=0 # Todas las variables valen cero >>> print x,y,z 0 0 0 O bien podemos hacer asignasiones diferentes valores a diferentes variables en una misma asignaci´n o >>> >>> 0 1 >>> >>> 1 1 >>> >>> 0 1 a,b=0,1 print a,b a,b=b,a+b print a,b a,b,c=0,1,2 print a,b,c 2

3.2.6.

Reciclando variables.

Una vez que una variable es creada su valor puede ser reasignado. Veamos un ejemplo donde la variable card_value es reutilizada card_value=card1+card2 print card_value card_value=card1+card2+card3 print card_value

3.2.7.

Operaciones matem´ticas. a

Con Python podemos realizar las operaciones b´sicas: suma (+), resta (−), multiplicaci´n a o (∗) y divisi´n (/). Operaciones menos b´sicas tambi´n est´n disponibles: el exponente (∗∗), o a e a el m´dulo ( %). o Entre las operaciones hay un orden de precedencia, unas se realizar´n primero que otras. a A continuaci´n damos el orden de precedencia, partiendo por lo que se hace primero: o Par´ntesis, exponentes, multiplicaci´n y divisi´n, e o o Suma y resta.

54

´ CAP´ ITULO 3. UNA BREVE INTRODUCCION A PYTHON. De izquierda a derecha.

Como ejemplo de la importancia de saber el orden de precedencia veamos los siguiente ejemplos: 2 ∗ (3 − 1) = 4 y 2∗3−1=5

3.2.8.

Operaciones con strings.

Dos de las operaciones m´s comunes con strings: a Concatenaci´n: se pueden concatenar dos strings al sumarlos, veamos un ejemplo: o >>> >>> >>> >>> x = "Hola" y = "Mundo" print x+y HolaMundo

Repetici´n: o >>> z = "Ja" >>> print z*3 >>> JaJaJa

3.2.9.

Composici´n. o

Se pueden combinar sentencias simples en una compuesta, a trav´s del operador ”,”: e >>> x = "Elizabeth" >>> print "Tu nombre es : ",x >>> Tu nombre es : Elizabeth En el ejemplo, x fue asignado expl´ ıcitamente a una variable, pero naturalmente cualquier tipo de asignaci´n es posible, por ejemplo: o >>> promedio=(nota+extra_creditos)/posibles >>> print "Tu promedio es : ",promedio

3.2.10.

Comentarios.

Los comentarios son anotaciones que usted escribe para ayudar a explicar lo que est´ haa ciendo en el programa. Los comentarios comienzan con #. Lo escrito despu´s de #, hasta el e final de la l´ ınea, es ignorado por el int´rprete. Por ejemplo: e dias = 60 #disponibles para el proyecto Naturalmente, los comentarios no son muy utiles cuando se trabaja interactivamente ´ con Python, pero s´ lo son cuando se escribe un script. De este modo se pueden insertar ı explicaciones en el c´digo que ayuden a recordar qu´ hace el programa en cada una de sus o e secciones, o explicarlo a terceros. Es buena costumbre de programaci´n que las primeras o l´ ıneas de un c´digo sean comentarios que incluyan el nombre del programador y una breve o descripci´n del programa. o

3.3. CONDICIONALES.

55

3.2.11.

Entrada (input).

Para leer strings del stdin use la instrucci´n raw_input(), por ejemplo o nombre = raw_input("Cual es tu nombre?") Si necesita leer n´meros del stdin use la instrucci´n input(): u o numero=input("Cuantos?") En ambos casos, el mensaje entre comillas dentro de los par´ntesis es opcional, sin embare go, aclara al usuario lo que el programa le est´ solicitando. En el siguiente par de ejemplos, el a programa solicita informaci´n al usuario, salvo que en el primero, el programa queda esperano do una respuesta del usuario, quien, a menos que sepa de antemano qu´ quiere el programa, e no tiene modo de saber por qu´ le programa no se contin´a ejecutando. e u Ejemplo sin mensaje (queda esperando para siempre una respuesta): >>> nombre = raw_input() Ejemplo con mensaje: >>> nombre = raw_input("Cual es tu nombre?") Cual es tu nombre? Pedro >>>

3.3.

Condicionales.

Los condicionales son expresiones que puede ser ciertas o falsas. Por ejemplo, ¿el usuario tipe´ la palabra correcta? o ¿El n´mero es mayor que 10? El resultado de la condici´n decide o u o que suceder´, por ejemplo, a todos los n´meros mayores que 100 r´stele 20, cuando la palabra a u e ingresada sea la correcta, imprima “¡Bien”

3.3.1.

Posibles condicionales.

x == y x es igual a y. x != y x no es igual a y. x >y x es mayor que y. x <y x es menor que y. x >= y x es mayor igual a y.

56 x <= y x es menor igual a y.

´ CAP´ ITULO 3. UNA BREVE INTRODUCCION A PYTHON.

A continuaci´n, algunos ejemplos de los anteriores condicionales: o x == 125: passwd == "nix": num >= 0: letter >"L": num/2 == (num1-num): num %5 != 0:

3.3.2.

El if.

A continuaci´n, estudiemos la instrucci´n if, partamos de la forma general de la instruco o ci´n: o if condition: statements Primero la palabra clave if, luego la condici´n condition, que puede ser algo como x<y o o x==y, etc. La l´ ınea termina con : requerido por la sintaxis del if. En las l´ ıneas siguientes statements, viene las instrucciones a seguir si la condici´n es cierta. Estas instrucciones o deben ir con sangr´ (indent). ıa Un ejemplo de una construcci´n if simple. o num = input("Entre su edad") if num >= 30: old-person(num) print print "Gracias"

3.3.3.

El if. . . else.

La forma general de la construcci´n if...else a continuaci´n: o o if condition: statements_1 else: statements_2 El else debe de estar despu´s de una prueba condicional. S´lo se ejecutar´ cuando condie o a ci´n evaluada en el if sea falsa. Use esta construcci´n cuando tenga dos conjuntos diferentes o o de instrucciones a realizar dependiendo de la condici´n. Un ejemplo o

3.3. CONDICIONALES. if x%2 == 0: print "el numero es par" else: print "el numero es impar"

57

3.3.4.

El if...elif...else.

La forma general de la construcci´n if...elif...else, a continuaci´n: o o if condition_1: statements_1 elif condition_2: statements_2 else: statements_3 Para m´s de dos opciones use la construcci´n con elif. elif es la forma acortada de las a o palabras else if. Las instrucciones asociadas a la opci´n else se ejecutar´n si todas las otras o a fallan. Un ejemplo concreto if x<0 : print x," elif x==0 : print x," elif x>0 : print x," else: print x," es negativo" es cero" es positivo" Error, no es un numero"

3.3.5.

La palabra clave pass.

El comando pass no realiza acci´n alguna, es decir, no hace nada. Un ejemplo o if x<0: HagaAlgo() else: pass

3.3.6.

Operadores l´gicos. o

Los condicionales pueden ser unidos usando las palabras reservadas and, or o not. Si ocupamos un and para unir dos condiciones l´gicas tenemos que ambas condiciones deben o satisfacerse para que el condicional sea cierto. En el caso de ocupar or para unir dos condiciones l´gicas una de ellas debe ser satisfecha para que el condicional sea cierto. Finalmente o el not se antepone a una condici´n y la niega, es decir, ser´ cierto si la condici´n no es o a o satisfecha. En todos los caso se aplica que falso == 0 y cierto == 1 (en realidad cierto ! = 0). A continuaci´n, algunos ejemplos de operadores l´gicos: o o

58 if x>0 and x<10: if y>0 and x>0: if pwd=="code" if y>0 or x<0: if not(x<y):

´ CAP´ ITULO 3. UNA BREVE INTRODUCCION A PYTHON.

or pwd=="monster":

if x>y or not(x<0):

3.3.7.

Forma alternativa.

Cuando pruebe valores para < o >, estas pruebas pueden ser escritas como un s´lo condio cional sin usar el and. Veamos ejemplos if 0<x<100: if 1000>=x >=0:

3.4.

Funciones Pre-hechas.

Una funci´n define un conjunto de instrucciones. Es un conjunto de c´digo que puede ser o o usado una y otra vez. Puede ser creado por usted o importado desde alg´n m´dulo. Ejemplos u o de funciones: De c´lculo matem´tico a a log, sen, cos, tan, exp, hypot. Funciones que generan n´meros al azar, funciones de ingreso, funciones que hacen u cambios sobre un string. C´digo hecho por el usuario que puede ser reciclado. o Hay un grupo de funciones que vienen hechas, es decir, listas para usar. Para encontrar qu´ funciones est´n disponibles tenemos la documentaci´n del Python y un sitio web e a o http://www.python.org/doc/current/modindex.html Estas funciones pre-hechas vienen en grupos llamados m´dulos. Para importar en nuestro o c´digo el m´dulo apropiado, que contiene la funci´n que nos interesa, usamos el comando o o o import modulo name Una vez importado el m´dulo, cuando queremos llamar a la funci´n para usarla, debemos o o dar el comando modulo name.function(arguments)

3.4. FUNCIONES PRE-HECHAS. Veamos un ejemplo com la funci´n hypot del m´dulo matem´tico o o a import math math.hypot(8,9)

59

Si analizamos las l´ ıneas anteriores de c´digo debemos decir que el m´dulo que contiene las o o funciones matem´ticas se llama math y ´ste incluye la funci´n hypot que devuelve el largo a e o de la hipotenusa. El s´ ımbolo . separa el nombre del m´dulo del de la funci´n. Por supuesto o o hypot es el nombre de la funci´n y () es el lugar para los argumentos. Una funci´n podr´ o o ıa no tener argumentos, pero a´n as´ deben ir los par´ntesis, son obligatorios. Los n´meros 8,9 u ı e u son enviados a la funci´n para que los procese. En el ejemplo, estos n´meros corresponden a o u los dos catetos de un tri´ngulo rect´ngulo. a a En las secciones anteriores vimos funciones especializadas en el ingreso de strings y de n´meros. Nos referimos a input() para n´meros y a raw input() para strings. En este caso, u u input e raw input corresponden al nombre de las funciones, y entre los par´ntesis se acepta e un string como argumento, el cual es desplegado como prompt cuando se da el comando. Como vimos, este argumento es opcional en ambas funciones, sin embargo, lo incluyan o no, siempre se deben poner los par´ntesis. e a Funciones como input() y raw input() est´n incorporadas al lenguaje y no necesitamos importar ning´n m´dulo para usarlas. u o

3.4.1.

Algunas funciones incorporadas.

float(obj) Convierte un string u otro n´mero a un n´mero de punto flotante. Con u u decimales. int(obj) Convierte un string u otro n´mero a un n´mero entero. Sin decimales. u u long(obj) Convierte un string u otro n´mero a un n´mero entero largo. Sin decimales. u u str(num) Convierte un n´mero a un string. u divmod(x,y) Devuelve los resultados de x/y y x %y. len(s) Retorna el largo de un string u otro tipo de dato (una lista o diccionario). pow(x,y) Retorna x a la potencia y. range(start,stop,step) Retorna un conjunto de n´meros desde start hasta stop, u con un paso igual a step. round(x,n) Retorna el valor del punto flotante x redondeado a n digitos despu´s del e punto decimal. Si n es omitido el valor por defecto es cero.

60

´ CAP´ ITULO 3. UNA BREVE INTRODUCCION A PYTHON.

3.4.2.

Algunas funciones del m´dulo math. o

acos(x), asin(x), atan(x) El arcocoseno, el arcoseno y la arcotangente de un n´meu ro. cos(x), sin(x), tan(x) El coseno, el seno y la tangente de un n´mero. u log(x), log10(x) El logaritmo natural y el logaritmo en base 10 de un n´mero. u pow(x,y) Retorna x a la potencia y. hypot(x,y) Retorna el largo de la hipotenusa de un tri´ngulo rect´ngulo de catetos x a a e y.

3.4.3.

Algunas funciones del m´dulo string. o

capitalize(string) Pone en may´scula la primera letra de la primera palabra. u capwords(string) Pone en may´scula la primera letra de todas las palabras. u lower(string) Todas las letras en min´sculas. u upper(string) Todas las letras en may´sculas. u replace(string,old,new) reemplaza todas las palabras old en string por las palabras new. center(string, width) Centra el string en un campo de un ancho dado por width. rjust(string, width) Justifica a la derecha el string en un campo de un ancho dado por width. ljust(string, width) Justifica a la izquierda el string en un campo de un ancho dado por width.

3.4.4.

Algunas funciones del m´dulo random. o

randrange(start, stop, step) Da un n´mero al azar entre el n´mero start y el u u n´mero stop. El n´mero step es opcional. u u choice(sequence) Elige al azar un objeto que pertenece a la sequencia sequence (una lista). Por ejemplo sequence=["a", "b", "c", "d", "e"].

3.4.5.

Algunos otros m´dulos y funciones. o

Una funci´n del m´dulo time: o o sleep(x) El computador queda en pausa por x segundos. Un par de funciones del m´dulo calendar: o

3.5. FUNCIONES HECHAS EN CASA. prcal(year) Imprime un calendario para el a˜o year. n prmoth(year, month) Imprime un calendario para el mes month del a˜o year. n

61

3.5.

Funciones hechas en casa.

Una funci´n define un conjunto de instrucciones. A menudo son almacenadas en conjuntos o llamados m´dulos. Pueden o no necesitar argumentos. Pueden o no retornar un valor al o programa.

3.5.1.

Receta para una funci´n. o

Para crear una funci´n primero hay que definir la funci´n, darle un nombre y escribir el o o conjunto de instrucciones que la constituyen. La funci´n realizar´ las instrucciones cuando o a es llamada. Despu´s, en el programa, llame la funci´n que ya defini´. A continuaci´n veamos e o o o la definici´n formal de una funci´n hecha por nosotros o o def nombre(argumentos): comandos Comenzamos con la palabra def, la cual es un palabra requerida. Debe ir en min´sculas. u Luego nombre es el nombre que uno le da a la funci´n. Despu´s vienes los argumentos o e (argumentos) que corresponden a las variables que se le pasan a la funci´n para que las o utilice. Finalmente, :, requeridos al final de la l´ ınea que define una funci´n. El bloque de o commandos asociados a la funci´n deben tener sangr´ para identificarlos como parte de la o ıa misma. A continuaci´n, un ejemplo concreto: o # Definiendo la funcion def mi_function(): print "Nos gusta mucho la Fisica" # Usando la funcion mi_function() La definici´n de una funci´n puede ser en cualquier parte del programa con la salvedad o o que debe ser antes de que la funci´n misma sea llamada. Una vez definida la funci´n ellas se o o ejecutar´n cuando sean llamadas. Cuando enviamos valores a nuestras funciones se crean las a variables nombradas en la definici´n. Por ejemplo: o def mi_function(nombre1, nombre2): print nombre1+nombre2 Los nombres de las variables s´lo ser´n v´lidos dentro de la funci´n (es decir, las variables o a a o son locales). Las funciones usan variables locales.

62

´ CAP´ ITULO 3. UNA BREVE INTRODUCCION A PYTHON.

3.5.2.

Variables globales.

Si desea asignar una variable definida fuera de la funci´n en la funci´n, tiene que utilizar o o la sentencia global. Esta se emplea para declarar que la variable es global es decir que no es local. Puede utilizar los valores de las variables definidas fuera de la funci´n (y no hay variables o con el mismo nombre dentro de la misma). Sin embargo, esto es inapropiado y debe ser evitado puesto que llega a ser confuso al lector del programa, en cuanto a donde se ha realizado dicha definici´n de variables. Usando la sentencia global queda claro que la variable se define en o un bloque externo. #!/usr/bin/python def func(): global x print ’x es’, x x = 2 print ’x cambiada a’, x #main x = 50 func() print ’El valor de x es’, x La salida del programa x es 50 Cambiada a 2 El valor de x es 2

3.5.3.

Pasando valores a la funci´n. o

Para enviar los valores a nuestra funci´n ponga los valores en la llamada de la funci´n. El o o tipo de los valores debe estar de acuerdo con lo que la funci´n espera. Las funciones pueden o tomar variables u otras funciones como argumentos. Veamos un ejemplo: def mi_function(nombre1, nombre2): print nombre1,nombre2 mi_function("azul","rojo")

3.5.4.

Valores por defecto de una funci´n. o

En algunas funciones, se puede hacer que el uso de algunos par´metros sean opcionales a y usar valores predeterminados si el usuario no desea proporcionarlos (los valores de dichos par´metros). Esto se hace con la ayuda de valores pre-definidos. Puedes especificar los valores a por defecto despu´s del nombre del par´metro en la definici´n de la funci´n con el operador e a o o de asignaci´n (=) seguido por el argumento a definir. o

3.6. ARGUMENTOS CLAVES. #!/usr/bin/python def say(s, times = 1): print s * times say(’Hola’) say(’Mundo’, 5) Salida del programa Hola MundoMundoMundoMundoMundo

63

Solamente los par´metros que est´n en el extremo de la lista de par´metros pueden tener a a a valores por defecto; es decir, no puedes tener un par´metro con un valor por defecto antes a de uno sin un valor, en el orden de los par´metros declarados, en la lista del par´metro de la a a funci´n. Esto se debe a que los valores son asignados a los par´metros por la posici´n. Por o a o ejemplo def func(a, b=5) es v´lido, pero def func(a=5, b) no lo es a

3.6.

Argumentos Claves.

Si se tiene funciones con muchos par´metros y se quiere especificar solamente algunos de a ellos, entonces se puede asignar los valores para tales par´metros con solo nombrarlos, a esto a se denomina argumentos claves. Utilizamos el nombre en vez de la posici´n que se ha estado o utilizando. Esto tiene dos ventajas: la primera, es que usar la funci´n es m´s f´cil puesto que o a a no se necesita preocuparnos del orden de los argumentos. La segunda, es que podemos dar valores solamente a los par´metros que deseamos, a condici´n de que los otros tengan valores a o por defecto. Usando Argumentos Claves #!/usr/bin/python def func(a, b=5, c=10): print ’a es’, a, ’y b es’, b, ’y c es’, c func(3, 7) func(25, c=24) func(c=50, a=100) La salida es: a es 3 y b es 7 y c es 10 a es 25 y b es 5 y c es 24 a es 100 y b es 5 y c es 50

64

´ CAP´ ITULO 3. UNA BREVE INTRODUCCION A PYTHON.

3.7.

DocStrings.

Python tiene una caracter´ ıstica interesante llamada cadenas de documentaci´n que geo neralmente son llamadas por su nombre corto: docstrings. DocStrings es una herramienta importante de la que se puede hacer uso puesto que ayuda a documentar mejor el programa. Podemos incluso ubicar docstring en una funci´n a tiempo de ejecuci´n, es decir cuando el o o programa est´ funcionando. Usando DocStrings a #!/usr/bin/python def printMax(x, y): ’’’Imprime el maximo de 2 numeros. Los dos valores deben ser enteros. Si hubieran decimales, son convertidos a enteros.’’’ x = int(x) # Convierte a enteros, si es posible y = int(y) if x > y: print x, ’es maximo’ else: print y, ’es maximo’ printMax(3, 5) print printMax.__doc__ La salida 5 es maximo Imprime el maximo de 2 numeros. Los dos valores deben ser enteros. Si hubieran decimales, son convertidos a enteros.

3.7.1.

La palabra clave return.

El comando return termina la ejecuci´n de una funci´n. Un ejemplo o o import math def raiz(num): if num<0: print "Ingrese un numero positivo" return print math.sqrt(num)

3.7. DOCSTRINGS.

65

Los condicionales como el if son especialmente util para atrapar y manejar errores. Use ´ el else para atrapar el error cuando la condici´n no es satisfecha. o Los if pueden ser anidados. Sea cuidadoso, ya que la anidaci´n puede producir confusi´n o o y deber´ ser usada con moderaci´n y mesura. ıa o

3.7.2.

Funciones que tienen un valor de retorno.

Podemos crear funciones que retornen un valor al programa que las llam´. Por ejemplo o def sumalos(x,y): new = x+y return new # Llamada a la funcion sum = sumalos(5,6)

3.7.3.

Recursi´n. o

Se llama recursi´n cuando una funci´n se llama a si misma. La recursi´n permite repetir o o o el uso de una funci´n incluso dentro de la misma funci´n. Un ejemplo es o o def count(x): x=x+1 print x count(x) Si la funci´n nunca para, esta recursi´n es llamada recursi´n infinita. Para prevenir este o o o situaci´n creamos un caso base. El caso base es la condici´n que causar´ que la funci´n pare o o a o de llamarse a si misma. Un ejemplo def count(x): if x<100: x=x+1 print x count(x) else: return time.sleep(1) Un programa que calcula el factorial de un n´mero en forma recursiva u #!/usr/bin/env python def fact(n): if n<2: return 1 else:

66

´ CAP´ ITULO 3. UNA BREVE INTRODUCCION A PYTHON. return n*fact(n-1)

#main i=input("Ingrese un natural :") print "El factorial de",i," es ",fact(i)

3.8.

Par´metros desde la l´ a ınea de comando.

Python puede recibir par´metros directamente de la l´ a ınea de comando. La lista sys.argv los contiene. Supongamos que el programa se llama main.py y es como sigue: #!/usr/bin/python import sys for i in sys.argv: print i print sys.argv[0] Si ejecutamos el programa con la l´ ınea de comando jrogan@huelen:~$ ./main.py h -l --mas xvzf La salida ser´ a ./main.py h -l --mas xvzf ./main.py Otro ejemplo, un programa que suma dos n´meros desde la l´ u ınea de comando, #!/usr/bin/python import sys if len(sys.argv)>2): n1=float(sys.argv[1]) n2=float(sys.argv[2]) print n1+n2 else: pass Si ejecutamos el programa con la l´ ınea de comando jrogan@huelen:~$ suma.py 1.2 3.5 La salida ser´ a 4.7 Si se llama el programa con menos argumentos, el programa no har´ nada. a

3.9. ITERACIONES CON WHILE.

67

3.9.

Iteraciones con while.

La palabra reservada while puede ser usada para crear una iteraci´n. La instrucci´n o o while necesita un contador que se incremente. Ejemplo while x < 10: print x x = x+1 Para hacer una secci´n de c´digo reusable, en vez de usar valores contantes use variables. o o Primero un ejemplo no generalizado while x < 12: print 2*x x = x+1 Ahora el mismo ejemplo generalizado while x < max_num: print num*x x = x+1 Utilicemos la instrucci´n while para hacer una salida ordenada para un programa. El o c´digo de escape del tabulador (\t) en un string permite hacer tabulaciones. Los tabuladores o mantienen los items alineados dando una salida ordenada. Ejemplo, en este caso combinando la instrucci´n while y el c´digo de escape del tabulador haremos una tabla: o o while x < 10: print item1, "\t", item2 x = x+1

3.10.

Los strings.

Los strings son hechos de peque˜as unidades, cada caracter individual. Cada uno de los n caracteres tiene una direcci´n num´rica dentro del string, donde el primer caracter tiene la o e direcci´n cero (0). Cada caracter individual, o conjunto de caracteres, en un string puede ser o acccesado usando sus direcciones num´ricas. Use [ ] para accesar caracteres dentro de un e string. Veamos un ejemplo palabra = "computador" letra = palabra[0] Para acceder un conjunto de caracteres dentro de un string lo podemos hacer como sigue: Use [#:#] para obtener un conjunto de letras. parte = palabra[1:3] Para tomar desde el comienzo a un punto dado en el string. parte = palabra[:4] Para tomar desde un punto dado al final del string. parte = palabra[3:]

68

´ CAP´ ITULO 3. UNA BREVE INTRODUCCION A PYTHON.

3.10.1.

´ Indice negativos.

Veamos que pasa cuando usamos ´ ındices negativos >>> a="hola" >>> a[0] ’h’ >>> a[-1] ’a’ >>> a[-2] ’l’ >>> a[-3] ’o’ >>> a[-4] ’h’ >>> a[-5] Traceback (most recent call last): File "<stdin>", line 1, in ? IndexError: string index out of range

3.10.2.

¿Cu´n largo es un string ? a

Para encontrar cu´ntos caracteres tiene un string usamos la funci´n len(string). La a o funci´n len requiere un string como argumento. Un ejemplo: o palabra = "computador" largo = len(palabra)

3.10.3.

Recorriendo un string.

Uno puede desear hacer una prueba sobre cada una de las letras que componen el string todas de una vez. Hay dos maneras de hacer esto usando una instrucci´n while o una o instrucci´n for para realizar el ciclo o loop. Primero veamos el ciclo con while: o palabra = "computador" indice = 0 while indice < len(palabra): letra = palabra[indice] print letra indice=indice +1

3.10.4.

El ciclo for.

Una manera m´s compacta de escribir el ciclo while anterior es usando un ciclo for, a veamos c´mo queda el c´digo o o

3.11. LISTAS. palabra = "computador" for letra in palabra: print letra

69

Notemos que hemos creado la variable letra cuando creamos el ciclo for. A continuaci´n, o un ejemplo m´s completo del ciclo for: a #!/usr/bin/env python # -*- coding: iso-8859-1 -*# Programa que cuenta vocales import string palabra = raw_input("Entre una palabra : ") palabra_min = string.lower(palabra) vocales="aeiou´´´´´" aeıou contador = 0 for letra in palabra_min: if letra in vocales: contador=contador +1 else: pass print "El n´mero de vocales en la palabra que ingres´ fueron : ", contador u o Notemos la segunda l´ ınea de este programa que nos permite ingresar e imprimir strings con caracteres acentuados y caracteres especiales.

3.10.5.

Comparando strings.

Los strings pueden ser usados en comparaciones. Ejemplo if palabra < "cebu": print palabra De acuerdo a Python, todas las letras may´sculas son mayores que las letras min´sculas. u u As´ a>Z. ı Una buena idea es convertir todos los strings a may´scula o min´scula, seg´n sea el caso, u u u antes de hacer comparaciones. Recordemos que el m´dulo string contiene varias funciones o utiles incluyendo: lower(string), upper(string) y replace(string,string,string). Re´ vise la documentaci´n. o

3.11.

Listas.

Una lista es un conjunto ordenado de elementos. Las listas est´n encerradas entre par´ntea e sis [ ]. Cada item en una lista est´ separado por una coma. Veamos ejemplos de listas a

70

´ CAP´ ITULO 3. UNA BREVE INTRODUCCION A PYTHON.

mascotas = ["perros", "gatos", "canarios", "elefantes"] numeros = [1,2,3,4,5,6] cosas = [ 1, 15, "gorila", 23.9, "alfabeto"] Un elemento de una lista puede ser otra lista. Una lista dentro de otra lista es llamada lista anidada. A continuaci´n un ejemplo de listas anidadas o para_hacer = ["limpiar", ["comida perro", "comida gato","comida pez"], "cena"]

3.11.1.

Rebanando listas.

Una lista puede ser accesada al igual que un string usando el operador [ ]. Ejemplo >>> lista=["Pedro", "Andres", "Jaime", "Juan"] >>> print lista[0] Pedro >>> print lista[1:] [’Andres’, ’Jaime’, ’Juan’] Para accesar un item en una lista anidada hay que proveer dos ´ ındices. Ejemplo >>> lista_palabras = ["perro", ["fluffy", "mancha", "toto"], "gato"] >>> print lista_palabras[1][2] toto

3.11.2.

Mutabilidad.

A diferencia de los strings las listas son mutables, lo que significa que se pueden cambiar. Ejemplo >>> string = "perro" >>> string [2] = "d" # Traceback (most recent File "<stdin>", line TypeError: object does En cambio en una lista >>> lista = ["p", "e", "r", "r", "o"] >>> lista [2] = "d" >>> print lista [’p’, ’e’, ’d’, ’r’, ’o’] Como se muestra en la comparaci´n anterior una lista puede ser cambiada usando el o operador [ ]. Ejemplo >>> lista=["Pedro", "Andres", "Jaime", "Juan"] >>> lista[0]="Matias" >>> print lista [’Pedro’, ’Andres’, ’Jaime’, ’Juan’, ’Matias’] Esta NO es un instruccion VALIDA call last): 1, in ? not support item assignment

3.11. LISTAS.

71

3.11.3.

Agregando a una lista.

Para agregar items al final de una lista use list.append(item). Ejemplo >>> lista=["Pedro", "Andres", "Jaime", "Juan"] >>> lista.append("Matias") >>> print lista [’Pedro’, ’Andres’, ’Jaime’, ’Juan’, ’Matias’]

3.11.4.

Operaciones con listas.

las listas se pueden sumar resultando una solo lista que incluye ambas lista iniciales. Adem´s, podemos multiplicar una lista por un entero n obteniendo una lista con n replicas a de la lista inicial. Veamos ejemplos de ambas operaciones en forma interactiva >>> lista1=["Pedro", "Andres", "Jaime", "Juan"] >>> lista2=["gato", 2] >>> print lista1+lista2 [’Pedro’, ’Andres’, ’Jaime’, ’Juan’, ’gato’, 2] >>> print lista2*2 [’gato’, 2, ’gato’, 2] >>> print 2*lista2 [’gato’, 2, ’gato’, 2]

3.11.5.

Borrando items de una lista.

Use el comando del para remover items basado en el ´ ındice de posici´n. Ejemplo en forma o interactivo >>> lista=["Pedro", "Andres", "Jaime", "Juan"] >>> del lista[1] >>> print lista [’Pedro’, ’Jaime’, ’Juan’] Para remover items desde una lista sin usar el ´ ındice de posici´n, use el siguiente comano do nombre_lista.remove("item") que borra la primera aparici´n del item en la lista. Un o ejemplo interactivo >>> jovenes = ["Pancho", "Sole", "Jimmy", "Pancho"] >>> jovenes.remove("Pancho") >>> print jovenes [’Sole’, ’Jimmy’, ’Pancho’]

3.11.6.

¿Qu´ contiene una lista? e

Con la palabra reservada in podemos preguntar si un item est´ en la lista, veamos un a ejemplo

72

´ CAP´ ITULO 3. UNA BREVE INTRODUCCION A PYTHON.

lista = ["rojo", "naranjo", "verde", "azul"] if "rojo" in lista: haga_algo() La palabra clave not puede ser combinada con in para hacer la pregunta contraria, es decir, si un item no est´ en un lista. Veamos un ejemplo a lista = ["rojo", "naranjo", "verde", "azul"] if "purpura" not in lista: haga_algo()

3.11.7.

Un ciclo for y las listas.

Los ciclos for pueden ser usados con listas de la misma manera que lo eran con strings, un ejemplo para mostrarlo email = ["oto@mail.com", "ana@mail.com"] for item in email: envie_mail(item)

3.11.8.

Otros trucos con listas.

len(list_name) Da el largo de la lista, su n´mero de elementos. u list_name.sort() Pone la lista en orden alfab´tico y num´rico. e e random.choice(list_name) Escoge un elemento al azar de la lista. string.split(list_name) Convierte un string, como una frase, en una lista de palabras. string.join(list_name) Convierte una lista de palabras en una frase dentro de un string.

3.11.9.

Generando listas de n´ meros. u

La funci´n range(num_init, num_fin, num_paso) toma tres argumentos enteros, el o n´mero de partida, el numero final y el paso, para generar una lista de enteros que comienu za en el n´mero de partida, termina con un n´mero menor que el final saltandose el paso u u se˜alado, si se omite el paso el salto ser´ de uno en uno. Veamos ejemplos n a range(10) = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] range(2,10) = [2, 3, 4, 5, 6, 7, 8, 9] range(0,11,2) = [0, 2, 4, 6, 8, 10]

3.12. TUPLAS.

73

3.12.

Tuplas.

Una tupla es una lista inmutable. Una tupla no puede modificarse de ning´n modo despu´s u e de su creaci´n. o >>> t = ("a", "b", 8) >>> t[0] ’a’ Una tupla se define del mismo modo que una lista, salvo que el conjunto se encierra entre par´ntesis ( ), en lugar de entre corchetes [ ]. Los elementos de la tupla tienen un orden e definido, como los de la lista. Las tuplas tienen primer ´ ındice 0, como las listas, de modo que el primer elemento de una tupla t, no vac´ es siempre t[0]. Los ´ ıa ındices negativos cuentan desde el final de la tupla, como en las listas. Las porciones funcionan como en las listas. Advierta que al extraer una porci´n de una lista, se obtiene una nueva lista; al extraerla o de una tupla, se obtiene una nueva tupla. No hay m´todos asociados a tuplas ( tal como e append() en una lista). No pueden a˜adirse elementos a una tupla, no pueden eliminarse elementos de una tupla, n no pueden buscarse elementos en una tupla, se puede usar in para ver si un elelmento existe en la tupla. Las tuplas son m´s r´pidas que las listas. Si est´ definiendo un conjunto constante de a a a valores y todo lo que va ha hacer con ´l es recorrerlo, utilice una tupla en lugar de una e lista. Una tupla puede utilizarse como clave en un diccionario, pero las listas no. Las tuplas pueden convertirse en listas y vice versa. La funci´n incorporada tuple(lista) toma una o lista y devuelve una tupla con los mismos elementos. La funci´n list(tupla) toma una o tupla y devuelve una lista.

3.13.

El comando break.

El comando break es capaz de salirse de un ciclo for o while. Un ciclo puede tener una secci´n else esta es ejecutada cuando el ciclo termina por haber agotado la lista en un ciclo o for o cuando la comparaci´n llega a ser falsa en un ciclo while, pero no cuando el ciclo o es ternimado con break. A continuaci´n, un programa que muestra este hecho y sirve para o encontrar n´meros primos u for n in range(2,10): for x in range(2,n): if n % x ==0: print n, "igual a", x,"*", n/x break else: print n,"es un numero primo"

74

´ CAP´ ITULO 3. UNA BREVE INTRODUCCION A PYTHON.

3.14.

Trabajando con archivos.

El lenguaje Python puede ser usado para crear programas que manipulan archivos sobre un sistema de archivos en un computador. El m´dulo os contiene las funciones necesarias o para buscar, listar, renombrar y borrar archivos. El m´dulo os.path contiene unas pocas o funciones especializadas para manipular archivos. Las funciones necesarias para abrir, leer y escribir archivos son funciones intr´ ınsecas de Python.

3.14.1.

Funciones del m´dulo os. o

Funciones que s´lo dan una mirada. o getcwd() Retorna el nombre el directorio actual. listdir(path) Retorna una lista de todos los archivos en un directorio. chdir(path) Cambia de directorio. Mueve el foco a un directorio diferente. Funci´n que ejecuta un comando del sistema operativo. o system(’comando’) Ejecuta el comando Funciones que agregan. mkdir(path) Hace un nuevo directorio con el nombre dado. mkdirs(path) Hace un subdirectorio y todos los directorios del path requeridos. Funciones que borran o remueven. remove(path) Borra un archivo. rmdir(path) Borra un directorio vac´ ıo. removedirs(path) Borra un directorio y todo dentro de ´l. e Funciones que cambian. rename(viejo,nuevo) Cambia el nombre de un archivo de viejo a nuevo renames(viejo,nuevo) Cambia el nombre de un archivo de viejo a nuevo cambiando los nombres de los directorios cuando es necesario.

3.14.2.

Funciones del m´dulo os.path. o

Funciones que verifican. exists(file) Retorna un booleano si el archivo file existe. isdir(path) Retorna un booleano si el path es un directorio. isfile(file) Retorna un booleano si el file es un archivo.

3.14. TRABAJANDO CON ARCHIVOS.

75

3.14.3.

Ejemplo de un c´digo. o

Un programa que borra todo un directorio import os, os.path path = raw_input("Directorio a limpiar : ") os.chdir(path) files= os.listdir(path) print files for file in files: if os.path.isfile(file): os.remove(file) print "borrando", file elif os.path.isdir(file): os.removedirs(file) print "removiendo", file else: pass

3.14.4.

Abriendo un archivo.

Para abrir un archivos debemos dar la instrucci´n open(filename,mode) donde filename o es el nombre del archivo y el mode corresponde a una de tres letras "r" para lectura solamente del archivo, "w" para escritura y "a" para agregar al final del archivo. para poder manejar un archivo abierto hay que crear una variable con ´l. Ejemplo e salida= open("datos.txt","w") salidaAppend= open("programa.log","a") entrada= open("archivo.txt","r")

3.14.5.

Leyendo un archivo.

entrada.read() Lee el archivo completo como un string. entrada.readline() Lee una l´ ınea en un string. entrada.readlines() Lee el archivo completo, cada l´ ınea llega a ser un item tipo string en una lista.

3.14.6.

Escribiendo a un archivo.

salida.write(string) Escribe el string al archivo. C´mo se escribira este depende o de en qu´ modo el archivo fue abierto. e salida.writelines(list) Escribe todos los items tipo string en la lista list. Cada elemento en la lista estar´ en la misma l´ a ınea a menos que un elemento contenga una caracter de newline

76

´ CAP´ ITULO 3. UNA BREVE INTRODUCCION A PYTHON.

Si queremos usar la instruccion print para escribir sobre un archivo abierto, digamos salida, podemos usar la instrucci´n o salida = open("resultados.txt", "w") print >> salida, datos # Imprime datos en el archivo datos.txt print >> salida # Imprime una linea en blanco en el archivo datos.txt salida.close()

3.14.7.

Cerrando un archivo.

file.close() Cierra un archivo previamente abierto.

3.14.8.

Archivos temporales.

Las funciones en el m´dulo tempfile puede ser usadas para crear y manejar archivos o temporales. La instrucci´n tempfile.mkstemp() devuelve una lista en el que el segundo o item es un nombre al azar que no ha sido usado. Los archivos temporales estar´n localizados a en el directorio temporal por defecto.

3.14.9.

Ejemplo de lectura escritura.

# Programa que reemplaza una palabra vieja por otra nueva import string, tempfile, os # Preguntarle al usuario por Informacion filename = raw_input("Nombre del archivo: ") find = raw_input("Busque por: ") replace = raw_input("Reemplacelo por: ") # Abra el archivo del usuario, lealo y cierrelo file = open(filename, "r") text = file.readlines() file.close() # Edite la informacion del archivo del usuario nueva = [] for item in text: line = string.replace(item, find, replace) nueva.append(line) # Cree un nuevo archivo temporal newname=tempfile.mkstemp() temp_filename=newname[1] newfile = open(temp_filename, "w") newfile.writelines(nueva)

3.15. EXCEPCIONES. newfile.close() # Cambie los nombres de los archivos y borra los temporales oldfile=filename+"~" os.rename(filename, oldfile) os.system(" cp "+temp_filename+" "+filename) os.remove(temp_filename)

77

3.15.

Excepciones.

Las palabras reservadas try y except pueden ser usadas para atrapar errores de ejecuci´n o en el c´digo. Primero en el bloque try se ejecutan un grupo de instrucciones o alguna funci´n. o o Si estas fallan o devuelven un error, el bloque de comandos encabezados por except se ejecutar´. Lo anterior, puede ser usado para manejar programas que pueden fallar bajo a alguna circunstancia de una forma muy elegante. # Sample Try / Except def open_file(): filename = raw_input("Entre el nombre del archivo: ") try: file = open(filename) except: print "Archivo no encontrado." open_file() return file

3.16.

Diccionarios.

Las listas son colecciones de items (strings, n´meros o incluso otras listas). Cada item en u la lista tiene un ´ ındice asignado. >>> lista >>> print primero >>> print segundo >>> print tercero = ["primero", "segundo", "tercero"] lista[0] lista[1] lista[2]

Para acceder a un valor de la lista uno debe saber su ´ ındice de posici´n. Si uno remueve o un item desde la lista, el ´ ındice puede cambiar por el de otro item en la lista. Un diccionario es una colecci´n de items que tiene una llave y un valor. Ellos son parecidos o a las listas, excepto que en vez de tener asignado un ´ ındice uno crea los ´ ındices. lista = ["primero", "segundo", "tercero"] diccionario = {0:"primero", 1:"segundo", 2:"tercero"}

78

´ CAP´ ITULO 3. UNA BREVE INTRODUCCION A PYTHON.

Para crear un diccionario debemos encerrar los item entre par´ntesis de llave {}. Debemos e proveer una llave y un valor, un signo : se ubica entre la llave y el valor (llave:valor). cada llave debe ser unica. Cada par llave:valor est´ separado por una coma. Veamos un ´ a par de ejemplos con diccionarios ingles = {’one’:’uno’, ’two’:’dos’} Uno en japon´s e nihon_go = {} nihon_go["ichi"] = "uno" nihon_go["ni"] = "dos" nihon_go["san"] = "tres" print nihon_go { ’ichi’:’uno’, ’ni’:’dos’, ’san’:’tres’} Para acceder el valor de un item de un diccionario uno debe entrar la llave. Los diccionarios s´lo trabajan en una direcci´n. Uno debe dar la llave y le devolver´n el valor. Uno no puede o o a dar el valor y que le devuelvan la llave. Ejemplo nihon_go = { ’ichi’:’uno’, ’ni’:’dos’, ’san’:’tres’} print nihon_go[’ichi’] uno Notemos que este diccionario traduce del japon´s al espa˜ol pero no del espa˜ol al japon´s. e n n e

3.16.1.

Editando un diccionario.

Para cambiar un valor de un par, simplemente reas´ ıgnelo nihon_go["ichi"]=1 Para agregar un par valor:llave, ´ntrelo e nihon_go["shi"]=cuatro Para remover un par use del del nihon_go["ichi"] Para ver si una llave ya existe, use la funci´n has_key() o nihon_go.has_key("ichi") Para copiar el diccionario entero use la funci´n o m´todo copy(). o e japones= nihon_go.copy() Los diccionarios son mutables. Uno no tiene que reasignar el diccionario para hacer cambios en ´l. e Los diccionarios son utiles cada vez que usted tiene items que desea ligar juntos. Tambi´n ´ e son utiles haciendo subtituciones (reemplace todos los x por y). Almacenando resultados ´ para una inspecci´n r´pida. Haciendo men´s para programas. Creando mini bases de datos o a u de informaci´n. o

3.17. MODULES Y SHELVE.

79

3.16.2.

Un ejemplo de c´digo, un men´ . o u

import string def add(num1,num2): print num1+num2 def mult(num1,num2): print num1*num2 # Programa num1 = input("Entre el primer numero: ") num2 = input("Entre el segundo numero: ") menu = {’S’:add, ’M’:mult} print "[S] para sumar, [M] para multiplicar: " choice = string.upper(raw_input()) menu[choice] (num1,num2)

3.16.3.

Tuplas y diccionarios como argumentos.

Si un par´metro formal de la forma **name est´ presente, la funci´n recibe un diccionario. a a o Si un par´metro formal de la forma *name est´ presente, la funci´n recibe una tupla. Los a a o par´metros formales *name deben ir antes que los **name. Ejemplo a def funcion(*mi_tupla, **nihon_go): ..

3.17.

Modules y Shelve.

Algunos problemas que se presentan a medida que los c´digos crecen son: con cientos o de l´ ıneas es muy f´cil perderse; trabaja en equipo se hace dif´ con c´digos muy grandes. a ıcil o Entonces, ser´ bueno poder separar el c´digo en peque˜os archivos independientes. Por otra ıa o n parte, se nos presenta otra dificultad, no podemos salvar estructuras de datos, es decir, si creamos un diccionario, sabemos como salvarlo como un archivo de texto, pero no podemos leerlo como un diccionario. Ser´ bueno poder salvar las listas como listas, los diccionarios ıa como diccionarios y as´ luego poder leerlos e incorporarlos a nuestro c´digo en forma f´cil. ı o a

3.17.1.

Partiendo el c´digo. o

El c´digo puede ser dividido en archivos separados llamados modules. Ya hemos usado o varios de estos m´dulos trabajando en Python (string, math, random, etc.). Para crear un o m´dulo s´lo tipee su c´digo Python y s´lvelo de la manera usual. Su m´dulo salvado puede o o o a o ser importado y usado tal como cualquier otro m´dulo de Python. o

3.17.2.

Creando un m´dulo. o

Lo principal para almacenar nuestro c´digo en un m´dulo es escribir c´digo reusable. El o o o c´digo debe ser principalmente funciones y clases. Evite tener variables o comandos fuera de o

80

´ CAP´ ITULO 3. UNA BREVE INTRODUCCION A PYTHON.

la definici´n de funciones. Las funciones pueden requerir valores desde el programa quien las o llama. Salve el c´digo como un archivo regular .py. Luego en el programa principal, importe o el m´dulo y uselo. o ´

3.17.3.

Agregando un nuevo directorio al path.

Cuando Python busca m´dulos s´lo lo hace en ciertos directorios. La mayor´ de los o o ıa m´dulos que vienen con Python son salvados en /usr/lib/python. Cuando salve sus proo pios m´dulos seguramente lo har´ en un lugar diferente, luego es necesario agregar el nuevo o a directorio a sys.path. Hay que consignar que el directorio desde el cual se invoca Python, si est´ en el path. Para editar el sys.path, en el modo interactivo tipee a >>> import sys >>> sys.path #imprime los actuales directorios en el path >>> sys.path.append(’/home/usuario/mis_modulos’) Dentro de un script usamos para importar mi m´dulos mis_funciones que est´ salvado en o a mi directorio de m´dulos o import sys sys.path.append(’/home/usuario/mis_modulos’) import mis_funciones

3.17.4.

Haciendo los m´dulos f´ciles de usar. o a

Como ya vimos los comentarios con triple comilla son usados para agregar documentaci´n o al c´digo, ejemplo o def mi_funcion(x,y): """mi_funcion( primer nombre, ultimo nombre) """ Use al principio y al final triple comilla. El texto en triple comilla deber´ explicar lo que ıa la funci´n, clase o m´dulo hace. Estas l´ o o ıneas de documentaci´n las podr´ ver, en el modo o e interactivo, si da el comando help(module.mi_funcion).

3.17.5.

Usando un m´dulo. o

En el programa principal incluya el comando import y el nombre del m´dulo. Cuando o llame a una funci´n del m´dulo debe incluir el nombre del m´dulo . el nombre de la funci´n, o o o o esta no es la unica manera de importarlos, veamos unos ejemplo, primero la forma habitual: ´ # Sean f(x,y) una funcion y C una clase con un metodo m(x) del modulo stuff import stuff print stuff.f(1,2) print stuff.C(1).m(2)

3.17. MODULES Y SHELVE. una segunda forma

81

# Sean f(x,y) una funcion y C una clase con un metodo m(x) del modulo stuff from stuff import f, C print f(1,2) print C(1).m(2) una tercera forma # Sean f(x,y) una funcion y C una clase con un metodo m(x) del modulo stuff from stuff import * print f(1,2) print C(1).m(2) una ultima manera ´ # Sean f(x,y) una funcion y C una clase con un metodo m(x) del modulo stuff import stuff as st print st.f(1,2) print st.C(1).m(2)

3.17.6.

Trucos con m´dulos. o

Un m´dulo puede ser corrido como programa independiente si inclu´ o ımos las siguientes l´ ıneas en el final if __name__ == ’__main__’: funcion_a_correr() Sustituya funcion_a_correr() por el nombre de la funci´n principal en el m´dulo. o o

3.17.7.

Preservando la estructura de la informaci´n. o

Existen dos m´todos de preservar la data: e El m´dulo pickle almacena una estructura de datos de Python en un archivo binario. o Est´ limitado a s´lo una estructura de datos por archivo. a o El m´dulo shelve almacena estructuras de datos de Python pero permite m´s de una o a estructura de datos y puede ser indexado por una llave.

3.17.8.

¿C´mo almacenar? o

Importe el m´dulo shelve, abra un archivo shelve, asigne un item, por llave, al archivo o shelve. Para traer la data de vuelta al programa, abra el archivo shelve y accese el item por llave. Los shelve trabajan como un diccionario, podemos agregar, accesar y borrar items usando sus llaves.

82

´ CAP´ ITULO 3. UNA BREVE INTRODUCCION A PYTHON.

3.17.9.

Ejemplo de shelve.

import shelve colores = ["verde", "rojo", "azul"] equipos = ["audax", "union", "lachile"] shelf = shelve.open(’mi_archivo’) # Almacenendo items shelf[’colores’] = colores shelf[’equipos’] = equipos # trayendolos de vuelta newlist = shelf[’colores’] # Cerrando shelf.close()

3.17.10.

Otras funciones de shelve.

Para tomar una lista de todas las llaves disponibles en un archivo shelve, use la funci´n o keys(): lista = shelf.keys() Para borrar un item, use la funci´n del: o del shelf(’ST’) Para ver si una llave existe, use la funci´n has_key(): o if shelf.has_key(’ST’): print "si"

3.18.

Clases y m´todos. e

Las clases son colecciones de data y funciones que pueden ser usadas una y otra vez. Para crear una clase parta con la palabra reservada class, luego necesita un nombre para la clase. Los nombres de las clases, por convenci´n, tiene la primera letra en may´scula. Despu´s del o u e nombre termine la l´ ınea con un : y entonces cree el cuerpo de la clase, las instrucciones que forman el cuerpo deben ir con sangr´ En el cuerpo cree las definiciones de las funciones, ıa. cada funci´n debe tomar self como par´metro. o a class MiClase: def hola(self): print "Bienvenido. " def math(self,v1,v2): print v1+v2 Declarando y luego usando la clase class MiClase: def hola(self): print "Bienvenido. " def math(self,v1,v2):

´ 3.18. CLASES Y METODOS. print v1+v2 fred = MiClase() fred.hola() fred.math(2,4)

83

Creamos una instancia de una clase al asignarla a una variable, fred = MiClase(). Para aplicar una funci´n o m´todo a una nueva instancia debemos especificar en forma completa o e la instancia y el m´todo fred.hola(). Si el m´todo toma argumentos debemos estar seguro e e de incluir todos los valores necesitados, por ejemplo fred.math(2,4).

3.18.1.

Clase de muestra LibretaNotas.

class LibretaNotas: def __init__(self, name, value): self.nombre = name self.puntaje = value self.evaluaciones = 1 def sumanota(self, puntos): self.evaluaciones += 1 self.puntaje += puntos self.promedio = self.puntaje/float(self.evaluaciones) def promedio(self) print self.nombre, ": promedio =", self.promedio Las variables dentro de una clase deben ser accesadas poniendo el prefijo a su nombre la palabra self. La funci´n __init__ es la que correr´ si una nueva instancia de la clase es creada. Esta o a funci´n es especial y se conoce como el constructor de la clase. o Usando la clase LibretaNotas eli = LibretaNota(’Elizabeth’, 6.5) mario = LibretaNota(’Mario’, 6.0) carmen = LibretaNota(’Carmen’, 6.1) eli.sumanota(6.2) mario.sumanota(6.1) carmen.sumanota(6.3) eli.sumanota(6.8) mario.sumanota(6.7) carmen.sumanota(6.6) eli.promedio() mario.promedio() carmen.promedio()

84

´ CAP´ ITULO 3. UNA BREVE INTRODUCCION A PYTHON.

Cada nueva instancia de la clase LibretaNotas debe tener un nombre y una primera nota porque as´ lo requiere la funci´n constructor __init__. Notemos que cada instancia tiene su ı o propio promedio.

3.18.2.

Valores por defecto.

Una funci´n puede tener valores por defecto, estos valores son usados s´lo cuando la o o funci´n es llamada sin especificar un valor. Ejemplo o def potencia(voltaje, corriente=0): return voltaje*corriente # Podemos llamarla potencia(220) potencia(voltaje=110, corriente=5) Veamos un ejemplo de valores por defecto en una clase class Dinero: def __init__(self, amount = 0) : self.amount=amount def print(self): print "Tienes", self.amount, "de dinero" # Llamadas posibles mi_dinero = Dinero(100) tu_dinero = Dinero() mi_dinero.print() tu_dinero.print()

3.19.

Sobrecarga de Operadores.

Las clases pueden redefinir comandos regulares de Python. Cambiar como los comandos regulares trabajan en una clase se llama sobrecarga de operadores. Para definir la sobrecarga, debemos usar nombres especiales cuando definimos los m´todos. Las definiciones sobrecargae das deben retornar un valor. Veamos un ejemplo de sobrecarga class Loca: def __init__(self, num1=2): self.num1=num1 def __del__(self): print "%d Destruido!" % self.num1 def __repr__(self): return "Su numero es %d" % self.num1 def __add__(self, newnum): return newnum*self.num1

3.19. SOBRECARGA DE OPERADORES.

85

Notemos que tenemos un m´todo nuevo el destructor que el la funci´n que se invoca cuane o do una variable se destruye. A continuaci´n, una lista de nombre especiales para sobrecargar o los operadores __add__ La suma +. __sub__ La resta −. __mul__ La multiplicaci´n ∗. o __div__ La divisi´n /. o __pow__ La exponenciaci´n ∗∗. o __repr__ El comando print. __len__ El comando len(x). __call__ El comando de llamada x(). __init__ El m´todo constructor. e __del__ El m´todo destructor. e

3.19.1.

Funci´n driver. o

Una funci´n driver es puesta al final de la clase para probarla. La funci´n toma la forma o o if __name__ == ’__main__’: funcion_a_correr() Cuando una clase o m´dulo es llamado como programa principal, correr´ este c´digo. o a o

3.19.2.

Atributos de las clases.

La informaci´n que necesita acceder una clase en cada una de sus instancias u objetos o puede ser almacenada en atributos de la clase. Los valores ser´n creados fuera de las defia niciones de las funciones de la clase. La data ser´ accesada dentro de las definici´n de las a o funciones o m´todos de la clase usando la notaci´n NombredelaClase.NombredelaVariable. e o Un ejemplo class Cuentas: alumnos=[] def __init__(self,nombre): self.nombre=nombre Cuentas.alumnos.append(self.nombre) def __del__(self) Cuentas.alumnos.remove(self.nombre) Notese que la lista de alumnos es siempre llamada por su nombre completo Cuentas.alumnos. Para acceder a la lista fuera de la clase, use su nombre completo Cuentas.alumnos.

86

´ CAP´ ITULO 3. UNA BREVE INTRODUCCION A PYTHON.

3.19.3.

Ejemplo de clase vectores.

Escribamso un m´dulo vec2d.py con una clase de vectores bidimensionales sobrecargando o la suma, la resta, el producto, la impresi´n, entre otros m´todos o e from math import sqrt class Vec2d: def __init__(self, x=0, y=0): self.x = x self.y = y def module(self): return sqrt(self.x**2+self.y**2) def __repr__(self): return "(%11.5f,%11.5f)" % (self.x,self.y) def __add__(self,newvec): return Vec2d(self.x+newvec.x,self.y+newvec.y) def __sub__(self,newvec): return Vec2d(self.x-newvec.x,self.y-newvec.y) def __mul__(self,newvec): return self.x*newvec.x+self.y*newvec.y Ahora un programa que ocupa el m´dulo o #!/usr/bin/env python from vec2d import * a=Vec2d(1.3278,2.67) b=Vec2d(3.1,4.2) print print print print print a, b a+b a-b a*b a.module(),b.module()

3.20.

Algunos m´dulos interesantes. o

Hay muchos m´dulos que le pueden ser utiles, aqu´ le sugerimos unos pocos particularo ´ ı mente importantes.

3.20.1.

El m´dulo Numeric. o

Extensi´n num´rica de Python que agrega poderosos arreglos multidimensionales. o e

´ 3.20. ALGUNOS MODULOS INTERESANTES. >>> import Numeric as num >>> a = num.zeros((3,2), num.Float) >>> a array([[ 0., 0.], [ 0., 0.], [ 0., 0.]]) >>> a[1]=1 >>> a array([[ 0., 0.], [ 1., 1.], [ 0., 0.]]) >>> a[0][1]=3 >>> a array([[ 0., 3.], [ 1., 1.], [ 0., 0.]]) >>> a.shape (3, 2)

87

3.20.2.

El m´dulo Tkinter. o

Un m´dulo para escribir aplicaciones gr´ficas portables con Phyton y Tk. o a #!/usr/bin/env python from Tkinter import * root = Tk() root.title("Mi ventana") btn = Button(root, text="Salir") btn.grid() def stop(event): root.destroy() btn.bind(’<Button-1>’, stop) root.mainloop()

3.20.3.

El m´dulo Visual. o

Un m´dulo que permite crear y manipular objetos 3D en un espacio 3D. o

88

´ CAP´ ITULO 3. UNA BREVE INTRODUCCION A PYTHON.

Cap´ ıtulo 4 Una breve introducci´n a C++. o
versi´n 7.50, 23 de Octubre del 2007 o

En este cap´ ıtulo se intentar´ dar los elementos b´sicos del lenguaje de programaci´n a a o C++. No se pretende m´s que satisfacer las m´ a ınimas necesidades del curso, sirviendo como un ayuda de memoria de los t´picos abordados, para futura referencia. Se debe consignar que o no se consideran todas las posibilidades del lenguaje y las explicaciones est´n reducidas al a m´ ınimo.

4.1.
4.1.1.

Estructura b´sica de un programa en C++. a
El programa m´s simple. a

El primer ejemplo de todo manual es el que permite escribir “Hola” en la pantalla. // // Los comentarios comienzan con // // #include <iostream> using namespace std; int main() { cout << "Hola." << endl; return 0 ; } Las tres primeras l´ ıneas corresponden a comentarios, todo lo que est´ a la derecha de a los caracteres // son comentarios y no ser´n considerados en la compilaci´n. En la l´ a o ınea siguiente se incluye un archivo de cabecera, o header, con la instrucci´n de preprocesador o #include. El nombre del archivo se puede escribir como <nombre> o bien "nombre.h". En el primer caso el archivo nombre ser´ buscado en el path por defecto para los include, a t´ ıpicamente /usr/include o /usr/include/c++/3.x/ en el caso de headers propios de C++; en el segundo caso la b´squeda se hace en el directorio local. Tambi´n podr´ u e ıamos incluir un path completo cuando se ocupan las comillas. En nuestro ejemplo se incluye el archivo iostream, en el cual se hacen las definiciones adecuadas para el manejo de la entrada y salida en C++. Este archivo es necesario para enviar luego un mensaje a pantalla. 89

90

´ CAP´ ITULO 4. UNA BREVE INTRODUCCION A C++.

La funci´n int main es donde comienza a ejecutarse el programa; siempre debe haber una o funci´n main en nuestro programa. Debido a imposiciones del sistema operativo la funci´n o o main devuelve un entero y por tanto debe ser declarada int. Los par´ntesis vac´ () indican e ıos que el main no tiene argumentos de entrada (m´s adelante se ver´ que puede tenerlos). Lo a a que est´ encerrado entre llaves {} corresponde al cuerpo de la funci´n main. Cada una de a o las l´ ıneas termina con el car´cter ;. El identificador predefinido cout representa la salida a a pantalla. El operador << permite que lo que est´ a su derecha se le d´ salida por el dispositivo a e que est´ a su izquierda, en este caso cout. Si se quiere enviar m´s de un objeto al dispositivo a a que est´ al inicio de la l´ a ınea agregamos otro operador <<, y en este caso lo que est´ a la a derecha del operador se agregar´ a lo que est´ a la izquierda y todo junto ser´ enviado al a a a dispositivo. En nuestro caso se ha enviado endl, un objeto predefinido en el archivo iostream que corresponde a un cambio de l´ ınea, el cual ser´ agregado al final del mensaje. La l´ a ınea final contiene la instrucci´n de retorno del entero cero, return 0. o Si escribimos nuestro primer programa en el editor xemacs con el nombre de primero.cc las instrucciones para editarlo, compilarlo y correrlo ser´n: a jrogan@pucon:~/tmp$ xemacs primero.cc jrogan@pucon:~/tmp$ g++ -Wall -o primero primero.cc jrogan@pucon:~/tmp$ ./primero Hola. jrogan@pucon:~/tmp$ Luego de la compilaci´n, un archivo ejecutable llamado primero es creado en el directoo rio actual. Si el directorio actual no est´ en el PATH, nuestro programa debe ser ejecutado a anteponiendo ./. Si est´ en el PATH, para ejecutarlo basta escribir primero. (Para agrea gar el directorio local al PATH basta editar el archivo ~/.bashrc agregarle una l´ ınea como PATH="${PATH}:." y ejecutar en la l´ ınea de comando source ~/.bashrc para que los cambios tengan efecto.)

4.1.2.

Definici´n de funciones. o

Las funciones en C++ son muy importantes, pues permiten aislar parte del c´digo en o una entidad separada. Esto es un primer paso a la modularizaci´n de nuestro programa, o es decir, a la posibilidad de escribirlo en partes que puedan ser editadas de modo lo m´s a independiente posible. Ello facilita enormemente la creaci´n de c´digo complicado, pues simo o plifica su modificaci´n y la localizaci´n de errores. Nos encontraremos frecuentemente con o o este concepto. Aprovecharemos de introducir las funciones modificando el primer programa de manera que se delegue la impresi´n del mensaje anterior a una funci´n independiente: o o // // Segunda version incluye funcion adicional // #include <iostream> using namespace std;

´ 4.1. ESTRUCTURA BASICA DE UN PROGRAMA EN C++. void PrintHola() { cout << "Hola." << endl; } int main() { PrintHola(); return 0; }

91

La funci´n debe estar definida antes de que sea ocupada, por eso va primero en el c´digo o o fuente. Como ya se dijo antes, la ejecuci´n del programa comienza en la funci´n main a o o pesar de que no est´ primera en el c´digo fuente. Los par´ntesis vac´ indican que la funci´n a o e ıos o PrintHola no tiene argumentos y la palabra delante del nombre de la funci´n indica el tipo o de dato que devuelve. En nuestro caso la palabra void indica que no devuelve nada a la funci´n main. o Una alternativa al c´digo anterior es la siguiente: o #include <iostream> using namespace std; void PrintHola(); int main() { PrintHola(); return 0 ; } void PrintHola() { cout << "Hola." << endl; } En esta versi´n se ha separado la declaraci´n de la funci´n de su implementaci´n. En o o o o la declaraci´n se establece el nombre de la funci´n, los argumentos que recibe, y el tipo de o o variable que entrega como resultado. En la implementaci´n se da expl´ o ıcitamente el c´digo o que corresponde a la funci´n. Hab´ o ıamos dicho que una funci´n debe estar definida antes que o sea ocupada. En verdad, basta con que la funci´n est´ declarada. La implementaci´n puede o e o ir despu´s (como en el ejemplo anterior), o incluso en un archivo distinto, como veremos m´s e a adelante. La separaci´n de declaraci´n e implementaci´n es otro paso hacia la modularizaci´n o o o o de nuestro programa.

92

´ CAP´ ITULO 4. UNA BREVE INTRODUCCION A C++.

4.1.3.

Nombres de variables.

Nuestros datos en los programas ser´n almacenados en objetos llamados variables. Para a referirnos a ellas usamos un nombre que debe estar de acuerdo a las siguientes reglas: – Deben comenzar con una letra (may´sculas y min´sculas son distintas). u u – Pueden contener n´meros, pero no comenzar por uno. u – Pueden contener el s´ ımbolo _ (underscore). – Longitud arbitraria. – No pueden corresponder a una de las palabras reservadas de C++1 : 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 operator private protected public register return short signed sizeof static struct switch template this throw try typedef union unsigned virtual void volatile while

4.1.4.

Tipos de variables.

Todas las variables a usar deben ser declaradas de acuerdo a su tipo. Por ejemplo, si usamos una variable i que sea un n´mero entero, debemos, antes de usarla, declararla, y s´lo u o entonces podemos asignarle un valor: int i; i=10; Esta necesidad de declarar cada variable a usar se relaciona con la caracter´ ıstica de C++ de 2 ser fuertemente “tipeado” . Algunos de los errores m´s habituales en programaci´n se deben a o al intento de asignar a variables valores que no corresponden a sus tipos originales. Si bien esto puede no ser muy grave en ciertos contextos, a medida que los programas se vuelven m´s complejos puede convertirse en un verdadero problema. El compilador de C++ es capaz a de detectar los usos indebidos de las variables pues conoce sus tipos, y de este modo nuestro c´digo se vuelve m´s seguro. o a Es posible reunir las acciones de declaraci´n e inicializaci´n en una misma l´ o o ınea: int i=10;
A esta tabla hay que agregar algunas palabras adicionales, presentes en versiones m´s recientes de C++, a como namespace y using 2 Una traducci´n libre del t´rmino ingl´s strongly typed. o e e
1

´ 4.1. ESTRUCTURA BASICA DE UN PROGRAMA EN C++.

93

o declarar m´s de una variable del mismo tipo simult´neamente, e inicializar algunas en la a a misma l´ ınea: int r1, r2, r3 = 10; A veces se requiere que una variable no var´ una vez que se le asigna un valor. Por ejemplo, ıe podr´ ıamos necesitar definir el valor de π = 3.14159..., y naturalmente no nos gustar´ que, ıa por un descuido, a esa variable se le asignara otro valor en alguna parte del programa. Para asegurarnos de que ello no ocurra, basta agregar el modificador const a la variable: const float pi = 3.14159; Para n´meros reales se puede usar la notaci´n exponencial. Por ejemplo, 1.5e-3 repreu o senta el n´mero 1.5 × 10−3 . u Una variable puede ser declarada s´lo una vez, pero naturalmente se le pueden asignar o valores en un n´mero arbitrario de ocasiones. u Los 15 tipos de datos aritm´ticos fundamentales disponibles son3 : e Booleanos y caracteres bool char signed char unsigned char Booleanas true o false. Caracteres de 0 a 255 o -128 a 127, usa 8 bits, Caracteres −128 a 127, Caracteres de 0 a 255. Enteros short Enteros entre −215 = −32768 y 215 − 1 = 32767 unsigned short Enteros entre 0 y 65535 int Enteros entre −231 = −2147483648 y 231 − 1 = 2147483647 unsigned int Enteros entre 0 y 232 = 4294967295 long (32 bits) Entero entre −2147483648 y 2147483647, long (64 bits) Entero entre −9223372036854775808 y 9223372036854775807, unsigned long (32 bits) Enteros entre 0 y 4294967295, unsigned long (64 bits) Enteros entre 0 y 18446744073709551615, long long Enteros entre −9223372036854775808 y 9223372036854775807 unsigned long long Enteros entre 0 y 18446744073709551615 Float float Reales x tal que 1.17549435 × 10−38 ≤ |x| ≤ 3.40282347 × 1038 , (Precisi´n de 7 d´ o ıgitos decimales.) double Reales x tal que 2.2250738585072014 × 10−308 ≤ |x| ≤ 1.7976931348623157 × 10308 , (Precisi´n de 15 d´ o ıgitos decimales.) long double Reales x tal que 3.36210314311209350626 × 10−4932 ≤ |x| ≤ 1.18973149535723176502 × 104932 , (Precisi´n de 18 d´ o ıgitos decimales.)

Los valores de los rangos indicados son simplemente representativos y dependen de la m´quina utilizada a (32 bits o 64 bits). Adem´s, estos valores no corresponden exactamente a las versiones m´s recientes de C++. a a

3

94

´ CAP´ ITULO 4. UNA BREVE INTRODUCCION A C++. Las variables tipo char alojan caracteres, debiendo inicializarse en la forma:

char c = ’a’; Adem´s de las letras may´sculas y min´sculas, y s´ a u u ımbolos como &, (, :, etc., hay una serie de caracteres especiales (escape codes) que es posible asignar a una variable char. Ellos son: newline horizontal tab vertical tab backspace carriage return form feed alert (bell) backslash single quote double quote \n \t \v \b \r \f \a \\ \’ \"

Por ejemplo, la l´ ınea: cout << "Primera columna\t Segunda columna\n Segunda linea" << endl; corresponde al output Primera columna Segunda linea Segunda columna

4.1.5.

Ingreso de datos desde el teclado.

El header iostream define un objeto especial llamado cin que est´ asociado al teclado o a stdin. Con el operador >> asignamos la entrada en el dispositivo de la izquierda a la variable de la derecha; una segunda entrada requiere de otro operador >> y de otra variable. En el siguiente ejemplo veremos una declaraci´n simult´nea de dos variables del mismo tipo i y o a j, un mensaje a pantalla con las instrucciones a seguir, el ingreso de dos variables desde el teclado y luego su escritura en la pantalla. #include <iostream> using namespace std; int main() { int i, j ; cout << "Ingrese dos numeros enteros: " ; cin >> i >> j ; cout << "Los dos numeros ingresados fueron: " << i <<" "<< j << endl ; return 0; }

´ 4.1. ESTRUCTURA BASICA DE UN PROGRAMA EN C++.

95

4.1.6.

Operadores aritm´ticos. e

Existen operadores binarios (i.e., que act´an sobre dos variables, una a cada lado del u operador) para la suma, la resta, la multiplicaci´n y la divisi´n: o o + * /

4.1.7.

Operadores relacionales.

Los s´ ımbolos para los operadores relacionales de igualdad, desigualdad, menor, menor o igual, mayor y mayor o igual son: == != < <= > >=

Para las relaciones l´gicas AND, OR y NOT: o && || !

4.1.8.

Asignaciones.

a) Asignaci´n simple. Podemos asignar a una variable un valor expl´ o ıcito, o el valor de otra variable: i = 1; j = k; Una pr´ctica habitual en programaci´n es iterar porciones del c´digo. La iteraci´n a o o o puede estar determinada por una variable cuyo valor aumenta (disminuye) cada vez, hasta alcanzar cierto valor m´ximo (m´ a ınimo), momento en el cual la iteraci´n se detiene. o Para que una variable x aumente su valor en 2, por ejemplo, basta escribir: x = x + 2; Si x fuera una variable matem´tica normal, esta expresi´n no tendr´ sentido. Esta a o ıa expresi´n es posible porque el compilador interpreta a x de modo distinto a cada lado o del signo igual: a la derecha del signo igual se usa el valor contenido en la variable x (por ejemplo, 10); a la izquierda del signo igual se usa la direcci´n de memoria en la o cual est´ alojada la variable x. De este modo, la asignaci´n anterior tiene el efecto de a o colocar en la direcci´n de memoria que contiene a x, el valor que tiene x m´s 2. En o a general, todas las variables tienen un rvalue y un lvalue: el primero es el valor usado a la derecha (right) del signo igual en una asignaci´n, y el segundo es el valor usado a la o izquierda (left), es decir, su direcci´n de memoria. o b) Asignaci´n compuesta. o La expresi´n o x = x + 2 se puede reemplazar por += -= *= /= x += 2. Existen los operadores

96

´ CAP´ ITULO 4. UNA BREVE INTRODUCCION A C++. c) Operadores de incremento y decremento. La expresi´n o x = x + 1 se puede reescribir x += 1 o bien x++.

An´logamente, existe el operador --. Ambos operadores unarios, ++ y -- pueden ocua parse como prefijos o sufijos sobre una variable y su acci´n difiere en ambos casos. o Como prefijo la operaci´n de incremento o decremento se aplica antes de que el valor o de la variable sea usado en la evaluaci´n de la expresi´n. Como sufijo el valor de la vao o riable es usado en la evaluaci´n de la expresi´n antes que la operaci´n de incremento o o o o decremento. Por ejemplo, supongamos que inicialmente x = 3. Entonces la instrucci´n o y=x++ hace que y = 3, x = 4; por su parte, y=++x hace que y = 4, x = 4. Con estas consideraciones, deber´ ıamos poder convencernos de que la salida del siguiente programa es 3 2 2-1 1 1 : // Ejemplo de operadores unarios ++ y --. #include <iostream> using namespace std; int main() { int y ; int x = (y = 1) ; int w = ++x + y++; cout << w <<" " << x << " " << y << "-" ; w = x-- - --y; cout << w << " " << x << " " << y << endl ; return 0; } Los operadores para asignaci´n compuesta, y los de incremento y decremento, no son s´lo o o abreviaciones. En realidad hay que preferirlas porque implican optimizaciones en el ejecutable resultante.

4.1.9.

Conversi´n de tipos. o

Una consecuencia de que C++ sea fuertemente “tipeado” es que no se pueden hacer operaciones binarias con objetos de tipos distintos. En la siguiente expresi´n, o int i = 3; float x = 43.8; cout << "Suma = " << x + i << endl; el computador debe sumar dos variables de tipos distintos, y en principio la operaci´n es o imposible. La estrategia para resolver este problema es convertir ambas variables a un tipo com´n antes de efectuar la suma (en ingl´s, decimos que hacemos un cast de un tipo a otro). u e Existen dos modos de proceder:

´ 4.1. ESTRUCTURA BASICA DE UN PROGRAMA EN C++. a) Conversi´n expl´ o ıcita.

97

Si i es un int, por ejemplo, entonces float(i) la convierte en float. As´ el programa ı, anterior se puede reescribir: int i = 3; float x = 43.8; cout << "Suma = " << x + float(i) << endl; Ahora la suma es claramente entre dos variables float, y se puede realizar. Sin embargo, esto es bastante tedioso, por cuanto el programador debe realizar el trabajo de conversi´n personalmente cada vez que en su c´digo se desee sumar un real con un o o n´mero entero. u b) Conversi´n impl´ o ıcita. En este caso, el compilador realiza las conversiones de modo autom´tico, prefiriendo a siempre la conversi´n desde un tipo de variable de menor precisi´n a uno de mayor o o precisi´n (de int a double, de short a int, etc.). As´ a pesar de lo que dijimos, el o ı, c´digo anterior habr´ funcionado en su forma original. Evidentemente esto es muy o ıa c´modo, porque no necesitamos hacer una conversi´n expl´ o o ıcita cada vez que sumamos un entero con un real. Sin embargo, debemos estar conscientes de que esta comodidad s´lo es posible porque ocurren varias cosas: primero, el compilador detecta el intento de o operar sobre dos variables que no son del mismo tipo; segundo, el compilador detecta, en sus reglas internas, la posibilidad de cambiar uno de los tipos (int en este caso) al otro (float); tercero, el compilador realiza la conversi´n, y finalmente la operaci´n se o o puede llevar a cabo. Entender este proceso nos permitir´ aprovechar las posibilidades a de la conversi´n impl´ o ıcita de tipos cuando nuestro c´digo involucre tipos de variables o m´s complicados, y entender varios mensajes de error del compilador. a Es interesante notar c´mo las conversiones impl´ o ıcitas de tipos pueden tener consecuencias insospechadas. Consideremos las tres expresiones: i) x = (1/2) * (x + a/x) ; ii) x = (0.5) * (x + a/x) ; iii) x = (x + a/x)/2 ; Si inicialmente x=0.5 y a=0.5, por ejemplo, i) entrega el valor x=0, mientras ii) y iii) entregan el valor x=1.5. Lo que ocurre es que 1 y 2 son enteros, de modo que 1/2 = 0. De acuerdo a lo que dijimos, uno esperar´ que en i), como conviven n´meros reales ıa u con enteros, los n´meros enteros fueran convertidos a reales y, por tanto, la expresi´n u o tuviera el resultado esperado, 1.5. El problema es la prioridad de las operaciones. No todas las operaciones tienen igual prioridad (las multiplicaciones y divisiones se realizan antes que las sumas y restas, por ejemplo), y esto permite al compilador decidir cu´l a operaci´n efectuar primero. Cuando se encuentra con operaciones de igual prioridad o (dos multiplicaciones, por ejemplo), se procede a efectuarlas de izquierda a derecha. Pues bien, en i), la primera operaci´n es 1/2, una divisi´n entre enteros, i.e. cero. En o o ii) no hay problema, porque todas son operaciones entre reales. Y en iii) la primera

98

´ CAP´ ITULO 4. UNA BREVE INTRODUCCION A C++. operaci´n es el par´ntesis, que es una operaci´n entre reales. Al dividir por 2 ´ste es o e o e convertido a real antes de calcular el resultado. i) a´n podr´ utilizarse, cambiando el prefactor del par´ntesis a 1.0/2.0, una pr´ctica u ıa e a que ser´ conveniente adoptar como standard cuando queremos utilizar enteros denıa tro de expresiones reales, para evitar errores que pueden llegar a ser muy dif´ ıciles de detectar.

4.2.
4.2.1.

Control de flujo.
if, if... else, if... else if.

Las construcciones siguientes permiten controlar el flujo del programa en base a si una expresi´n l´gica es verdadera o falsa. o o a) En el caso de la sentencia if se evaluar´ la expresi´n (a==b), si ella es cierta ejecutar´ la a o a o las l´ ıneas entre los par´ntesis de llave y si la expresi´n es falsa el programa se salta e o esa parte del c´digo. o if (a==b) { cout << "a es igual a b" << endl; } En este y en muchos de los ejemplos que siguen, los par´ntesis cursivos son opcionales. e Ellos indican simplemente un grupo de instrucciones que debe ser tratado como una sola instrucci´n. En el ejemplo anterior, los par´ntesis cursivos despu´s del if (o despu´s de o e e e un while, for, etc. m´s adelante) indican el conjunto de instrucciones que deben o no a ejecutarse dependiendo de si cierta proposici´n es verdadera o falsa. Si ese conjunto de o instrucciones es una sola, se pueden omitir los par´ntesis: e if (a==b) cout << "a es igual a b" << endl; b) En el caso if... else hay dos acciones mutuamente excluyentes. La sentencia if (c!=b) evaluar´ la expresi´n (c!=b). Si ella es cierta ejecutar´ la o las l´ a o a ıneas entre los par´ntesis de llave que le siguen, salt´ndose la o las l´ e a ıneas entre los par´ntesis de e llave que siguen a la palabra clave else. Si la expresi´n es falsa el programa se salta la o primera parte del c´digo y s´lo ejecuta la o las l´ o o ıneas entre los par´ntesis de llave que e siguen a else. if (c!=d) { cout << "c es distinto de d" << endl; } else { cout << "c es igual a d" << endl; }

4.2. CONTROL DE FLUJO.

99

c) En el ultimo caso se evaluar´ la expresi´n que acompa˜a al if y si ella es cierta se ´ a o n ejecutar´ la o las l´ a ıneas entre los par´ntesis de llave que le siguen, salt´ndose todo el e a resto de las l´ ıneas entre los par´ntesis de llave que siguen a las palabras claves else if e y else. Si la primera expresi´n es falsa el programa se salta la primera parte del c´digo o o y eval´a la expresi´n que acompa˜a al primer else if y si ella es cierta ejecutar´ la u o n a o las l´ ıneas entre los par´ntesis de llave que le siguen, salt´ndose todo el resto de las e a l´ ıneas entre los par´ntesis que siguen a otros eventuales else if o al else. Si ninguna e de las expresiones l´gicas resulta cierta se ejecutar´ la o las l´ o a ıneas entre los par´ntesis e que siguen al else. if (e > f) { cout << "e es mayor que f" << endl; } else if (e == f) { cout << "e es igual a f" << endl; } else { cout << "e es menor que f" << endl; } Para C++, una expresi´n verdadera es igual a 1, y una falsa es igual a 0. Esto es, cuando o escribimos if(e>f), y e>f es falsa, en realidad estamos diciendo if(0). A la inversa, 0 es considerada una expresi´n falsa, y cualquier valor no nulo es considerado una expresi´n o o verdadera. As´ podr´ ı, ıamos hacer que una porci´n del c´digo siempre se ejecute (o nunca) o o poniendo directamente if(1) o if(0), respectivamente. Naturalmente, lo anterior no tiene mucho sentido, pero un error habitual (y particularmente dif´ de detectar) es escribir a = b en vez de a == b en una expresi´n l´gica. Esto ıcil o o normalmente trae consecuencias indeseadas, pues la asignaci´n a = b es una funci´n que se o o eval´a siempre al nuevo valor de a. En efecto, una expresi´n como a=3 siempre equivale a u o verdadero, y a=0 siempre equivale a falso. Por ejemplo, en el siguiente programa: #include <iostream> using namespace std; int main(){ int k=3; if (k==3){ cout << "k es igual a 3" << endl; } k=4; if (k=3){ cout << "k es igual a 3" << endl; } return 0; }

100 la salida siempre es: k es igual a 3 k es igual a 3

´ CAP´ ITULO 4. UNA BREVE INTRODUCCION A C++.

aunque entre los dos if el valor de k cambia.

4.2.2.

Expresi´n condicional. o

Una construcci´n if else simple, que s´lo asigna un valor distinto a una misma variable o o seg´n si una proposici´n es verdadera o falsa, es muy com´n en programaci´n. Por ejemplo: u o u o if (a==b) { c = 1; } else { c = 0; } ´ Existen dos maneras de compactar este c´digo. Este se puede reemplazar por o if (a==b) c = 1; else c = 0; Sin embargo, esto no es recomendable por razones de claridad al leer el c´digo. Una expresi´n o o m´s compacta y clara, se consigue usando el operador ternario ? : a c = (a==b) ? 1 : 0; Como en el caso de los operadores de incremento y decremento, el uso del operador ? es preferible para optimizar el ejecutable resultante.

4.2.3.

switch.

La instrucci´n switch permite elegir m´ltiples opciones a partir del valor de una variable o u entera. En el ejemplo siguiente tenemos que si i==1 la ejecuci´n continuar´ a partir del caso o a case 1:, si i==2 la ejecuci´n continuar´ a partir del caso case 2: y as´ sucesivamente. Si o a ı i toma un valor que no est´ enumerado en ning´n case y existe la etiqueta default, la a u ejecuci´n continuar´ a partir de ah´ Si no existe default, la ejecuci´n contin´a luego del o a ı. o u ultimo par´ntesis cursivo. ´ e switch (i) { case 1: { cout << "Caso 1." << endl; } break; case 2:

4.2. CONTROL DE FLUJO. { cout << "Caso 2." << endl; } break; default: { cout << "Otro caso." << endl; } break; }

101

La instrucci´n break permite que la ejecuci´n del programa salte a la l´ o o ınea siguiente despu´s e de la serie de instrucciones asociadas a switch. De esta manera s´lo se ejecutar´n las l´ o a ıneas correspondientes al case elegido y no el resto. Por ejemplo, si i==1 ver´ ıamos en pantalla s´lo la l´ o ınea Caso 1. En el otro caso, si no existieran los break, y tambi´n i==1, entonces e ver´ ıamos en pantalla las l´ ıneas Caso 1., Caso 2. y Otro caso. La instrucci´n default es o opcional.

4.2.4.

for.

Una instrucci´n que permite repetir un bloque de instrucciones un n´mero definido de o u veces es el for. Su sintaxis comienza con una o varias inicializaciones, luego una condici´n o l´gica de continuaci´n mientras sea verdadera, y finalmente una o m´s expresiones que se o o a eval´an vuelta por vuelta no incluyendo la primera vez. Siguiendo al for(...) viene una u instrucci´n o un bloque de ellas encerradas entre par´ntesis de llave. En el ejemplo siguiente o e la variable entera i es inicializada al valor 1, luego se verifica que la condici´n l´gica sea o o cierta y se ejecuta el bloque de instrucciones. A la vuelta siguiente se eval´a la expresi´n a u o la extrema derecha (suele ser uno o m´s incrementadores), se verifica que la condici´n l´gica a o o se mantenga cierta y se ejecuta nuevamente el bloque de instrucciones. Cuando la condici´n o l´gica es falsa se termina el loop, saltando la ejecuci´n a la l´ o o ınea siguiente al par´ntesis que e indica el fin del bloque de instrucciones del for. En este ejemplo, cuando i=4 la condici´n o de continuaci´n ser´ falsa y terminar´ la ejecuci´n del for. o a a o for (int i = 1; i < 4; i++) { cout << "Valor del indice: " << i << endl; } El output correspondiente es: Valor del indice: 1 Valor del indice: 2 Valor del indice: 3 Cualquier variable declarada en el primer argumento del for es local al loop. En este caso, la variable i es local, y no interfiere con otras posibles variables i que existan en nuestro c´digo. o

102

´ CAP´ ITULO 4. UNA BREVE INTRODUCCION A C++.

for es una instrucci´n particularmente flexible. En el primer y tercer argumento del for o se puede colocar m´s de una instrucci´n, separadas por comas. Esto permite, por ejemplo, a o involucrar m´s de una variable en el ciclo. El c´digo: a o for (int i=0, k=20; (i<10) && (k<50); i++, k+=6) { cout << "i + k = " << i + k << endl; } resulta en el output: i i i i i + + + + + k k k k k = = = = = 20 27 34 41 48

Adem´s, la condici´n de continuaci´n (segundo argumento del for), no tiene por qu´ dea o o e pender de las variables inicializadas en el primer argumento. Y el tercer argumento no tiene por qu´ ser un incremento o decremento de las variables del loop; puede ser cualquier expree si´n que queramos ejecutar cada vez que un ciclo termina. En el siguiente ejemplo, adem´s o a de incrementar los contadores en cada ciclo, se env´ un mensaje a pantalla: ıa for (int i=1, k=2;k<5 && i<20;k++, i+=2, cout << "Fin iteracion" << endl){ cout << " i = " << i <<’’,’’; cout << " k = " << k << endl; } El resultado de las iteraciones: i = 1, k = 2 Fin iteracion i = 3, k = 3 Fin iteracion i = 5, k = 4 Fin iteracion Todos los argumentos del for son opcionales (no los ;), por lo cual se puede tener un for que carezca de inicializaci´n y/o de condici´n de continuaci´n y/o de una expresi´n que se o o o o eval´e en cada iteraci´n. u o Un caso t´ ıpico en que se aprovecha la opcionalidad de los argumentos del for es para tener un loop infinito, que puede servir para dejar el programa en pausa indefinida. Para salir del loop (y en general, para detener cualquier programa en C++), hay que presionar ^C: for (; ; ) cout << "Este es un loop infinito, ^C para detenerlo"<< endl; Se puede adem´s, salir abruptamente del loop con break. El c´digo: a o

4.2. CONTROL DE FLUJO. for(int indice=0; indice<10; indice++) { int cuadrado = indice*indice ; cout << indice << " " ; if(cuadrado > 10 ) break ; } cout << endl; da la salida a pantalla: 0 1 2 3 4

103

aun cuando la condici´n de continuaci´n permite que indice llegue hasta 9. o o Finalmente, las variables involucradas en el for pueden ser modificadas dentro del ciclo. Por ejemplo, modifiquemos uno de los ejemplos anteriores, cambiando la variable k en medio del ciclo: for (int i=1, k=2;k<5 && i<8;k++, i+=2, cout << "Fin iteracion" << endl){ cout << " i = " << i << ", k = " << k << endl; k = k+5; } El resultado es: i = 1, k = 2 Fin iteracion En vez de pasar por el ciclo tres veces, como ocurr´ originalmente, el programa sale del loop, ıa al cabo del primer ciclo, k = 2 + 5 = 7 > 5. En general no es una buena pr´ctica modificar las variables internas del ciclo en medio a de ´l, porque no es muy ordenado, y el desorden normalmente conduce a los errores en e programaci´n, pero ocasionalmente puede ser util hacer uso de esta libertad que proporciona o ´ el lenguaje. Los ciclos for pueden anidarse, tal que uno contenga a otro completamente.

4.2.5.

while.

La instrucci´n while permite repetir un bloque de instrucciones encerradas entre par´nteo e sis de llave mientras la condici´n l´gica que acompa˜a al while se mantenga cierta. La cono o n dici´n es evaluada antes de que comience la primera iteraci´n; si es falsa en ´sta o en una o o e posterior evaluaci´n no se ejecuta el bloque de instrucciones que le siguen y se contin´a la o u ejecuci´n en la l´ o ınea siguiente al par´ntesis que indica el fin del bloque asociado al while. e Hay que notar que la instrucci´n while podr´ no ejecutarse ni una sola vez si la condici´n o ıa o no se cumple inicialmente. Un ejemplo simple: int i=1; while (i < 3) { cout << i++ << " "; }

104

´ CAP´ ITULO 4. UNA BREVE INTRODUCCION A C++.

que da por resultado: 1 2. En el siguiente loop, la salida ser´: 5 4 3 2 1 (¿Por qu´?) a e int k=5 ; while(k) { cout << k-- <<" "; }

4.2.6.

do... while.

La instrucci´n do... while es an´loga a while, salvo que la condici´n l´gica es evaluada o a o o despu´s de la primera iteraci´n. Por tanto, el bloque se ejecuta al menos una vez, siempre. e o Un ejemplo simple: do { cout << i++ << endl; } while (i<=20); Podemos construir de otra manera un loop infinito usando do while do { cout << "Este es un segundo loop infinito, ^C para detenerlo"<< endl; } while (1);

4.2.7.

goto.

Existe tambi´n en C++ una instrucci´n goto que permite saltar de un punto a otro del e o programa (goto salto; permite saltar a la l´ ınea que contiene la instrucci´n salto:). Sin o embargo, se considera una mala t´cnica de programaci´n usar goto, y siempre se puede die o se˜ar un programa evit´ndolo. Es altamente no recomendable, pero si su utilizaci´n simplifica n a o el c´digo se puede usar. o

4.3.

Funciones.

Las funciones nos permiten programar partes del procedimiento por separado. Un ejemplo simple de ellas lo vimos en la subsecci´n 4.1.2. o

4.3.1.

Funciones tipo void.

Un caso especial de funciones es aquel en que el programa que llama la funci´n no espera o que ´sta le entregue ning´n valor al terminar. Por ejemplo, en la subsecci´n 4.1.2, la funci´n e u o o PrintHola simplemente imprime un mensaje en pantalla. El resto del programa no necesita de ning´n resultado parcial proveniente de la ejecuci´n de dicha funci´n. La definici´n de u o o o estas funciones debe ir precedida de la palabra void, como en el ejemplo citado.

4.3. FUNCIONES.

105

4.3.2.

return.

Si deseamos definir una funci´n que calcule una ra´ cuadrada, evidentemente esperamos o ız que la funci´n nos entregue un resultado: el valor de la ra´ cuadrada. En este caso hay que o ız traspasar el valor de una variable desde la funci´n al programa que la llam´. Esto se consigue o o con return. Veamos un ejemplo muy simple: int numero(){ int i = 3; return i; } int main(){ cout << "Llamamos a la funcion" << endl; cout << "El numero es: " << numero() << endl; int i = 5; i = i + numero(); cout << "El numero mas 5 es: " << i << endl; return 0; } En este caso, la funci´n simplemente entrega el valor de la variable interna i, es decir 3, el o cual puede ser usado para salida en pantalla o dentro de operaciones matem´ticas corrientes. a Separando declaraci´n e implementaci´n de la funci´n, el ejemplo anterior se escribe: o o o int numero(); int main(){ ... } int numero(){ int i = 3; return i; } Dos observaciones utiles: ´ a) La declaraci´n de la funci´n lleva antepuesto el tipo de variable que la funci´n entrega. o o o En el ejemplo, la variable entregada es un entero, i, y la declaraci´n debe ser, por tanto, o int numero(). Podemos tener funciones tipo double, char, long, etc., de acuerdo al tipo de variable que corresponde a return. b) La variable i que se usa dentro de main() y la que se usa dentro de numero() son distintas. A pesar de que tienen el mismo nombre, se pueden usar independientemente como si se llamaran distinto. Se dice que i es una variable local. Despu´s de return debe haber una expresi´n que se eval´e a una variable del tipo correse o u pondiente, ya sea expl´ ıcitamente o a trav´s de un cast impl´ e ıcito. Las siguientes funciones devuelven un double al programa:

106 double f1(){ double l = 3.0; return l; } double f2(){ double l = 3.0, m = 8e10; return l*m; } double f3(){ int l = 3; return l; }

´ CAP´ ITULO 4. UNA BREVE INTRODUCCION A C++.

Sin embargo, la siguiente funci´n har´ que el compilador emita una advertencia, pues se o a est´ tratando de devolver un double donde deber´ ser un int, y la conversi´n implica una a ıa o p´rdida de precisi´n: e o int f4(){ double l=3.0; return l; } Naturalmente, podemos modificar la funci´n anterior haciendo una conversi´n expl´ o o ıcita antes de devolver el valor: return int(l).

4.3.3.

Funciones con par´metros. a

Volviendo al ejemplo de la ra´ cuadrada, nos gustar´ llamar a esta funci´n con un ız ıa o par´metro (el n´mero al cual se le va a calcular la ra´ cuadrada). Consideremos por ejemplo a u ız una funci´n que necesita un solo par´metro, de tipo int, y cuyo resultado es otro int: o a int funcion(int i){ i+=4; return i; } int main(){ int i = 3; cout << "El valor de la funcion es " << funcion(i) << endl; cout << "El valor del parametro es " << i << endl; return 0 ; } El resultado en pantalla es:

4.3. FUNCIONES. El valor de la funcion es 7 El valor del parametro es 3

107

La funci´n funcion entrega el valor del par´metro m´s 4. Usamos el mismo nombre (i) o a a para las variables en main y funcion, pero son variables locales, as´ que no interfieren. Lo ı importante es notar que cuando se llama a la funci´n, la reasignaci´n del valor de i (i+=4) o o ocurre s´lo para la variable local en funcion; el par´metro externo mantiene su valor. o a Separando declaraci´n e implementaci´n el ejemplo anterior se escribe: o o int funcion(int); int main(){...} int funcion(int i){ i+=4; return i; } Si nuestra funci´n necesita m´s par´metros, basta separarlos con comas, indicando para o a a cada uno su tipo: int funcion2(int,double); void funcion3(double,int,float); double funcion4(float); El compilador verifica cuidadosamente que cada funci´n sea llamada con el n´mero de o u par´metros adecuados, y que cada par´metro corresponda al tipo especificado. En los ejema a plos anteriores, funcion2 debe ser llamada siempre con dos argumentos, el primero de los cuales es int y el segundo double. Como siempre, puede ser necesario un cast impl´ ıcito (si se llama funcion2 con el segundo argumento int, por ejemplo), pero si no existe una regla de conversi´n autom´tica (llamando a funcion2 con el primer argumento double, por ejemplo), o a el compilador enviar´ una advertencia. Adem´s, el compilador verifica que el valor de retorno a a de la funci´n sea usado como corresponde. Por ejemplo, en las dos l´ o ıneas: double m = funcion2(2,1e-3); int k = funcion4(0.4); la primera compilar´ exitosamente (pero hay un cast impl´ a ıcito), y la segunda dar´ una a advertencia. Existen dos modos de transferir par´metros a una funci´n: a o a) Por valor. Se le pasan los par´metros para que la funci´n que es llamada copie sus a o valores en sus propias variables locales, las cuales desaparecer´n cuando la funci´n a o termine y no tienen nada que ver con las variables originales. Hasta ahora, en todos los ejemplos de esta subsecci´n el traspaso de par´metros ha sido o a por valor. En la funci´n int funcion(int), en el c´digo de la p´gina 106, lo que ha o o a ocurrido es que la funci´n copia el valor de la variable externa i en una nueva variable o (que tambi´n se llama i, pero est´ en otra direcci´n de memoria). El valor con el que e a o trabaja la funci´n es la copia, manteniendo inalterada la variable original. o

108

´ CAP´ ITULO 4. UNA BREVE INTRODUCCION A C++.

b) Por referencia. Se le pasa la direcci´n de memoria de los par´metros. La funci´n llamada o a o puede modificar el valor de tales variables. La misma funci´n de la p´gina 106 puede ser modificada para que el paso de par´metros o a a sea por referencia, modificando la declaraci´n: o int funcion(int &); int main() { int i = 3; cout << "El valor de la funcion es " << funcion(i) << endl; cout << "El valor del parametro es " << i << endl; return 0; } int funcion(int & i) { i+=4; return i; } En vez de traspasarle a funcion el valor del par´metro, se le entrega la direcci´n a o de memoria de dicha variable. Debido a ello, funcion puede modificar el valor de la variable. El resultado en pantalla del ultimo programa ser´: ´ a El valor de la funcion es 7 El valor del parametro es 7 Debido a que las variables dejan de ser locales, el paso de par´metros por referencia a debe ser usado con sabidur´ De hecho el ejemplo presentado es poco recomendable. ıa. Peor a´n, el problema es no s´lo que las variables dejan de ser locales, sino que es u o imposible saber que no lo son desde el main. En efecto, el main en ambas versiones de funcion es el mismo. Lo unico que cambi´ es la declaraci´n de la funci´n. Puesto que un ´ o o o usuario normal usualmente no conoce la declaraci´n e implementaci´n de cada funci´n o o o que desea usar (pues pueden haber sido hechas por otros programadores), dejamos al usuario en la indefensi´n. o Por otro lado, hay al menos dos situaciones en que el paso de referencia es la unica ´ opci´n viable para entregar los par´metros. Un caso es cuando hay que cuidar el uso o a de la memoria. Supongamos que una funci´n necesita un par´metros que es una matriz o a de 10 millones de filas por 10 millones de columnas. Seguramente estaremos llevando al l´ ımite los recursos de nuestra m´quina, y ser´ una torpeza pasarle la matriz por valor: a ıa ello involucrar´ primero, duplicar la memoria utilizada, con el consiguiente riesgo de ıa, que nuestro programa se interrumpa; y segundo, har´ el programa m´s lento, porque ıa a la funci´n necesitar´ llenar su versi´n local de la matriz elemento por elemento. Es o ıa o decir, nada de eficiente. En esta situaci´n, el paso por referencia es lo adecuado. o

4.3. FUNCIONES.

109

Un segundo caso en que el paso por referencia es recomendable es cuando efectivamente nuestra intenci´n es cambiar el valor de las variables. El ejemplo t´ o ıpico es el intercambio de dos variables entre s´ digamos a1=1 y a2=3. Luego de ejecutar la funci´n queremos ı, o que a1=3 y a1=1. El siguiente c´digo muestra la definici´n y el uso de una funci´n para o o o esta tarea, y por cierto requiere el paso de par´metros por referencia: a #include <iostream> void swap(int &,int &); using namespace std; int main(){ int i = 3, k=10; swap(i,k); cout << "Primer argumento: " << i << endl; cout << "Segundo argumento: " << k << endl; return 0 ; } void swap(int & j,int & p){ int temp = j; j = p; p = temp; } El output es: Primer argumento: 10 Segundo argumento: 3 En el ejemplo de la matriz anterior, ser´ interesante poder pasar el par´metro por refeıa a rencia, para ahorrar memoria y tiempo de ejecuci´n, pero sin correr el riesgo de que nuestra o matriz gigantesca sea modificada por accidente. Afortunadamente existe el modo de hacerlo, usando una palabra que ya hemos visto antes: const. En el siguiente c´digo: o int f5(const int &); int main(){...} int f5(const int & i){...}; f5 recibir´ su unico argumento por referencia, pero, debido a la presencia del modificador a ´ const, el compilador avisar´ si se intenta modificar el argumento en medio del c´digo de la a o funci´n. o

4.3.4.

Par´metros por defecto. a

C++ permite que omitamos algunos par´metros de la funci´n llamada, la cual reema o plaza los valores omitidos por otros predeterminados. Tomemos por ejemplo la funci´n o

110

´ CAP´ ITULO 4. UNA BREVE INTRODUCCION A C++.

int funcion(int); de la subsecci´n 4.3.3, y modifiqu´mosla de modo que si no le entregao e mos par´metros, asuma que el n´mero entregado fue 5: a u int funcion(int i = 5){ i+=4; return i; } int main(){ cout << "El resultado default es " << funcion() << endl; int i = 3; cout << "Cuando el parametro vale " << i << " el resultado es " << funcion(i) << endl; return 0; } El output correspondiente es: El resultado default es 9 Cuando el parametro vale 3 el resultado es 7 Separando declaraci´n e implementaci´n: o o int funcion(int = 5); main(){...} int funcion(int i){ i+=4; return i; } Si una funci´n tiene n argumentos, puede tener m ≤ n argumentos opcionales. La unica o ´ restricci´n es que, en la declaraci´n e implementaci´n de la funci´n, los par´metros opcionales o o o o a ocupen los ultimos m lugares: ´ void f1(int,int = 4); int f2(double,int = 4, double = 8.2); double f3(int = 3,double = 0.0, int = 0); En este caso, f1(2), f1(2,8), f2(2.3,5), f3(3), f3(), y muchas otras, son todas llamadas v´lidas de estas funciones. Cada vez, los par´metros no especificados son reemplazados por a a sus valores predeterminados.

4.3.5.

Ejemplos de funciones: ra´ cuadrada y factorial. ız

Ra´ cuadrada. ız Con lo visto hasta ahora, ya podemos escribir un programa que calcule la ra´ cuadrada ız de una funci´n. Para escribir una funci´n, debemos tener claro qu´ se espera de ella: cu´ntos o o e a

4.3. FUNCIONES.

111

y de qu´ tipo son los argumentos que recibir´, qu´ tipo de valor de retorno deber´ tener, e a e a y, por cierto, un nombre adecuado. Para la ra´ cuadrada, es claro que el argumento es un ız n´mero. Pero ese n´mero podr´ ser un entero o un real, y eso al compilador no le da lo u u ıa mismo. En este punto nos aprovechamos del cast impl´ ıcito: en realidad, basta definir la ra´ ız cuadrada con argumento double; de este modo, si se llama la funci´n con un argumento int, o el compilador convertir´ autom´ticamente el int en double y nada fallar´. En cambio, si la a a a defini´ramos para int y la llamamos con argumento double, el compilador se quejar´ de que e ıa no sabe efectuar la conversi´n. Si el argumento es double, evidentemente esperamos que el o valor de retorno de la funci´n sea tambi´n un double. Llamando a la funci´n raiz, tenemos o e o la declaraci´n: o double raiz(double); Debido a la naturaleza de la funci´n ra´ cuadrada, raiz() no tendr´ sentido, y por tanto o ız ıa no corresponde declararla con un valor default. Ahora debemos pensar en c´mo calcular la ra´ cuadrada. Usando una variante del m´todo o ız e de Newton-Raphson, se obtiene que la secuencia xn+1 = 1 2 xn + a xn

√ converge a a cuando n → ∞. Por tanto, podemos calcular la ra´ cuadrada con aproximaız ciones sucesivas. El c´lculo terminar´ en el paso N , cuando la diferencia entre el cuadrado a a de la aproximaci´n actual, xN , y el valor de a, sea menor que un cierto n´mero peque˜o: o u n 1. El valor de determinar´ la precisi´n de nuestro c´lculo. Un ejemplo de a o a | x2 − a | < N c´digo lo encontramos a continuaci´n: o o #include <iostream> #include <cmath> using namespace std; double raiz(double); int main(){ double r; cout.precision(20); cout << "Ingrese un numero: " << endl; cin >> r; cout << raiz(r) << endl; return 0 ; } double raiz(double a){ double x =a/2.0 ; // para comenzar double dx = 1e3, epsilon = 1e-8;

112

´ CAP´ ITULO 4. UNA BREVE INTRODUCCION A C++.

while (fabs(dx)>epsilon){ x = (x + a/x)/2; dx = x*x - a; cout << "x = " << x << ", precision = " << dx << endl; } return x; } Luego de la declaraci´n de la funci´n raiz, est´ main, y al final la implementaci´n de o o a o raiz. En main se pide al usuario que ingrese un n´mero, el cual se aloja en la variable r, u y se muestra en pantalla el valor de su ra´ cuadrada. La instrucci´n cout.precision(20) ız o permite que la salida a pantalla muestre el resultado con 20 cifras significativas. En la implementaci´n de la funci´n hay varios aspectos que observar. Se ha llamado x a la o o variable que contendr´ las sucesivas aproximaciones a la ra´ Al final del ciclo, x contendr´ el a ız. a valor (aproximado) de la ra´ cuadrada. dx contiene la diferencia entre el cuadrado de x y el ız valor de a, epsilon es el n´mero (peque˜o) que determina si la aproximaci´n es satisfactoria u n o o no. El ciclo est´ dado por una instrucci´n while, y se ejecuta mientras dx>epsilon, es decir, a o termina cuando dx es suficientemente peque˜o. El valor absoluto del real dx se obtiene con la n funci´n matem´tica fabs, disponible en el header cmath incluido al comienzo del programa. o a Observar que inicialmente dx=1e3, esto es un valor muy grande; esto permite que la condici´n o del while sea siempre verdadera, y el ciclo se ejecuta al menos una vez. Dentro del ciclo, se calcula la nueva aproximaci´n, y se env´ a pantalla un mensaje con o ıa la aproximaci´n actual y la precisi´n alcanzada (dada por dx). Eventualmente, cuando la o o aproximaci´n es suficientemente buena, se sale del ciclo y la funci´n entrega a main el valor o o de x actual, que es la ultima aproximaci´n calculada. ´ o Factorial. Otro ejemplo util es el c´lculo del factorial, definido para n´meros naturales: ´ a u n! = n · (n − 1) · · · 2 · 1 , 0! ≡ 1 .

La estrategia natural es utilizar un ciclo for, determinado por una variable entera i, que va desde 1 a n, guardando los resultados en una variable auxiliar que contiene el producto de todos los n´meros naturales desde 1 hasta i: u #include <iostream> using namespace std; int factorial(int); int main(){ int n=5 ; cout << "El factorial de " << n << " es: " << factorial(n) << endl;

4.3. FUNCIONES. return 0 ; } int factorial(int i) { int f =1; for (int j=1;j<=i;j++){ f = f*j; } return f; }

113

Observar que la variable auxiliar f, que contiene el producto de los primeros i n´meros u naturales, debe ser inicializada a 1. Si se inicializara a 0, factorial(n) ser´ 0 para todo n. ıa Esta funci´n no considera el caso n=0, pero al menos para el resto de los naturales funo cionar´ bien. a

4.3.6.

Alcance, visibilidad, tiempo de vida.

Con el concepto de funci´n hemos apreciado que es posible que coexistan variables con el o mismo nombre en puntos distintos del programa, y que signifiquen cosas distintas. Conviene entonces tener en claro tres conceptos que est´n ligados a esta propiedad: a Alcance (scope) La secci´n del c´digo durante la cual el nombre de una variable puede ser o o usado. Comprende desde la declaraci´n de la variable hasta el final del cuerpo de la o funci´n donde es declarada. o Si la variable es declarada dentro de una funci´n es local . Si es definida fuera de todas o las funciones (incluso fuera de main), la variable es global. Visibilidad Indica cu´les de las variables, actualmente al alcance, pueden ser accesadas. En a u a nuestros ejemplos (subsecci´n 4.3.3), la variable i en main a´n est´ al alcance dentro o de la funci´n funcion, pero no es visible, y por eso es posible reutilizar el nombre. o Tiempo de vida Indica cu´ndo las variables son creadas y cu´ndo destruidas. En general a a este concepto coincide con el alcance (las variables son creadas cuando son declaradas y destruidas cuando la funci´n dentro de la cual fueron declaradas termina), salvo porque o es posible definir: (a) variables din´micas, que no tienen alcance, sino s´lo tiempo de a o vida; (b) variables est´ticas, que conservan su valor entre llamadas sucesivas de una a funci´n (estas variables tienen tiempo de vida mayor que su alcance). Para declarar o estas ultimas se usa un modificador static. ´ El efecto del modificador static se aprecia en el siguiente ejemplo: #include <iostream> int f();

114 using namespace std; int main(){ cout << f() << endl; cout << f() << endl; return 0; } int f(){ int x=0; x++; return x; }

´ CAP´ ITULO 4. UNA BREVE INTRODUCCION A C++.

La funci´n f simplemente toma el valor inicial de x y le suma 1. Como cada vez que la o funci´n es llamada la variable local x es creada e inicializada, el resultado de este programa o es siempre un 1 en pantalla: 1 1 Ahora modifiquemos la funci´n, haciendo que x sea una variable est´tica: o a #include <iostream> int f(); using namespace std; int main(){ cout << f() << endl; cout << f() << endl; return 0 ; } int f(){ static int x=0; x++; return x; } Ahora, al llamar a f por primera vez, la variable x es creada e inicializada, pero no destruida cuando la funci´n termina, de modo que conserva su valor cuando es llamada por o segunda vez: 1 2

4.3. FUNCIONES. Veamos un ejemplo de una variable est´tica en el c´lculo del factorial: a a int factorial2(int i=1){ static int fac = 1; fac*=i; return fac ; } int main (){ int n=5; int m=n; while(n>0) factorial2(n--); cout << "El factorial de "<< m << " es = " << factorial2() << endl; return 0 ; }

115

La idea, si se desea calcular el factorial de 5, por ejemplo, es llamar a la funci´n factorial2 o una vez, con argumento n = 5, y despu´s disminuir n en 1. Dentro de la funci´n, una variable e o est´tica (fac) aloja el valor 1 ∗ 5 = 5. Luego se llama nuevamente con n = 4, con lo cual a fac=1*5*4, y as´ sucesivamente, hasta llegar a n = 1, momento en el cual fac=1*5*4*3*2*1. ı Al disminuir n en 1 una vez m´s, la condici´n del while es falsa y se sale del ciclo. Al llamar a o una vez m´s a factorial2, esta vez sin argumentos, el programa asume que el argumento a tiene el valor predeterminado 1, y as´ el resultado es 1*5*4*3*2*1*1, es decir 5!. ı Observemos el uso del operador de decremento en este programa: factorial2(n--) llama ´ a la funci´n con argumento n y despu´s disminuye n en 1. Esto es porque el operador de o e decremento est´ actuando como sufijo, y es equivalente a las dos instrucciones: a factorial2(n); n--; Si fuera un prefijo [factorial2(n--)], primero disminuir´ n en 1, y llamar´ luego a factorial2 ıa ıa con el nuevo valor de n Este ejemplo de c´lculo del factorial ilustra el uso de una variable est´tica, que aloja los a a productos parciales de los n´meros enteros, pero no es un buen ejemplo de una funci´n que u o calcule el factorial, porque de hecho esta funci´n no lo calcula: es main quien, a trav´s de o e sucesivas llamadas a factorial2, calcula el factorial, pero la funci´n en s´ no. o ı

4.3.7.

Recursi´n. o

C++ soporta un tipo especial de t´cnica de programaci´n, la recursi´n, que permite que e o o una funci´n se llame a s´ misma (esto es no trivial, por cuanto si definimos, digamos, una o ı funci´n f, dentro del cuerpo de la implementaci´n no hay ninguna declaraci´n a una funci´n o o o o f, y por tanto en principio no se podr´ usar f porque dicho nombre no estar´ en scope; ıa ıa C++ permite soslayar este hecho). La recursi´n permite definir de modo muy compacto una o funci´n que calcule el factorial de un n´mero entero n. o u

116

´ CAP´ ITULO 4. UNA BREVE INTRODUCCION A C++.

int factorial3(int n){ return (n<2) ? 1: n * factorial3(n-1); } int main(){ int n=5; cout << "El factorial de "<< n << " es = " << factorial3(n) << endl; return 0; } En este tercer ejemplo, el factorial de n es definido en funci´n del factorial de n − 1. o Se ha usado la expresi´n condicional (operador ?) para compactar a´n m´s el c´digo. Por o u a o ejemplo, al pedir el factorial de 5 la funci´n se pregunta si 5 < 2. Esto es falso, luego, la o funci´n devuelve a main el valor 5*factorial3(4). A su vez, factorial3(4) se pregunta si o 4 < 2; siendo falso, devuelve a la funci´n que la llam´ (es decir, a factorial3(5)), el valor o o 4*factorial3(3). El proceso sigue hasta que factorial(2) llama a factorial3(1). En ese momento, 1 < 2, y la funci´n factorial3(1), en vez de llamar nuevamente al factorial, o devuelve a la funci´n que la llam´ el valor 1. No hay m´s llamadas a factorial3, y el o o a proceso de recursi´n se detiene. El resultado final es que main recibe el valor factorial3(5) o = 5*factorial3(4) = · · · = 5*4*3*2*factorial3(1) = 5*4*3*2*1= 120. Este tercer c´digo para el c´lculo del factorial s´ considera el caso n = 0, y adem´s es m´s o a ı a a eficiente, al ser m´s compacto. a La recursi´n debe ser empleada con cuidado. Es importante asegurarse de que existe o una condici´n para la cual la recursi´n se detenga, de otro modo, caer´ o o ıamos en una recursi´n o infinita que har´ in´til nuestro programa. En el caso del factorial, pudimos verificar que dicha ıa u condici´n existe, por tanto el programa es finito. En situaciones m´s complicadas puede no o a ser tan evidente, y es responsabilidad del programador —como siempre— revisar que todo est´ bajo control. e

4.3.8.

Funciones internas.

Existen muchas funciones previamente implementadas en C++ almacenadas en distintas bibliotecas. Una de las bibliotecas importante es la matem´tica. Para usarla uno debe incluir a el archivo de header <cmath> y luego al compilar agregar al final del comando de compilaci´n o -lm:

g++ -Wall -o <salida> <fuente>.cc -lm

si se desea crear un ejecutable <salida> a partir del c´digo en <fuente>.cc. o Veamos algunas de estas funciones:

4.4. PUNTEROS. pow(x,y) fabs(x) sqrt(x) sin(x) cos(x) tan(x) atan(x) atan2(y, x) exp(x) log(x) log10(x) floor(x) ceil(x) fmod(x,y) Eleva a potencia, xy Valor absoluto Ra´ cuadrada ız Seno y coseno Tangente Arcotangente de x en [−π, π] Arcotangente de y/x en [−π, π] Exponencial Logaritmo natural y logaritmo en base 10 Entero m´s cercano hacia abajo (e.g. floor(3.2)=3) a Entero m´s cercano hacia arriba (e.g. ceil(3.2)=4) a El resto de x/y (e.g. fmod(7.3, 2)=1.3)

117

Para elevar a potencias enteras, es m´s conveniente usar la forma expl´ a ıcita en vez de la funci´n pow, i.e. calcular x^3 como x*x*x es m´s eficiente computacionalmente que pow(x,3), o a ´ debido a los algoritmos que usa pow para calcular potencias. Estos son m´s convenientes a cuando las potencias no son enteras, en cuyo caso no existe una forma expl´ ıcita en t´rminos e de productos.

4.4.

Punteros.

Una de las ventajas de C++ es permitir el acceso directo del programador a zonas de memoria, ya sea para crearlas, asignarles un valor o destruirlas. Para ello, adem´s de los tipos a de variables ya conocidos (int, double, etc.), C++ proporciona un nuevo tipo: el puntero. El puntero no contiene el valor de una variable, sino la direcci´n de memoria en la cual dicha o variable se encuentra. Un peque˜o ejemplo nos permite ver la diferencia entre un puntero y la variable a la cual n ese puntero “apunta”: int main(){ int i = 42; int * p = &i; cout << "El valor del puntero es: " << p << endl; cout << "Y apunta a la variable: " << *p << endl; return 0; } En este programa definimos una variable i entera. Al crear esta variable, el programa reserv´ un espacio adecuado en alg´n sector de la memoria. Luego pusimos, en esa direcci´n o u o de memoria, el valor 42. En la siguiente l´ ınea creamos un puntero a i, que en este caso denominamos p. Los punteros no son punteros a cualquier cosa, sino punteros a un tipo particular de variable. Ello es manifiesto en la forma de la declaraci´n: int * p. En la o misma l´ ınea asignamos a este puntero un valor. Ese valor debe ser tambi´n una direcci´n de e o memoria, y para eso usamos &i, que es la direcci´n de memoria donde est´ i. Ya hemos visto o a antes el uso de & para entregar una direcci´n de memoria, al estudiar paso de par´metros a o a funciones por referencia (4.3.3).

118

´ CAP´ ITULO 4. UNA BREVE INTRODUCCION A C++.

Al ejecutar este programa vemos en pantalla los mensajes: El valor del puntero es: 0xbffff9d8 Y apunta a la variable: 42 Primero obtenemos un n´mero hexadecimal imposible de determinar a priori , y que corresu ponde a la direcci´n de memoria donde qued´ ubicada la variable i. La segunda l´ o o ınea nos da el valor de la variable que est´ en esa direcci´n de memoria: 42. Puesto que * aplicado a o a un puntero entrega el contenido de esa direcci´n de memoria, se le denomina operador de o desreferenciaci´n. o En este ejemplo, hemos creado un puntero que contiene la direcci´n de memoria de una o variable preexistente: declaramos una variable, esa variable queda en alguna direcci´n de o memoria, y despu´s asignamos esa direcci´n de memoria a un puntero. En este caso, podemos e o referirnos a la variable tanto por su nombre (i) como por su puntero asociado (p_i). Tambi´n es posible crear directamente una direcci´n de memoria, sin necesidad de crear e o una variable antes. En este caso, la unica forma de manipular este objeto es a trav´s de su ´ e puntero, porque no existe ninguna variable y por tanto ning´n nombre asociado a ´l. Esto se u e hace con el operador new. El mismo ejemplo anterior puede ser reescrito usando s´lo punteros: o int main(){ int * p = new int; *p = 42; cout << "El valor del puntero es: " << p << endl; cout << "Y apunta a la variable: " << *p << endl; delete p; return 0;

} La primera l´ ınea crea un nuevo puntero a int llamado p. new verifica que haya suficiente memoria para alojar un nuevo int, y si es as´ reserva ese espacio de memoria. En p queda la ı direcci´n de la memoria reservada. Esto es equivalente a la declaraci´n int i; del programa o o anterior, salvo que ahora la unica manera de accesar esa direcci´n de memoria es a trav´s ´ o e del puntero p. A continuaci´n se coloca dentro de esa direcci´n (observar la presencia del o o operador de desreferenciaci´n *) el n´mero 42. El programa manda a pantalla la misma o u informaci´n que la versi´n anterior, salvo que seguramente el valor de p ser´ distinto. o o a Finalmente, ya que el puntero no volver´ a ser usado, la direcci´n de memoria debe ser a o liberada para que nuestro u otros programas puedan utilizarla. Ello se realiza con el operador delete. Todo puntero creado con new debe ser, cuando ya no se utilice, borrado con delete. Ello evitar´ desagradables problemas en nuestro programa debido a fuga de memoria (memory a leak ). Los punteros tienen gran importancia cuando de manejar datos din´micos se trata, es a decir, objetos que son creados durante la ejecuci´n del programa, en n´mero imposible de o u predecir al momento de compilar. Por ejemplo, una aplicaci´n X-windows normal que crea o una, dos, tres, etc. ventanas a medida que uno abre archivos. En este caso, cada ventana es un objeto din´mico, creado durante la ejecuci´n, y la unica forma de manejarlo es a trav´s a o ´ e de un puntero a ese objeto, creado con new cuando la ventana es creada, y destruido con delete cuando la ventana es cerrada.

4.5. MATRICES O ARREGLOS.

119

4.5.
4.5.1.

Matrices o arreglos.
Declaraci´n e inicializaci´n. o o

Podemos declarar (e inicializar inmediatamente) matrices de enteros, reales de doble precisi´n, caracteres, etc., seg´n nuestras necesidades. o u int a[5]; double r[3] = {3.5, 4.1, -10.8}; char palabra[5]; Una vez declarada la matriz (digamos a[5]), los valores individuales se accesan con a[i], con i desde 0 a 4. Por ejemplo, podemos inicializar los elementos de la matriz as´ ı: a[0] = 3; a[3] = 5; ... o si queremos ingresarlos desde el teclado: for (i = 0; i < 5; i++){ cin >> a[i]; } Y si deseamos escribirlos en pantalla: for (i = 0; i < 5; i++){ cout << a[i] ; }

4.5.2.

Matrices como par´metros de funciones. a

Si deseamos, por ejemplo, dise˜ar una funci´n que mande los elementos de una matriz n o a pantalla, necesitamos entregarle como par´metro la matriz que va a utilizar. Para ello se a agrega [] luego del nombre de la variable, para indicar que se trata de una matriz: void PrintMatriz(int, double []); int main(){ double matriz[5] = {3.5, 5.2, 2.4, -0.9, -10.8}; PrintMatriz(5, matriz); return 0; } void PrintMatriz(int i, double a[]){ for (int j = 0; j < i; j++){ cout << "Elemento " << j << " = " << a[j] << endl; } }

120

´ CAP´ ITULO 4. UNA BREVE INTRODUCCION A C++.

Observemos que la funci´n debe recibir dos par´metros, uno de los cuales es la dimensi´n o a o de la matriz. Esto se debe a que cuando las matrices son usadas como par´metros la infora maci´n de su dimensi´n no es traspasada, y debe ser comunicada independientemente. Una o o ligera optimizaci´n al programa anterior es modificar main a: o int main() { int dim = 5; double matriz[dim] = {3.5, 5.2, 2.4, -0.9, -10.8}; PrintMatriz(dim, matriz); return 0; } De este modo, si eventualmente cambiamos de opini´n y deseamos trabajar con matrices o de longitud distinta, s´lo hay que modificar una l´ o ınea de c´digo (la primera) en todo el o programa, el cual puede llegar a ser bastante largo por cierto. (En el ejemplo, tambi´n habr´ e ıa que cambiar la l´ ınea de inicializaci´n de la matriz, porque asume que la matriz requiere s´lo 5 o o elementos, pero de todos modos deber´ ser clara la enorme conveniencia.) Podemos reescribir ıa este programa con un comando de preprocesador para hacer la definici´n de la dimensi´n: o o #include <iostream> #define DIM 5 using namespace std; int main(){ double matriz[DIM] = {3.5, 5.2, 2.4, -0.9, -10.8}; PrintMatriz(DIM, matriz); return 0; }

4.5.3.

Asignaci´n din´mica. o a

La reserva de memoria para la matriz podemos hacerla en forma din´mica ocupando el a operador new que pedir´ al sistema la memoria necesaria, si est´ disponible el sistema se a a la asignar´. Como con cualquier puntero, una vez desocupado el arreglo debemos liberar la a memoria con el comando delete. #include <iostream> using namespace std; int main() { cout<<"Ingrese la dimension deseada :" ; int dim ; cin >> dim ; double * matriz = new double[dim] ; // Reserva la memoria for(int i=0; i < dim; i++) {

4.5. MATRICES O ARREGLOS. cout << "Ingrese elemento "<< i <<" : "; cin >> matriz[i] ; } for (int i=0;i<dim;i++){ cout << matriz[i] << ", "; } cout << endl; delete [] matriz; return 0; } // Libera la memoria reservada

121

Este ejemplo permite apreciar una gran ventaja del uso de punteros, al permitirnos liberarnos de definir la dimensi´n de una matriz como una constante. Aqu´ dim es simplemente un int. o ı, La asignaci´n din´mica permite definir matrices cuya dimensi´n se determina reci´n durante o a o e la ejecuci´n. o Observemos finalmente que la liberaci´n de memoria, en el caso de arreglos, se hace con o el operador delete [], no delete como en los punteros usuales.

4.5.4.

Matrices multidimensionales.

Es f´cil declarar e inicializar matrices de m´s de una dimensi´n: a a o double array[10][8]; int array[2][3] = {{1, 2, 3}, {4, 5, 6}}; Una operaci´n usual es definir primero las dimensiones de la matriz, y luego llenar sus o elementos uno por uno (o desplegarlos en pantalla), recorriendo la matriz ya sea por filas o por columnas. Hay que tener cuidado del orden en el cual uno realiza las operaciones. En el siguiente c´digo, definimos una matriz de 10 filas y 3 columnas, la llenamos con ceros o elemento por elemento, y luego inicializamos tres de sus elementos a n´meros distintos de u cero. Finalmente desplegamos la matriz resultante en pantalla: #include <iostream> using namespace std; int main(){ int dimx=3, dimy=10; double a[dimy][dimx]; for (int i=0;i<dimy;i++){ for (int j=0;j<dimx;j++){ a[i][j]=0;

122 } } a[0][0]=1; a[3][2]=2; a[9][2]=3;

´ CAP´ ITULO 4. UNA BREVE INTRODUCCION A C++.

for (int i=0;i<dimy;i++){ for (int j=0;j<dimx;j++){ cout << a[i][j] << ", "; } cout << endl; } return 0; } Inicializar los elementos a cero inicialmente es particularmente relevante. Si no, la matriz se llenar´ con elementos aleatorios. Veamos un ejemplo a continuaci´n que ilustra el paso de ıa o arreglos multidimensionales como un par´metro a una funci´n y la necesidad de inicializar a a o cero los elementos de un arreglo #include <iostream> #define NROWS 3 #define NCOLUMNS 2 using namespace std; void f(int, int, int [][NCOLUMNS]); int main() { int array[NROWS][NCOLUMNS]; f(NROWS, NCOLUMNS, array); for(int i=0;i<NROWS;i++) { for(int j=0;j<NCOLUMNS;j++) array[i][j]=0; } f(NROWS, NCOLUMNS, array); return 0; } void f(int n, int m, int a[][NCOLUMNS]) { for(int i=0;i<n;i++) { for(int j=0;j<m;j++) cout <<a[i][j]<<" "; cout << endl; } }

4.5. MATRICES O ARREGLOS.

123

4.5.5.

Matrices de caracteres: cadenas (strings).

Una palabra, frase o texto m´s largo es representado internamente por C++ como una a matriz de chars. A esto se le llama “cadena” (string). Sin embargo, esto ocasiona un problema, pues las matrices deben ser definidas con dimensi´n constante (a menos que sean definidas o din´micamente), y las palabras pueden tener longitud arbitraria. La convenci´n de C++ para a o resolver el problema es aceptar que una cadena tiene longitud arbitraria, pero debe indicar d´nde termina. Esto se hace con el char nulo: ’\0’. As´ para asignar a la variable palabra o ı, el valor “Hola”, debe definirse como una matriz de dimensi´n 5 (una m´s que el n´mero de o a u letras): char palabra[5] = {’H’, ’o’, ’l’, ’a’, ’\0’}; Para escribir “Hola” en pantalla basta recorrer los elementos de palabra uno a uno: for (i = 0; i < 5; i++) { cout << palabra[i]; } Si tuvi´ramos que hacer esto cada vez que queremos escribir algo a pantalla no ser´ muy e ıa c´modo. Por ello, tambi´n podemos escribir “Hola” en pantalla simplemente con cout << "Hola", o e y de hecho ´se fue el primer ejemplo de este cap´ e ıtulo. De hecho, la declaraci´n de palabra o podr´ haberse escrito: ıa char palabra[5] = "Hola"; Esto ya es bastante m´s c´modo, aunque persiste la inconsistencia de definir palabra con a o dimensi´n 5, cuando en realidad al lado derecho de la asignaci´n hay un objeto con s´lo 4 o o o elementos (visibles). ´ Este y otros problemas asociados con el manejo convencional de cadenas en C++ se resuelven incluyendo el header string. Usando string. El c´digo anterior se puede reescribir: o #include <iostream> #include <string> using namespace std; int main(){ string palabra = "Hola"; cout << palabra << endl; return 0; }

124

´ CAP´ ITULO 4. UNA BREVE INTRODUCCION A C++.

Observar que la l´ ınea a incluir es #include <string>, sin la extensi´n “.h”. Al incluir o string, las cadenas pueden ser declaradas como objetos tipo string en vez de arreglos de char. El hecho de que ya no tengamos que definir a priori la dimensi´n de la cadena o es una gran ventaja. De hecho, permite ingresar palabras desde el teclado trivialmente, sin preocuparse de que el input del usuario sea demasiado grande (tal que supere la dimensi´n del o arreglo que podamos haber declarado inicialmente) o demasiado corto (tal que se traduzca en un despilfarro de memoria por reservar m´s memoria para el arreglo de la que realmente a se necesita): #include <iostream> #include <string> using namespace std; int main(){ string palabra; cin >> palabra; return 0; } Adem´s, este nuevo tipo string permite acceder a un sin n´mero de funciones adicionales a u que facilitan enormemente el manejo de cadenas. Por ejemplo, las cadenas se pueden sumar, donde la suma de cadenas a y b est´ definida (siguiendo la intuici´n) como la cadena que a o resulta de poner b a continuaci´n de a: o #include <iostream> #include <string> using namespace std; int main(){ string texto1 = "Primera palabra"; string texto2 = "Segunda palabra"; cout << texto1 << endl << texto2 << endl; cout << texto1 + ", " + texto2 << endl; // La ultima linea es equivalente a: // string texto3 = texto1 + ", " + texto2; // cout << texto3 << endl; return 0 ; } El output de este programa ser´: a Primera palabra Segunda palabra Primera palabra, Segunda palabra

4.6. MANEJO DE ARCHIVOS. Ingreso con espacios.

125

Dijimos que es muy f´cil ingresar una cadena desde el teclado, pues no es necesario a definir la dimensi´n desde el comienzo. Sin embargo, el c´digo anterior, usando cin, no o o es muy general, porque el input termina cuando el usuario ingresa el primer cambio de l´ ınea o el primer espacio. Esto es muy c´modo cuando queremos ingresar una serie de vao lores (por ejemplo, para llenar un arreglo), pues podemos ingresarlos ya sea en la forma: 1<Enter> 2<Enter> 3<Enter>, etc., o 1 2 3, etc, pero no es ´ptimo cuando deseamos ino gresar texto, que podr´ constar de m´s de una palabra y, por tanto, necesariamente incluir´ ıa a ıa espacios (por ejemplo, al ingresar el nombre y apellido de una persona). Sin explicar demasiado por qu´, digamos que la soluci´n a este problema es utilizar una funci´n asociada a cin e o o llamada get, y leer desde el teclado hasta que el usuario d´ el primer cambio de l´ e ınea. Un ejemplo simple lo encontramos en el siguiente c´digo: o #include <iostream> #include <string> using namespace std; int main(){ string texto1 = "El resultado es: " ; string texto2 =""; char ch; cout << "Entre un string:" << endl; while( ( ch = cin.get() ) != ’\n’ ) cout << texto1 + texto2 << endl; return 0; } Observamos que cin.get() no necesita argumento y devuelve un char el cual es primero comparado con el caracter de fin de l´ ınea y luego acumulado en texto2.

texto2 = texto2 + ch;

4.6.

Manejo de archivos.

Una operaci´n usual en todo tipo de programas es la interacci´n con archivos. Ya sea que o o el programa necesite conocer ciertos par´metros de configuraci´n, hacer an´lisis estad´ a o a ıstico sobre un gran n´mero de datos generados por otro programa, entregar las coordenadas de u los puntos de una trayectoria para graficarlos posteriormente, etc., lo que se requiere es un modo de ingresar datos desde, o poner datos en, archivos. En C++ ello se efect´a incluyendo u el header fstream.

4.6.1.

Archivos de salida.

Observemos el siguiente programa:

126 #include <iostream> #include <fstream> using namespace std;

´ CAP´ ITULO 4. UNA BREVE INTRODUCCION A C++.

int main(){ ofstream nombre_logico("nombre_fisico.dat"); int i = 3, j; cout << i << endl; nombre_logico << i << endl; cout << "Ingrese un numero entero: "; cin >> j; cout << j << endl; nombre_logico << j << endl; nombre_logico.close(); return 0; } La primera l´ ınea de main define un objeto de tipo ofstream (output file stream). Esto corresponde a un archivo de salida. Dentro de main este archivo ser´ identificado por a una variable llamada nombre_logico, y corresponder´ a un archivo en el disco duro llamaa do nombre_fisico.dat. Naturalmente, el identificador nombre_logico puede ser cualquier nombre de variable v´lido para C++, y nombre_fisico.dat puede ser cualquier nombre de a archivo v´lido para el sistema operativo. En particular, se pueden tambi´n dar nombres que a e incluyan paths absolutos o relativos: ofstream nombre_logico_1("/home/vmunoz/temp/nombre_fisico.dat"); ofstream nombre_logico_2("../nombre_fisico.dat"); Cuando creamos un objeto del tipo archivo, sin importar si es de salida o de entrada, podemos inicializarlo con un nombre de archivo f´ ısico. Este nombre lo podemos almacenar previamente en una variable de string, llamemosla mi_nombre_archivo. En este caso, cuando creamos el objeto ofstream debemos usar un m´todo del objeto string que devuelve un e puntero a char, para poder inicializar el objeto ofstream. Veamos la sint´xis expl´ a ıcitamente string mi_nombre_archivo=’’archivo.txt’’; ofstream nombre_logico_1( mi_nombre_archivo.c_str()); Las l´ ıneas tercera y sexta de main env´ ıan a nombre_logico (es decir, escribe en nombre_fisico.dat), las variables i y j. Observar la analog´ que existe entre estas operaıa ciones y las que env´ la misma informaci´n a pantalla.4 Si ejecutamos el programa y en ıan o el teclado ingresamos el n´mero 8, al finalizar la ejecuci´n el archivo nombre_fisico.dat u o tendr´ los dos n´meros escritos: a u 3 8
Esta analog´ no es casual y se entiende con el concepto de clases (Sec. 4.8). fstream e iostream definen ıa clases que heredan sus propiedades de un objeto abstracto base, com´n a ambas, y que en el caso de iostream u se concreta en la salida est´ndar —pantalla—, y en el de fstream en un archivo. a
4

4.6. MANEJO DE ARCHIVOS.

127

Finalmente, el archivo creado debe ser cerrado (nombre_logico.close()). Si esta ultima ´ operaci´n se omite en el c´digo, no habr´ errores de compilaci´n, y el programa se encaro o a o gar´ de cerrar por s´ solo los archivos abiertos durante su ejecuci´n, pero un buen programador a ı o debiera tener cuidado de cerrarlos expl´ ıcitamente. Por ejemplo, un mismo programa podr´ ıa desear utilizar un mismo archivo m´s de una vez, o varios programas podr´ querer acceder a ıan al mismo archivo, y si no se ha insertado un close en el punto adecuado esto podr´ provocar ıa problemas. El archivo indicado al declarar la variable de tipo ofstream tiene modo de escritura, para permitir la salida de datos hacia ´l. Si no existe un archivo llamado nombre_fisico.dat es e creado; si existe, los contenidos antiguos se pierden y son reemplazados por los nuevos. No siempre deseamos este comportamiento. A veces deseamos agregar la salida de un programa a un archivo de texto ya existente. En ese caso la declaraci´n del archivo es diferente, para o crear el archivo en modo “append”: #include <iostream> #include <fstream> using namespace std; int main(){ ofstream nombre_logico("nombre_fisico.dat",ios::app); int i = 3; nombre_logico << i << endl; nombre_logico.close(); return 0; } Si ejecutamos este programa y el archivo nombre_fisico.dat no existe, ser´ creado. El a resultado ser´ un archivo con el n´mero 3 en ´l. Al ejecutarlo por segunda vez, los datos se a u e ponen a continuaci´n de los ya existentes, resultando el archivo con el contenido: o 3 3 La l´ ınea del tipo ofstream a("b") es equivalente a una del tipo int i=3, declarando una variable (a/i) de un cierto tipo (ofstream/int) y asign´ndole un valor simult´neamente a a "b"/3. Como para los tipos de variables predefinidos de C++, es posible separar declaraci´n o y asignaci´n para una variable de tipo ofstream: o ofstream a; a.open("b"); es equivalente a ofstream a("b"). Esto tiene la ventaja de que podr´ ıamos usar el mismo nombre l´gico para identificar dos archivos f´ o ısicos distintos, usados en distintos momentos del programa:

128

´ CAP´ ITULO 4. UNA BREVE INTRODUCCION A C++.

ofstream a; a.open("archivo1.txt"); // Codigo en que "archivo1.txt" es utilizado a.close(); a.open("archivo2.txt"); // Ahora "archivo2.txt" es utilizado a.close(); Observar la necesidad del primer close, que permitir´ liberar la asociaci´n de a a un nombre a o f´ ısico dado, y reutilizar la variable l´gica en otro momento. o En los ejemplos hemos escrito solamente variables de tipo int en los archivos. Esto por cierto no es restrictivo. Cualquiera de los tipos de variables de C++ —float, double, char, etc.— se puede enviar a un archivo del mismo modo. Dicho esto, en el resto de esta secci´n o seguiremos usando como ejemplo el uso de int.

4.6.2.

Archivos de entrada.

Ya sabemos que enviar datos a un archivo es tan f´cil como enviarlos a pantalla. ¿C´mo a o hacemos ahora la operaci´n inversa, de leer datos desde un archivo? Como es de esperar, es tan o f´cil como leerlos desde el teclado. Para crear un archivo en modo de lectura, basta declararlo a de tipo ifstream (input file stream). Por ejemplo, si en nombre_logico.dat tenemos los siguientes datos: 3 6 9 12 el siguiente programa, #include <iostream> #include <fstream> using namespace std; int main(){ ifstream nombre_logico("nombre_fisico.dat"); int i, j,k,l; nombre_logico >> i >> j >> k >> l; cout << i << "," << j << "," << k << "," << l << endl; nombre_logico.close(); return 0; }

4.6. MANEJO DE ARCHIVOS.

129

ser´ equivalente a asignar i=3, j=6, k=9, l=12, y luego enviar los datos a pantalla. Observar a que la sintaxis para ingresar datos desde un archivo, nombre_logico >> i, es id´ntica a e cin >> i, para hacerlo desde el teclado. Al igual que cin, espacios en blanco son equivalentes a cambios de l´ ınea, de modo que el archivo podr´ haber sido tambi´n: ıa e 3 6 9 12 Por cierto, el ingreso de datos desde un archivo se puede hacer con cualquier t´cnica, por e ejemplo, usando un for: ifstream nombre_logico("nombre_fisico.dat"); int i; for (int j=0;j<10;j++){ nombre_logico >> i; cout << i << ","; } nombre_logico.close(); } Como con ofstream, es posible separar declaraci´n e implementaci´n: o o ifstream a; a.open("b"); a.close();

4.6.3.

Archivos de entrada y salida.

Ocasionalmente nos encontraremos con la necesidad de usar un mismo archivo, en el mismo programa, a veces para escribir datos, y otras veces para leer datos. Por ejemplo, podr´ ıamos tener una secuencia de datos en un archivo, leerlos, y de acuerdo al an´lisis de a esos datos agregar m´s datos a continuaci´n del mismo archivo, o reemplazar los datos ya a o existentes con otros. Necesitamos entonces un tipo de variable flexible, que pueda ser usado como entrada y salida. Ese tipo es fstream. Todo lo que hemos dicho para ofstream y ifstream por separado es cierto simult´neamente para fstream.5 Para especificar si el archivo a debe ser abierto en modo de escritura o lectura, open contiene el argumento ios::out o ios::in, respectivamente. Por ejemplo, el siguiente c´digo escribe el n´mero 4 en un archivo, o u y luego lo lee desde el mismo archivo: #include <iostream> #include <fstream> using namespace std; int main(){ fstream nombre_logico;
Nuevamente, este hecho se debe al concepto de clases que subyace a las definiciones de estos tres tipos de variables; fstream es una clase derivada a la vez de ofstream y de ifstream, heredando las propiedades de ambas.
5

130

´ CAP´ ITULO 4. UNA BREVE INTRODUCCION A C++.

nombre_logico.open("nombre_fisico.dat",ios::out); int i = 4,j; nombre_logico << i << endl; nombre_logico.close(); nombre_logico.open("nombre_fisico.dat",ios::in); nombre_logico >> j; cout << j << endl; nombre_logico.close(); return 0; } Las dos primeras l´ ıneas de main separan declaraci´n y asignaci´n, y son equivalentes a o o fstream nombre_logico("nombre_fisico.dat",ios::out);, pero lo hemos escrito as´ paı ra hacer evidente la simetr´ entre el uso del archivo como salida primero y como entrada ıa despu´s. e De lo anterior, se deduce que: fstream archivo_salida("salida.dat",ios::out); fstream archivo_entrada("entrada.dat",ios::in); es equivalente a ofstream archivo_salida("salida.dat"); ifstream archivo_entrada("entrada.dat");

4.7.

main como funci´n. o

Para ejecutar un programa compilado en C++, escribimos su nombre en el prompt: user@host:~/$ programa Si el mismo usuario desea ejecutar alguno de los comandos del sistema operativo, debe hacer lo mismo: user@host:~/$ ls Sin embargo, ls es en realidad el nombre de un archivo ejecutable en el directorio /bin, de modo que en realidad no hay diferencias entre nuestro programa y un comando del sistema operativo en ese sentido. Sin embargo, ´stos pueden recibir argumentos y opciones. Por e ejemplo, para ver todos los archivos que comienzan con l en el directorio local basta con darle a ls el argumento l*: ls l*. Si queremos ordenar los archivos en orden inverso de modificaci´n, basta dar otro argumento, en forma de opci´n: ls -tr l*. Se ve entonces que o o los argumentos de un archivo ejecutable permiten modificar el comportamiento del programa de modos espec´ ıficos.

´ 4.7. MAIN COMO FUNCION.

131

¿Es posible hacer lo mismo con archivos ejecutables hechos por el usuario? La respuesta es s´ y para eso se usan los argumentos del main. Recordemos que main es una funci´n, ı, o pero hasta el momento no hemos aprovechado esa caracter´ ıstica. Simplemente sabemos que el programa empieza a ejecutarse en la l´ ınea donde est´ la funci´n main. Adem´s, siempre a o a hemos escrito esa l´ ınea como main(). Sin embargo, main, como cualquier funci´n, es capaz de o aceptar argumentos. Espec´ ıficamente, acepta dos argumentos, el primero es un entero (que cuenta el n´mero de argumentos que main recibi´), y el segundo es un puntero a un arreglo u o de caracteres (que contiene los distintos argumentos, en forma de cadenas de caracteres, que se le entregaron). Por ejemplo: #include <iostream> using namespace std; int main( int argc, char * argv[]) { for(int i = 0; i < argc; i++) { cout << argv[i] << endl ; } return 0; } Si llamamos a este programa argumentos, obtenemos distintas salidas al llamarlo con distintos argumentos: user@host:~/$ argumentos argumentos user@host:~/$ argumentos ap k 5 argumentos ap k 5 user@host:~/$ argumentos -t -s 4 arg1 argumentos -t -s 4 arg1 Observar que el primer argumento del programa es siempre el nombre del propio programa. Naturalmente, ´ste es un ejemplo muy simple. Es tarea del programador decidir c´mo manejar e o cada una de las opciones o argumentos que se le entregan al programa desde la l´ ınea de comandos, escribiendo el c´digo correspondiente. o

132

´ CAP´ ITULO 4. UNA BREVE INTRODUCCION A C++.

4.7.1.

Tipo de retorno de la funci´n main. o

Un segundo aspecto con el cual no hemos sido sistem´ticos es que main, como toda funci´n, a o tiene un tipo de retorno. En el caso de main, ese tipo debe ser int. Este int es entregado al sistema operativo, y puede servir para determinar si el programa se ejecut´ con normalidad o o si ocurri´ algo anormal. Podr´ o ıamos hacer ese valor de retorno igual a 0 o 1, respectivamente. As´ la siguiente estructura es correcta: ı, int main(){ // Codigo

return 0; } En este caso, el programa entrega siempre el valor 0 al sistema operativo. Los c´digos del tipo: o main(){ // Codigo

} o void main(){ // Codigo

} tambi´n compilan, pero el compilador emite una advertencia si es llamado con la opci´n e o -Wall (Warning all ). En el primer caso, la advertencia es: warning: ANSI C++ forbids declaration ‘main’ with no type En el segundo: return type for ‘main’ changed to ‘int’ En general, siempre es conveniente compilar con la opci´n -Wall, para lograr que nuestro o c´digo est´ realmente correcto (g++ -Wall <archivo>.cc -o <archivo>). o e

4.8. CLASES.

133

4.8.

Clases.

C++ dispone de una serie de tipos de variables con las cuales nos est´ permitido operar: a int, double, char, etc. Creamos variables de estos tipos y luego podemos operar con ellas: int x = y = int x, y; 3; 6; z = x + y;

No hay, sin embargo, en C++, una estructura predefinida que corresponda a n´meros u complejos, vectores de dimensi´n n o matrices, por ejemplo. Y sin embargo, nos agradar´ o ıa disponer de n´meros complejos que pudi´ramos definir como u e z = (3,5); w = (6,8); y que tuvieran sentido las expresiones a b c d e f = = = = = = z + w; z * w; z / w; z + 3; modulo(z); sqrt(z);

Todas estas expresiones son completamente naturales desde el punto de vista matem´tico, a y ser´ bueno que el lenguaje las entendiera. Esto es imposible en el estado actual, pues, por ıa ejemplo, el signo + es un operador que espera a ambos lados suyos un n´mero. Sumar cualquier u cosa con cualquier cosa no significa nada necesariamente, as´ que s´lo est´ permitido operar ı o a con n´meros. Pero los humanos sabemos que los complejos son n´meros. ¿C´mo dec´ u u o ırselo al computador? ¿C´mo convencerlo de que sumar vectores o matrices es tambi´n posible o e matem´ticamente, y que el mismo signo + deber´ servir para todas estas operaciones? a ıa La respuesta es: a trav´s del concepto de clases. Lo que debemos hacer es definir una clase e de n´meros complejos. Llam´mosla Complejo. Una vez definida correctamente, Complejo u e ser´ un tipo m´s de variable que el compilador reconocer´, igual que int, double, char, etc. a a a Y ser´ tan f´cil operar con los Complejos como con todos los tipos de variables preexistentes. a a Esta facilidad es la base de la extensibilidad de que es capaz C++, y por tanto de todas las propiedades que lo convierten en un lenguaje muy poderoso. Las clases responden a la necesidad del programador de construir objetos o tipos de datos que respondan a sus necesidades. Si necesitamos trabajar con vectores de 5 coordenadas, ser´ natural definir una clase que corresponda a vectores con 5 coordenadas; si se trata de a un programa de administraci´n de personal, la clase puede corresponder a un empleado, con o sus datos personales como elementos. Si bien es cierto uno puede trabajar con clases en el contexto de orientaci´n al procedio miento, las clases muestran con mayor propiedad su potencial con la orientaci´n al objeto, o donde cada objeto corresponde a una clase. Por ejemplo, para efectuar una aplicaci´n para o X-windows, la ventana principal, las ventanas de los archivos abiertos, la barra de men´, las u cajas de di´logo, los botones, etc., cada uno de estos objetos estar´ asociado a una clase. a a

134

´ CAP´ ITULO 4. UNA BREVE INTRODUCCION A C++.

4.8.1.

Definici´n. o

Digamos que queremos una clase para representar a los empleados de una empresa. Llam´mosla Persona. La convenci´n aceptada es que los nombres de las clases comiencen e o con may´scula. Esto es porque las clases, recordemos, corresponder´n a tipos de variables u a tan v´lidos como los internos de C++ (int, char, etc.). Al usar nombres con may´scula a u distinguimos visualmente los nombres de un tipo de variable interno y uno definido por el usuario. La estructura m´ ınima de la definici´n de la clase Persona es: o class Persona { }; Todas las caracter´ ısticas de la clase se definen entre los par´ntesis cursivos. e

4.8.2.

Miembros.

Se denomina miembros de una clase a todas las variables y funciones declaradas dentro de una clase. Por ejemplo, para personas, es natural caracterizarlas por su nombre y su edad. Y si se trata de empleados de una empresa, es natural tambi´n tener una funci´n que entregue e o su sueldo: class Persona { string nombre; fecha nacimiento; int rut; double edad(); }; Los miembros de una clase pueden tener cualquier nombre, excepto el nombre de la propia clase dentro de la cual se definen, ese nombre est´ reservado. a

4.8.3.

Miembros p´ blicos y privados. u

Una clase distingue informaci´n (datos o funciones) privada (accesible s´lo a otros miemo o bros de la misma clase) y p´blica (accesible a funciones externas a la clase). La parte privada u corresponde a la estructura interna de la clase, y la parte p´blica a la implementaci´n (t´ u o ıpicamente funciones), que permite la interacci´n de la clase con el exterior. o Consideremos ahora nuestro deseo de tener una clase que represente n´meros complejos. u Un n´mero complejo tiene dos n´meros reales (parte real e imaginaria), y ´sos son elementos u u e privados, es decir, parte de su estructura interna. Sin embargo, nos gustar´ poder modificar ıa y conocer esas cantidades. Eso s´lo puede hacerse a trav´s de funciones p´blicas. o e u

4.8. CLASES. class Complejo { private: double real, imaginaria; public: void setreal(double); void setimag(double); double getreal(); double getimag(); };

135

En este ejemplo, los miembros privados son s´lo variables, y los miembros p´blicos son s´lo o u o ´ funciones. Este es el caso t´ ıpico, pero puede haber variables y funciones de ambos tipos.

4.8.4.

Operador de selecci´n (.). o

Hemos definido una clase de n´meros complejos y funciones que nos permiten conocer u y modificar las partes real e imaginaria. ¿C´mo se usan estos elementos? Consideremos el o siguiente programa de ejemplo: using namespace std; class Complejo { private: double real, imaginaria; public: void setreal(double); void setimag(double); double getreal(); double getimag(); }; int main() { Complejo z, w; z.setreal(3); z.setimag(2.8); w.setreal(1.5); w.setimag(5); cout << "El primer numero complejo es: " << z.getreal() << " + i*" << z.getimag() << endl; cout << "El segundo es: " << w.getreal() << " + i*" << z.getimag() << endl; return 0; }

136

´ CAP´ ITULO 4. UNA BREVE INTRODUCCION A C++.

Vemos en la primera l´ ınea de main c´mo la clase Complejo se usa del mismo modo que o usar´ ıamos int o double. Ahora Complejo es un tipo de variable tan v´lido como los tipos a predefinidos por C++. Una vez definida la variable, el operador de selecci´n (.) permite o acceder a las funciones p´blicas correspondientes a la clase Complejo, aplicadas a la variable u particular que nos interesa: z.setreal(3) pone en la parte real del Complejo z el n´mero u 3, y w.setreal(1.5) hace lo propio con w.

4.8.5.

Implementaci´n de funciones miembros. o

Ya sabemos c´mo declarar funciones miembros en el interior de la clase y c´mo usarlas. o o Ahora veamos c´mo se implementan. o void Complejo::setreal(double x) { real = x; } void Complejo::setimag(double x) { imaginaria = x; } double Complejo::getreal() { return real; } double Complejo::getimag() { return imaginaria; } Como toda funci´n, primero va el tipo de la funci´n (void o double en los ejemplos), luego o o el nombre de la funci´n y los argumentos. Finalmente la implementaci´n. Lo diferente es que o o el nombre va precedido del nombre de la clase y el operador “::” .

4.8.6.

Constructor.

Al declarar una variable, el programa crea el espacio de memoria suficiente para alojarla. Cuando se trata de variables de tipos predefinidos en C++ esto no es problema, pero cuando son tipos definidos por el usuario, C++ debe saber c´mo construir ese espacio. La funci´n o o que realiza esa tarea se denomina constructor. El constructor es una funci´n p´blica de la clase, que tiene el mismo nombre que ella. o u Agreguemos un constructor a la clase Complejo: class Complejo

4.8. CLASES. { private: double real,imaginaria; public: Complejo(double,double); void setreal(double); void setimag(double); double getreal(); double getimag(); }; Complejo::Complejo (double x, double y) : real(x), imaginaria(y) {}

137

Definir el constructor de esta manera nos permite crear en nuestro programa variables de tipo Complejo y asignarles valores sin usar setreal() o setimag(): Complejo z (2, 3.8); Complejo w = Complejo(6.8, -3); En el constructor se inicializan las variables internas que nos interesa inicializar al momento de crear un objeto de esta clase. Si una de las variables internas a inicializar es una cadena de caracteres, hay que inicializarla de modo un poco distinto. Por ejemplo, si estamos haciendo una clase OtraPersona que s´lo tenga el nombre de una persona, entonces podemos definir la clase y su constructor o en la forma: class OtraPersona { private: char nombre[20]; public: Persona(char []); }; Persona::Persona(char a[]) { strcpy(nombre,a); } Si uno no especifica el constructor de una clase C++ crea uno default, pero en general ser´ insuficiente para cualquier aplicaci´n realmente pr´ctica. Es una mala costumbre ser a o a descuidado y dejar estas decisiones al computador.

4.8.7.

Destructor.

As´ como es necesario crear espacio de memoria al definir una variable, hay que deshacerse ı de ese espacio cuando la variable deja de ser necesaria. En otras palabras, la clase necesita

138

´ CAP´ ITULO 4. UNA BREVE INTRODUCCION A C++.

tambi´n un destructor . Si la clase es Complejo, el destructor es una funci´n p´blica de ella, e o u llamada ~Complejo. class Complejo { private: double real, imaginaria; public: Complejo(double,double); ~Complejo(); void setreal(double); void setimag(double); double getreal(); double getimag(); }; Complejo::Complejo (double x, double y): real(x), imaginaria(y) { } Complejo::~Complejo() { } Como con los constructores, al omitir un destructor C++ genera un default, pero es una mala costumbre. . . , etc.

4.8.8.

Arreglos de clases.

Una clase es un tipo de variable como cualquier otra de las predefinidas en C++. Es posible construir matrices con ellas, del mismo modo que uno tiene matrices de enteros o caracteres. La unica diferencia con las matrices usuales es que no se pueden s´lo declarar, ´ o sino que hay que inicializarlas simult´neamente. Por ejemplo, si queremos crear una matriz a que contenga 2 n´meros complejos, la l´ u ınea Complejo z[2]; es incorrecta, pero s´ es aceptable la l´ ı ınea Complejo z[2] = {Complejo(3.5,-0.8), Complejo(-2,4)};

4.9.

Sobrecarga.

Para que la definici´n de nuevos objetos sea realmente util, hay que ser capaz de hacer o ´ con ellos muchas acciones que nos ser´ naturales. Como ya comentamos al introducir el ıan concepto de clase, nos gustar´ sumar n´meros complejos, y que esa suma utilizara el mismo ıa u

4.9. SOBRECARGA.

139

signo + de la suma usual. O extraerles la ra´ cuadrada, y que la operaci´n sea tan f´cil ız o a como escribir sqrt(z). Lo que estamos pidiendo es que el operador + o la funci´n sqrt() o sean polim´rficos, es decir, que act´en de distinto modo seg´n el tipo de argumento que o u u se entregue. Si z es un real, sqrt(z) calcular´ la ra´ de un n´mero real; si es complejo, a ız u calcular´ la ra´ de un n´mero complejo. a ız u La t´cnica de programaci´n mediante la cual podemos definir funciones polim´rficas se e o o llama sobrecarga.

4.9.1.

Sobrecarga de funciones.

Digamos que la ra´ cuadrada de un n´mero complejo a + ib es (a/2) + i(b/2). (Es m´s ız u a complicado en realidad, pero no queremos escribir las f´rmulas ahora.) o Para sobrecargar la funci´n sqrt() de modo que acepte n´meros complejos basta definirla o u as´ ı: Complejo sqrt(Complejo z) { return Complejo (z.getreal()/2, z.getimag()/2); } Observemos que definimos una funci´n sqrt que acepta argumentos de tipo Complejo, y que o entrega un n´mero del mismo tipo. Cuando pidamos la ra´ de un n´mero, el computador u ız u se preguntar´ si el n´mero en cuesti´n es un int, double, float o Complejo, y seg´n eso a u o u escoger´ la versi´n de sqrt que corresponda. a o Con la definici´n anterior podemos obtener la ra´ cuadrada de un n´mero complejo o ız u simplemente con las instrucciones: Complejo z(1,3); Complejo raiz = sqrt(z);

4.9.2.

Sobrecarga de operadores.

¿C´mo le decimos al computador que el signo + tambi´n puede aceptar n´meros compleo e u jos? La respuesta es f´cil, porque para C++ un operador no es sino una funci´n, y la acci´n a o o de sobrecargar que ya vimos sirve en este caso tambi´n. La sintaxis es: e Complejo operator + (Complejo z, Complejo w) { return Complejo (z.getreal() + w.getreal(), z.getimag() + w.getimag()); }

4.9.3.

Coerci´n. o

Sabemos definir a + b, con a y b complejos. Pero ¿qu´ pasa si a o b son enteros? ¿O reales? e Pareciera que tendr´ ıamos que definir no s´lo o

140

´ CAP´ ITULO 4. UNA BREVE INTRODUCCION A C++.

Complejo operator + (Complejo a, Complejo b); sino tambi´n todas las combinaciones restantes: e Complejo operator + (Complejo a, int b); Complejo operator + (Complejo a, float b); Complejo operator + (int a, Complejo b); etc´tera. e En realidad esto no es necesario. Por cierto, un n´mero real es un n´mero complejo con u u parte imaginaria nula, y es posible hacerle saber esto a C++, usando la posibilidad de definir funciones con par´metros default. Basta declarar (en el interior de la clase) el constructor de a los n´meros complejos como u Complejo (double, double = 0); Esto permite definir un n´mero complejo con la instrucci´n: u o Complejo c = Complejo(3.5); resultando el n´mero complejo 3.5 + i · 0. Y si tenemos una l´ u ınea del tipo: Complejo c = Complejo(3,2.8) + 5; el computador convertir´ impl´ a ıcitamente el entero 5 a Complejo (sabe c´mo hacerlo porque o el constructor de n´meros complejos acepta tambi´n un solo argumento en vez de dos), y u e luego realizar´ la suma entre dos complejos, que es entonces la unica que es necesario definir. a ´

4.10.

Herencia.

Herencia es el mecanismo mediante el cual es posible definir clases a partir de otras, preservando parte de las propiedades de la primera y agregando o modificando otras. Por ejemplo, si definimos la clase Persona, toda Persona tendr´ una variable miembro a que sea su nombre. Si definimos una clase Hombre, tambi´n ser´ Persona, y por tanto deber´ e a ıa tener nombre. Pero adem´s puede tener esposa. Y ciertamente no toda Persona tiene esposa. a S´lo un Hombre. o C++ provee mecanismos para implementar estas relaciones l´gicas y poder definir una o clase Hombre a partir de Persona. Lo vemos en el siguiente ejemplo: class Persona { private: string nombre; public: Persona(string = ""); ~Persona(); string getname(); }

4.11. EJEMPLO: LA CLASE DE LOS COMPLEJOS.

141

class Hombre : public Persona { private: string esposa; public: Hombre(string a) : Persona(a) { }; string getwife(); void setwife(string); }; Primero definimos una clase Persona que tiene nombre. Luego definimos una clase Hombre a partir de Persona (con la l´ ınea class Hombre : public Persona). Esto permite de modo autom´tico que Hombre tenga tambi´n una variable nombre. Y finalmente, dentro de la clase a e Hombre, se definen todas aquellas caracter´ ısticas adicionales que una Persona no tiene pero un Hombre s´ esposa, y funciones miembros para modificar y obtener el nombre de ella. ı: Un ejemplo de uso de estas dos clases: Persona cocinera("Maria"); Hombre panadero("Claudio"); panadero.setwife("Estela"); cout << cocinera.getname() << endl; cout << panadero.getname() << endl; cout << panadero.getwife() << endl; Observemos que panadero tambi´n tiene una funci´n getname(), a pesar de que la clase e o Hombre no la define expl´ ıcitamente. Esta funci´n se ha heredado de la clase de la cual Hombre o se ha derivado, Persona.

4.11.

Ejemplo: la clase de los complejos.

A continuaci´n, una clase de complejos m´s completa. Primero el archivo de headers o a complejos.h, con las definiciones: #ifndef _complejos_ #define _complejos_ #include <iostream> #include <cmath> class Complejo { private: double real, imaginaria;

142

´ CAP´ ITULO 4. UNA BREVE INTRODUCCION A C++.

public: Complejo(); Complejo(double,double=0); ~Complejo(); void setreal(double); void setimag(double); double getreal(); double getimag(); double getmodule(); double getmodule2(); double getphase(); }; Complejo operator + (Complejo,Complejo); Complejo operator - (Complejo,Complejo); Complejo operator * (Complejo,Complejo); Complejo operator / (Complejo,Complejo); Complejo conjugate(Complejo); Complejo inverse(Complejo); Complejo sqrt(Complejo); Complejo log(Complejo); bool operator == (Complejo,Complejo); bool operator != (Complejo,Complejo); std::ostream & operator << (std::ostream &, Complejo); #endif y la implementaci´n de lo anterior o #include "complejos.h" Complejo::Complejo(double x, double y) :real(x), imaginaria(y) {} Complejo::Complejo() :real(0), imaginaria(0) {} Complejo::~Complejo() {} void Complejo::setreal(double x) { real = x;

4.11. EJEMPLO: LA CLASE DE LOS COMPLEJOS. } void Complejo::setimag(double x) { imaginaria = x; } double Complejo::getreal() { return real; } double Complejo::getimag() { return imaginaria; } double Complejo::getmodule() { return sqrt(real*real+imaginaria*imaginaria); } double Complejo::getmodule2() { return real*real+imaginaria*imaginaria; } double Complejo::getphase() { return atan2(real,imaginaria); }

143

Complejo operator + (Complejo z,Complejo w) { return Complejo(z.getreal()+w.getreal(), z.getimag()+w.getimag()); } Complejo operator - (Complejo z,Complejo w) { return Complejo(z.getreal()-w.getreal(), z.getimag()-w.getimag()); } Complejo operator * (Complejo z,Complejo w) {

144

´ CAP´ ITULO 4. UNA BREVE INTRODUCCION A C++. return Complejo(z.getreal()*w.getreal()- z.getimag()*w.getimag(), z.getreal()*w.getimag()+ z.getimag()*w.getreal());

} Complejo operator / (Complejo z,Complejo w) { return z*inverse(w); } Complejo conjugate(Complejo z) { return Complejo(z.getreal(), -z.getimag()); } Complejo inverse(Complejo z) { return Complejo(z.getreal()/z.getmodule2(), -z.getimag()/z.getmodule2()); } Complejo sqrt(Complejo z) { return Complejo(sqrt(z.getmodule())*cos(z.getphase()/2.0), sqrt(z.getmodule())*sin(z.getphase()/2.0)) ; } Complejo log(Complejo z) { return Complejo(log(z.getmodule()), z.getphase()); } bool operator == (Complejo z,Complejo w) { return bool(z.getreal()==w.getreal() && z.getimag()==w.getimag()); } bool operator != (Complejo z,Complejo w) { return bool(z.getreal()!=w.getreal() || z.getimag()!=w.getimag()); } std::ostream & operator << (std::ostream & os , Complejo z) { os << z.getreal(); if(z.getimag() !=0) os << " + i*"<< z.getimag(); return os; }

´ 4.12. COMPILACION Y DEBUGGING.

145

4.12.
4.12.1.

Compilaci´n y debugging. o
Compiladores.

El comando para usar el compilador de lenguaje C es gcc, para usar el compilador de C++ es g++ y para usar el compilador de fortran 77 es g77. Centr´mosnos en el compilador e de C++, los dem´s funcionan en forma muy similar. Su uso m´s elemental es: a a g++ filename.cc Esto compila el archivo filename.cc y crea un archivo ejecutable que se denomina a.out por omisi´n. Existen diversas opciones para el compilador, s´lo comentaremos una pocas. o o -c realiza s´lo la compilaci´n pero no el link: o o g++ -c filename.cc genera el archivo filename.o que es c´digo objeto. o -o exename define el nombre del ejecutable creado, en lugar del por defecto a.out. g++ -o outputfile filename.cc -lxxx incluye la biblioteca /usr/lib/libxxx.a en la compilaci´n. o g++ filename.cc -lm En este caso se compila con la biblioteca matem´tica libm.a. a -g permite el uso de un debugger posteriormente. -On optimizaci´n de grado n que puede tomar valores de 1 (por defecto) a 3. El objetivo o inicial del compilador es reducir el tiempo de la compilaci´n. Con -On, el compilador o trata de reducir el tama˜o del ejecutable y el tiempo de ejecuci´n, con n se aumenta el n o grado de optimizaci´n. o -Wall notifica todos los posibles warnings en el c´digo que est´ siendo compilado. o a -L/path1 -I/path2/include incluye en el camino de b´squeda /path1/ para las biu bliotecas y /path2/include para los archivos de cabecera (headers). El compilador gcc (the GNU C compiler) es compatible ANSI.

146

´ CAP´ ITULO 4. UNA BREVE INTRODUCCION A C++.

Cap´ ıtulo 5 Gr´fica. a
versi´n 4.12, 24 de Octubre del 2003 o

En este cap´ ıtulo quisi´ramos mostrar algunas de las posibilidades gr´ficas presentes en Lie a nux. Nuestra intensi´n es cubrir temas como la visualizaci´n, conversi´n, captura y creaci´n o o o o de archivos gr´ficos. S´lo mencionaremos las aplicaciones principales en cada caso centr´ndoa o a nos en sus posibilidades m´s que en su utilizaci´n espec´ a o ıfica, ya que la mayor´ posee una ıa interfase sencilla de manejar y una amplia documentaci´n. o

5.1.

Visualizaci´n de archivos gr´ficos. o a

Si disponemos de un archivo gr´fico conteniendo alg´n tipo de imagen lo primero que es a u importante determinar es en qu´ tipo de formato gr´fico est´ codificada. Existe un n´mero e a a u realmente grande de diferentes tipos de codificaciones de im´genes, cada una de ellas se a considera un formato gr´fico. Por razones de reconocimiento inmediato del tipo de formato a gr´fico se suelen incluir en el nombre del archivo, que contiene la imagen, un tr´ de letras a ıo finales, conocidas como la extensi´n, que representan el formato. Por ejemplo: bmp, tiff, jpg, o ps, eps, fig, gif entre muchas otras, si uno quiere asegurarse puede dar el comando: jrogan@huelen:~$file mono.jpg mono.jpg: JPEG image data, JFIF standard 1.01, resolution (DPCM), 72 x 72 ¿De qu´ herramientas disponemos en Linux para visualizar estas im´genes? La respuesta e a es que en Linux disponemos de variadas herramientas para este efecto. Si se trata de archivos de tipo PostScript o Encapsulated PostScript, identificados por la extensi´n ps o eps, existen las aplicaciones gv, gnome-gv o kghostview, todos programas que o nos permitir´n visualizar e imprimir este tipo de archivos. Si los archivos son tipo Portable a Document Format, con extensi´n pdf, tenemos las aplicaciones gv, acroread o xpdf, Con o todas ellas podemos ver e imprimir dicho formato. Una menci´n especial requieren los archivos o DeVice Independent con extensi´n dvi ya que son el resultado de la compilaci´n de un o o A X, para este tipo de archivo existen las aplicaciones xdvi, advi, gxdvi documento TEX o L TE y kdvi por nombrar las principales. La aplicaci´n xdvi s´lo permite visualizar estos archivos o o y no imprimirlos, la mayor´ de las otras permiten imprimirlo directamente. Si usa xdvi y ıa desea imprimir el documento debe transformar a ps v´ dvips y luego se imprime como ıa cualquier otro Postscript. Para la gran mayor´ de formatos gr´ficos m´s conocidos y usualmente usados para alıa a a macenar fotos existen otra serie se programas especializados en visualizaci´n que son capaces o 147

148

´ CAP´ ITULO 5. GRAFICA.

de entender la mayor´ de los formatos m´s usados. Entre estos programas podemos mencioıa a nar: Eye of Gnome (eog), Electric Eyes (eeyes), kview o display. Podemos mencionar que aplicaciones como display entienden sobre ochenta formatos gr´ficos distintos entre los que a se encuentran la mayor´ de los formatos conocidos m´s otros como ps, eps, pdf, fig, html, ıa a entre muchos otros. Una menci´n especial merece el utilitario gthumb que nos permite hacer o un preview de un directorio con muchas imagenes de manera muy f´cil. a

5.2.

Modificando im´genes a

Si queremos modificaciones como rotaciones, ampliaciones, cortes, cambios de paleta de colores, filtros o efectos sencillos, display es la herramienta precisa. Pero si se desea intervenir la imagen en forma profesional, el programa gimp es el indicado. El nombre gimp viene de GNU Image Manipulation Program. Se puede usar esta aplicaci´n para editar y manipular o im´genes. Pudiendo cargar y salvar en una variedad de formatos, lo que permite usarlo para a convertir entre ellos. La aplicaci´n gimp puede tambi´n ser usado como programa de pintar, o e de hecho posee una gran variedad de herramientas en este sentido, tales como brocha de aire, l´piz clonador, tijeras inteligentes, curvas bezier, etc. Adem´s, permite incluir plugins a a que realizan gran variedad de manipulaciones de imagen. Como hecho anecd´tico podemos o mencionar que la imagen oficial de Tux, el ping¨ino mascota de Linux, fue creada en gimp. Sin u embargo, si gimp le parece muy profesional o usted s´lo necesita un programa para dibujar o en el cual se entretenga su hermano menor tuxpaint es la alternativa.

5.3.

Conversi´n entre formatos gr´ficos. o a

El problema de transformar de un formato a otro es una situaci´n usual en el trabajo con o archivos gr´ficos. Muchos softwares tienen salidas muy restringidas en formato o bien usan a formatos arcaicos (gif) por ejemplo. De ah´ que se presenta la necesidad de convertir estos ı archivos de salida en otros formatos que nos sean m´s manejables o pr´cticos. Como ya se a a mencion´, gimp puede ser usado para convertir entre formatos gr´ficos. Tambi´n display o a e permite este hecho. Sin embargo, en ambos casos la conversi´n es v´ men´s, lo cual lo o ıa u hace engorroso para un gran n´mero de conversiones e imposible para conversiones de tipo u autom´tico. Existe un programa llamado convert que realiza conversiones desde la l´ a ınea de comando. Este programa junto con display, import y varios otros forman la suite gr´fica a ImageMagick, una de las m´s importantes en unix, en general, y en especial en Linux y que a ya ha sido migrada a otras plataformas. Adem´s, de la clara ventaja de automatizaci´n que a o proporciona convert, posee otro aspecto interesante, puede convertir un grupo de im´genes a asociadas en una secuencia de animaci´n o pel´ o ıcula. Veamos la sintaxis para este programa: user@host:~/imagenes$convert cockatoo.tiff cockatoo.jpg user@host:~/secuencias$convert -delay 20 dna*.png dna.mng En el primer caso convierte el archivo cockatoo de formato tiff a formato jpg. En el segundo, a partir de un conjunto de archivos con formato png llamados dna m´s un n´mero a u

5.4. CAPTURA DE PANTALLA.

149

correlativo, crea una secuencia animada con im´genes que persisten por 20 cent´simas de a e segundos en un formato conocido como mng.

5.4.

Captura de pantalla.

A menudo se necesita guardar im´genes que s´lo se pueden generar a tiempo de ejecuci´n, a o o es decir, mientras corre nuestro programa genera la imagen pero no tiene un mecanismo propio para exportarla o salvarla como imagen. En este caso necesitamos capturar la pantalla y poderla almacenar en un archivo para el cual podamos elegir el formato. Para estos efectos existe un programa, miembro tambi´n de la suite ImageMagick, llamado import que nos e permite hacer el trabajo. La sintaxis del comando es import figure.eps import -window root root.jpg En el primer caso uno da el comando en un terminal y queda esperando hasta que uno toque alguna de las ventanas, la cual es guardada en este caso en un archivo figure.eps en formato PostScript. La extensi´n le indica al programa qu´ formato usar para almacenar la imagen. o e En el segundo caso uno captura la pantalla completa en un archivo root.jpeg. Este comando puede ser dado desde la consola de texto para capturar la imagen completa en la pantalla gr´fica. a

5.5.

Creando im´genes. a

Para im´genes art´ a ısticas sin duda la alternativa es gimp, todo le que se dijo respecto a sus posibilidades para modificar im´genes se aplica tambi´n en el caso de crearlas. En el caso a e de necesitar im´genes m´s bien t´cnicas como esquemas o diagramas o una ilustraci´n para a a e o aclarar un problema las alternativas pueden ser xfig, sodipodi o sketch todas herramientas vectoriales muy poderosa. Este tipo de programas son manejados por medio de men´s y u permiten dibujar y manipular objetos interactivamente. Las im´genes pueden ser salvadas, a en formato propios y posteriormente editadas. La gran ventaja de estos programas es que trabaja con objetos y no con bitmaps. Adem´s, puede exportar las im´genes a otros formatos: a a PostScript o Encapsulated PostScript o bien gif o jpeg. Habitualmente los dibujos necesarios para ilustrar problemas en F´ ısica en tareas, pruebas y apuntes son realizados con software de este tipo, principalmente xfig, luego exportados A a PostScript e inclu´ ıdos en los respectivos archivos L TEX. Tambi´n existe una herramienta e extremadamente util que permite convertir un archivo PostScript, generado de cualquier ´ manera, a un archivo fig que puede ser editado y modificado. Esta aplicaci´n que transforma o se llama pstoedit y puede llegar a ser realmente pr´ctica. Otra herramienta interesante es a autotrace que permite pasar una figura en bitmap a forma vectorial. Una aparente limitaci´n de este tipo de software es que se podr´ pensar que no podemos o ıa incluir curvas anal´ ıticas, es decir, si necesitamos ilustrar una funci´n gaussiana no podemos o pretender “dibujarla” con las herramientas de que disponen. Sin embargo, este problema puede ser resuelto ya que software que grafica funciones anal´ ıticas, tales como gnuplot,

150

´ CAP´ ITULO 5. GRAFICA.

permite exportar en formato que entienden los programas vectoriales (fig, por ejemplo) luego podemos leer el archivo y editarlo. Adem´s, xfig permite importar e incluir im´genes a a del tipo bitmap, agregando riqueza a los diagramas que puede generar. Una caracter´ ıstica importante de este tipo de programas es que trabajen por capas, las cuales son tratadas independientemente, uno puede poner un objeto sobre otro o por debajo de otro logrando diferentes efectos. Algunos programas de presentaci´n gr´ficos basados en o a A X y pdf est´n utilizando esta capacidad en xfig para lograr animaciones de im´genes. L TE a a Finalmente el programa xfig permite construir una biblioteca de objetos reutilizables ahorrando mucho trabajo. Por ejemplo, si uno dibuja los elementos de un circuito el´ctrico y e los almacena en el lugar de las bibliotecas de im´genes podr´ incluir estos objetos en futuros a a trabajos. El programa viene con varias bibliotecas de objetos listas para usar.

5.6.

Graficando funciones y datos.

Existen varias aplicaciones que permiten graficar datos de un archivo, entre las m´s popua lares est´n: gnuplot, xmgrace y SciGraphica. La primera est´ basada en la l´ a a ınea de comando y permite gr´ficos en 2 y 3 dimensiones, pudiendo adem´s, graficar funciones directamente a a sin pasar por un archivo de datos. Las otras dos son aplicaciones basadas en men´s que u permiten un resultado final de mucha calidad y con m´ltiples variantes. La debilidad en el u caso de xmgrace es que s´lo hace gr´ficos bidimensionales. o a El programa gnuplot se invoca de la l´ ınea de comando y da un prompt en el mismo terminal desde el cual se puede trabajar, veamos una sesi´n de gnuplot: o jrogan@huelen:~$ gnuplot G N U P L O T Version 3.7 patchlevel 2 last modified Sat Jan 19 15:23:37 GMT 2002 System: Linux 2.4.19 Copyright(C) 1986 - 1993, 1998 - 2002 Thomas Williams, Colin Kelley and many others Type ‘help‘ to access the on-line reference manual The gnuplot FAQ is available from http://www.gnuplot.info/gnuplot-faq.html Send comments and requests for help to <info-gnuplot@dartmouth.edu> Send bugs, suggestions and mods to <bug-gnuplot@dartmouth.edu>

Terminal gnuplot> gnuplot> gnuplot>

type set to ’x11’ plot sqrt(x) set xrange[0:5] set xlabel" eje de las x"

5.7. GRAFICANDO DESDE NUESTROS PROGRAMAS.

151

gnuplot> replot gnuplot> set terminal postscript Terminal type set to ’postscript’ Options are ’landscape noenhanced monochrome dashed defaultplex "Helvetica" 14’ gnuplot> set output "mygraph.ps" gnuplot> replot gnuplot> set terminal X Terminal type set to ’X11’ Options are ’0’ gnuplot> set xrange[-2:2] gnuplot> set yrange[-2:2] gnuplot> splot exp(-x*x-y*y) gnuplot> plot "myfile.dat" w l gnuplot> exit jrogan@huelen:~$ En el caso de xmgrace y SciGraphica mucho m´s directo manejarlo ya que est´ baa a sado en men´s. Adem´s, existe abundante documentaci´n de ambos softwares. El software u a o SciGraphica es una aplicaci´n de visualizaci´n y an´lisis de data cient´ o o a ıfica que permite el despliegue de gr´ficos en 2 y 3 dimensiones, adem´s, exporta los resultados a formato a a PostScript. Realmente esta aplicaci´n naci´ como un intento de clonar el programa comercial o o origen no disponible para Linux.

5.7.

Graficando desde nuestros programas.

Finalmente para poder graficar desde nuestro propio programa necesitamos alguna biblioteca gr´fica, en nuestro caso usaremos la biblioteca iglu, hecha completamente en casa. La a p´gina de iglu est´ en : http://aristoteles.ciencias.uchile.cl/homepage/iglu/iglu.html a a El comando de compilaci´n incluido en un script, que llamaremos iglu_compila, y que cono tiene las siguientes l´ ıneas: #!/bin/bash g++ -Wall -O3 -o $1 $1.cc -I. -I$HOME/iglu/ \ -L/usr/X11R6/lib/ -L$HOME/iglu/ -liglu -lX11 -lm Veamos algunos ejemplos: /* Ejemplo: sen(x) */ #include ‘‘iglu.h’’ #include <cmath> int main() { IgluDibujo v(‘‘Funcion Seno’’); const int N=100; double x[N], y[N];

152 v.map_coordinates(0,2*M_PI,-1.2,1.2); double dx = 2*M_PI/(N-1); for (int i=0;i<N;i++){ x[i] = i*dx; y[i] = sin(x[i]); } v.plot_line(x,y,N); v.wait(); return 0; }

´ CAP´ ITULO 5. GRAFICA.

Este programa grafica la funci´n seno con un n´mero de puntos dado. o u Otro caso, una primitiva animaci´n o // Ejemplo sen(x-vt) #include "iglu.h" #include <cmath> int main(){ IgluDibujo v(‘‘Pelicula’’); const int N=100, Nt=100; double x[N], y[N]; v.map_coordinates(0,2*M_PI,-1.2,1.2); double dx = 2*M_PI/(N-1), dt = 1, t=0; for (int j=0;j<Nt;j++){ v.clean(); t += dt; for (int i=0;i<N;i++){ x[i] = i*dx; y[i] = sin(x[i]-.1*t); } v.plot_line(x,y,N); v.wait(.03); v.flush(); } v.wait(); return 0; }

Cap´ ıtulo 6 El sistema de preparaci´n de o documentos TEX .
versi´n 5.0, 30 de Julio del 2003 o

6.1.

Introducci´n. o

TEX es un procesador de texto o, mejor dicho, un avanzado sistema de preparaci´n de o documentos, creado por Donald Knuth, que permite el dise˜o de documentos de gran calin dad, conteniendo textos y f´rmulas matem´ticas. A˜os despu´s, L TEX fue desarrollado por o a n e A Leslie Lamport, facilitando la preparaci´n de documentos en TEX, gracias a la definici´n de o o “macros” o conjuntos de comandos de f´cil uso. a A A L TEX tuvo diversas versiones hasta la 2.09. Actualmente, L TEX ha recibido importantes A modificaciones, siendo la distribuci´n actualmente en uso y desarrollo L TEX 2ε , una versi´n o o A A transitoria en espera de que alg´n d´ se llegue a la nueva versi´n definitiva de L TEX, L TEX3. u ıa o A A En estas p´ginas cuando digamos L TEX nos referiremos a la versi´n actual, L TEX 2ε . Cuana o do queramos hacer referencia a la versi´n anterior, que deber´ quedar progresivamente en o ıa A desuso, diremos expl´ ıcitamente L TEX 2.09.

6.2.

Archivos.

A El proceso de preparaci´n de un documento L TEX consta de tres pasos: o

1. Creaci´n de un archivo con extensi´n tex con alg´n editor. o o u 2. Compilaci´n o del archivo tex, con un comando del tipo latex <archivo>.tex o latex <archivo>. Esto da por resultado tres archivos adicionales, con el mismo nombre del archivo original, pero con extensiones distintas: a) dvi. Es el archivo procesado que podemos ver en pantalla o imprimir. Una vez compilado, este archivo puede ser enviado a otro computador, para imprimir en otra impresora, o verlo en otro monitor, independiente de la m´quina (de donde a su extensi´n dvi, device independent). o 153

154

´ CAP´ ITULO 6. EL SISTEMA DE PREPARACION DE DOCUMENTOS TEX . b) log. Aqu´ se encuentran todos los mensajes producto de la compilaci´n, para ı o consulta si es necesario (errores encontrados, memoria utilizada, mensajes de advertencia, etc.). c) aux. Contiene informaci´n adicional que, por el momento, no nos interesa. o

3. Visi´n en pantalla e impresi´n del archivo procesado a trav´s de un programa anexo o o e (xdvi o dvips, por ejemplo), capaz de leer el dvi.

6.3.
6.3.1.

Input b´sico. a
Estructura de un archivo.

En un archivo no pueden faltar las siguientes l´ ıneas: \documentclass[12pt]{article} \begin{document} \end{document} Haremos algunas precisiones respecto a la primera l´ ınea m´s tarde. Lo importante es que a una l´ ınea de esta forma debe ser la primera de nuestro archivo. Todo lo que se encuentra antes de \begin{document} se denomina pre´mbulo. El texto que queramos escribir va entre a \begin{document} y \end{document}. Todo lo que se encuentre despu´s de \end{document} e es ignorado.

6.3.2.

Caracteres.

Pueden aparecer en nuestro texto todos los caracteres del c´digo ASCII no extendido o (teclado ingl´s usual): letras, n´meros y los signos de puntuaci´n: e u o . : ; , ? ! ‘ ’ ( ) [ ] / * @

Los caracteres especiales: # $ % & ~ _ ^ \ { }

A tienen un significado espec´ ıfico para L TEX. Algunos de ellos se pueden obtener anteponi´ndoe les un backslash:

#

\#

$

\$

%

\%

&

\&

{

\{

}

\}

Los caracteres + = | < >

´ 6.3. INPUT BASICO.

155

generalmente aparecen en f´rmulas matem´ticas, aunque pueden aparecer en texto normal. o a Finalmente, las comillas dobles (") casi nunca se usan. A Los espacios en blanco y el fin de l´ ınea son tambi´n caracteres (invisibles), que L TEX e considera como un mismo car´cter, que llamaremos espacio, y que simbolizaremos ocasionala mente como . Para escribir en castellano requeriremos adem´s algunos signos y caracteres especiales: a n ˜ \~n a ´ \’a ´ ı \’{\i} u ¨ \"u ¡ !‘ ¿ ?‘

6.3.3.

Comandos.

Todos los comandos comienzan con un backslash, y se extienden hasta encontrar el primer car´cter que no sea una letra (es decir, un espacio, un n´mero, un signo de puntuaci´n o a u o matem´tico, etc.). a

6.3.4.

Algunos conceptos de estilo.

A L TEX es consciente de muchas convenciones estil´ ısticas que quiz´s no apreciamos cuando a leemos textos bien dise˜ados, pero las cuales es bueno conocer para aprovecharlas. n

a) Observemos la siguiente palabra: fino. Esta palabra fue generada escribiendo simplemente fino, pero observemos que las letras ‘f’ e ‘i’ no est´n separadas, sino que unidas a art´ ısticamente. Esto es una ligadura, y es considerada una pr´ctica est´ticamente prea e A X sabe esto e inserta este peque˜ o efecto tipogr´fico sin que nos demos ferible. L TE n a cuenta. b) Las comillas de apertura y de cierre son distintas. Por ejemplo: ‘insigne’ (comillas simples) o “insigne” (comillas dobles). Las comillas de apertura se hacen con uno o con dos acentos graves (‘), para comillas simples o dobles, respectivamente, y las de cierre con acentos agudos (’): ‘insigne’, ‘‘insigne’’. No es correcto entonces utilizar las comillas dobles del teclado e intentar escribir "insigne" (el resultado de esto es el poco est´tico ”insigne”). e c) Existen tres tipos de guiones: Corto (entre palabras, corte en s´ ılabas al final de la l´ ınea) Medio p´ginas 1–2 a -(rango de n´meros) u Largo un ejemplo —como ´ste --- (puntuaci´n, par´ntesis) e o e A d) L TEX inserta despu´s de un punto seguido un peque˜o espacio adicional respecto al e n espacio normal entre palabras, para separar sutilmente frases. Pero, ¿c´mo saber que o un punto termina una frase? El criterio que utiliza es que todo punto termina una frase cuando va precedido de una min´scula. Esto es cierto en la mayor´ de los casos, u ıa as´ como es cierto que generalmente cuando un punto viene despu´s de una may´scula ı e u no hay fin de frase:

Saint-Exup´ry e

156

´ CAP´ ITULO 6. EL SISTEMA DE PREPARACION DE DOCUMENTOS TEX . China y U.R.S.S. estuvieron de acuerdo. Sin embargo. . . Pero hay excepciones: ´ En la p´g. 11 encontraremos noticias desde la U.R.S.S. Estas fueron entregaa das. . . Cuando estas excepciones se producen, nosotros, humanos, tenemos que ayudarle al computador, dici´ndole que, aunque hay un punto despu´s de la “g”, no hay un fin de e e frase, y que el punto despu´s de la ultima “S” s´ termina frase. Esto se consigue as´ e ´ ı ı: En la p\’ag.\ 11 encontraremos noticias desde la U.R.S.S\@. \’Estas fueron entregadas...

´ d) Enfasis de texto:
´ Este es un texto enfatizado. \’Este es un texto {\em enfatizado}. Otro texto \emph{enfatizado}.

Otro texto enfatizado.

Al enfatizar, pasamos temporalmente a un tipo de letra distinto, la it´lica. Esta letra es a ligeramente inclinada hacia adelante, lo cual puede afectar el correcto espaciado entre palabras. Comparemos, por ejemplo:
Quiero hoy mi recompensa. Quiero hoy mi recompensa. Quiero hoy mi recompensa. Quiero {\em hoy} mi recompensa. Quiero {\em hoy\/} mi recompensa. Quiero \emph{hoy} mi recompensa.

La segunda y tercera frase tienen un peque˜o espacio adicional despu´s de “hoy”, n e para compensar el espacio entre palabras perdido por la inclinaci´n de la it´lica. Este o a peque˜o espacio se denomina correcci´n it´lica, y se consigue usando \emph, o, si se n o a usa \em, agregando \/ antes de cerrar el par´ntesis cursivo. La correcci´n it´lica es e o a A innecesaria cuando despu´s del texto enfatizado viene un punto o una coma. L TEX e advierte esto y omite el espacio adicional aunque uno lo haya sugerido.

6.3.5.

Notas a pie de p´gina. a

Insertemos una nota a pie de p\’agina.\footnote{Como \’esta.}
A L TEX colocar´ una nota a pie de p´gina1 en el lugar apropiado. a a
1

Como ´sta. e

´ 6.3. INPUT BASICO.

157

6.3.6.

F´rmulas matem´ticas. o a

A L TEX distingue dos modos de escritura: un modo de texto, en el cual se escriben los textos usuales como los ya mencionados, y un modo matem´tico, dentro del cual se escriben a las f´rmulas. Cualquier f´rmula debe ser escrita dentro de un modo matem´tico, y si alg´n o o a u s´ ımbolo matem´tico aparece fuera del modo matem´tico el compilador acusar´ un error. a a a Hay tres formas principales para acceder al modo matem´tico: a

a) $x+y=3$ b) $$xy=8$$ c) \begin{equation} x/y=5 \end{equation} Estas tres opciones generan, respectivamente, una ecuaci´n en el texto: x + y = 3, una o ecuaci´n separada del texto, centrada en la p´gina: o a xy = 8 y una ecuaci´n separada del texto, numerada: o x/y = 5 (6.1)

Es importante notar que al referirnos a una variable matem´tica en el texto debemos a escribirla en modo matem´tico: a
Decir que la inc´gnita es x es o incorrecto. No: la inc´gnita es o x. Decir que la inc{\’o}gnita es x es incorrecto. No: la inc{\’o}gnita es $x$.

6.3.7.

Comentarios.

Uno puede hacer que el compilador ignore parte del archivo usando %. Todo el texto desde este car´cter hasta el fin de la l´ a ınea correspondiente ser´ ignorado (incluyendo el fin de l´ a ınea).
Un peque˜o comentario. n Un peque{\~n}o co% mentario. Texto ignorado

6.3.8.

Estilo del documento.

Las caracter´ ısticas generales del documento est´n definidas en el pre´mbulo. Lo m´s a a a importante es la elecci´n del estilo, que determina una serie de par´metros que al usuario o a normal pueden no importarle, pero que son b´sicas para una correcta presentaci´n del texto: a o ¿Qu´ m´rgenes dejar en la p´gina? ¿Cu´nto dejar de sangr´ ¿Tipo de letra? ¿Distancia e a a a ıa? entre l´ ıneas? ¿D´nde poner los n´meros de p´gina? Y un largo etc´tera. o u a e Todas estas decisiones se encuentran en un archivo de estilo (extensi´n cls). Los archivos o standard son: article, report, book y letter, cada uno adecuado para escribir art´ ıculos cortos (sin cap´ ıtulos) o m´s largos (con cap´ a ıtulos), libros y cartas, respectivamente.

158

´ CAP´ ITULO 6. EL SISTEMA DE PREPARACION DE DOCUMENTOS TEX .

La elecci´n del estilo global se hace en la primera l´ o ınea del archivo:2 \documentclass{article} Esta l´ ınea ser´ aceptada por el compilador, pero nos entregar´ un documento con un a a tama˜o de letra peque˜o, t´cnicamente llamado de 10 puntos ´ 10pt (1pt = 1/72 pulgadas). n n e o Existen tres tama˜os de letra disponibles: 10, 11 y 12 pt. Si queremos un tama˜o de letra n n m´s grande, como el que tenemos en este documento, se lo debemos indicar en la primera a l´ ınea del archivo: \documentclass[12pt]{article} Todas las decisiones de estilo contenidas dentro del archivo cls son modificables, existiendo tres modos de hacerlo: a) Modificando el archivo cls directamente. Esto es poco recomendable, porque dicha modificaci´n (por ejemplo, un cambio de los m´rgenes) se har´ extensible a todos los o a ıa archivos compilados en nuestro computador, y esto puede no ser agradable, ya sea que nosotros seamos los unicos usuarios o debamos compartirlo. Por supuesto, podemos ´ deshacer los cambios cuando terminemos de trabajar, pero esto es tedioso. ´ b) Introduciendo comandos adecuados en el pre´mbulo. Esta es la opci´n m´s recomena o a dable y la m´s usada. Nos permite dominar decisiones espec´ a ıficas de estilo v´lidas s´lo a o para el archivo que nos interesa. c) Creando un nuevo archivo cls. Esto es muy recomendable cuando las modificaciones de estilo son abundantes, profundas y deseen ser reaprovechadas. Se requiere un poco de A experiencia en L TEX para hacerlo, pero a veces puede ser la unica soluci´n razonable. ´ o En todo caso, la opci´n a usar en la gran mayor´ de los casos es la b) (Sec. 6.9). o ıa

6.3.9.

Argumentos de comandos.

Hemos visto ya algunos comandos que requieren argumentos. Por ejemplo: \begin{equation}, \documentclass[12pt]{article}, \footnote{Nota}. Existen dos tipos de argumentos: 1. Argumentos obligatorios. Van encerrados en par´ntesis cursivos: \footnote{Nota}, e por ejemplo. Es obligatorio que despu´s de estos comandos aparezcan los par´ntesis. A e e veces es posible dejar el interior de los par´ntesis vac´ pero en otros casos el compilador e ıo, reclamar´ incluso eso (\footnote{} no genera problemas, pero \documentclass{} s´ es a ı un gran problema).
A Una propiedad muy general de los comandos de L TEX es que las llaves de los argumentos obligatorios se pueden omitir cuando dichos argumentos tienen s´lo un car´cter. Por o a ejemplo, \~n es equivalente a \~{n}. Esto permite escribir m´s f´cilmente muchas a a expresiones, particularmente matem´ticas, como veremos m´s adelante. a a
A En L TEX 2.09 esta primera l´ ınea debe ser \documentstyle[12pt]article, y el archivo de estilo tiene A extensi´n sty. Intentar compilar con L TEX 2.09 un archivo que comienza con \documentclass da un error. o A Por el contrario, la compilaci´n con L TEX 2ε de un archivo que comienza con \documentstyle no genera un o A A error, y L TEX entra en un modo de compatibilidad . Sin embargo, interesantes novedades de L TEX 2ε respecto A a L TEX 2.09 se pierden. 2

´ 6.3. INPUT BASICO.

159

2. Argumentos opcionales. Van encerrados en par´ntesis cuadrados. Estos argumentos e son omitibles, \documentclass[12pt]... . Ya dijimos que \documentclass{article} es aceptable, y que genera un tama˜o de letra de 10pt. Un argumento en par´ntesis n e cuadrados es una opci´n que modifica la decisi´n default del compilador (en este caso, o o lo obliga a usar 12pt en vez de sus instintivos 10pt).

6.3.10.

T´ ıtulo.

Un t´ ıtulo se genera con: \title{Una breve introducci\’on} \author{V\’{\i}ctor Mu\~noz} \date{30 de Junio de 1998} \maketitle \title, \author y \date pueden ir en cualquier parte (incluyendo el pre´mbulo) ana tes de \maketitle. \maketitle debe estar despu´s de \begin{document}. Dependiendo de e nuestras necesidades, tenemos las siguientes alternativas: a) Sin t´ ıtulo: \title{} b) Sin autor: \author{} c) Sin fecha: \date{} d) Fecha actual (en ingl´s): omitir \date. e e) M´s de un autor: a \author{Autor_1 \and Autor_2 \and Autor_3}
A Para art´ ıculos cortos, L TEX coloca el t´ ıtulo en la parte superior de la primera p´gina a del texto. Para art´ ıculos largos, en una p´gina separada. a

160

´ CAP´ ITULO 6. EL SISTEMA DE PREPARACION DE DOCUMENTOS TEX .

6.3.11.

Secciones.

Los t´ ıtulos de las distintas secciones y subsecciones de un documento (numerados adecuadamente, en negrita, como en este texto) se generan con comandos de la forma: \section{Una secci\’on} \subsection{Una subsecci\’on} Los comandos disponibles son (en orden decreciente de importancia): \part \chapter \section \subsection \subsubsection \paragraph \subparagraph

Los m´s a usados son \chapter, \section, \subsection \subsubsection. \chapter s´lo est´ disponible en los estilos report y book. o a

y

6.3.12.

Listas.

Los dos modos usuales de generar listas: a) Listas numeradas (ambiente enumerate):
\begin{enumerate} \item Nivel 1, \’{\i}tem \item Nivel 1, \’{\i}tem \begin{enumerate} \item Nivel 2, \’{\i}tem \begin{enumerate} \item Nivel 3, \’{\i}tem \end{enumerate} \end{enumerate} \item Nivel 1, \’{\i}tem \end{enumerate}

1. Nivel 1, ´ ıtem 1. 2. Nivel 1, ´ ıtem 2. a) Nivel 2, ´ ıtem 1. 1) Nivel 3, ´ ıtem 1. 3. Nivel 1, ´ ıtem 3.

1. 2. 1. 1.

3.

b) Listas no numeradas (ambiente itemize):
Nivel 1, ´ ıtem 1. Nivel 1, ´ ıtem 2. • Nivel 2, ´ ıtem 1. ◦ Nivel 3, ´ ıtem 1. Nivel 1, ´ ıtem 3. \begin{itemize} \item Nivel 1, {\’\i}tem \item Nivel 1, {\’\i}tem \begin{itemize} \item Nivel 2, {\’\i}tem \begin{itemize} \item Nivel 3, {\’\i}tem \end{itemize} \end{itemize} \item Nivel 1, {\’\i}tem \end{itemize}

1. 2. 1. 1.

3.

´ 6.3. INPUT BASICO.

161

Es posible anidar hasta tres niveles de listas. Cada uno usa tipos distintos de r´tulos, o seg´n el ambiente usado: n´meros ar´bes, letras y n´meros romanos para enumerate, y u u a u puntos, guiones y asteriscos para itemize. Los r´tulos son generados autom´ticamente por o a cada \item, pero es posible modificarlos agregando un par´metro opcional: a
a) Nivel 1, ´ ıtem 1. b) Nivel 1, ´ ıtem 2. \begin{enumerate} \item[a)] Nivel 1, \’{\i}tem 1. \item[b)] Nivel 1, \’{\i}tem 2. \end{enumerate}

\item es lo primero que debe aparecer despu´s de un \begin{enumerate} o \begin{itemize}. e

6.3.13.
Fonts.

Tipos de letras.

A Los fonts disponibles por default en L TEX son:

roman boldface sans serif

italic slanted

Small Caps typewriter

Los siguientes modos de cambiar fonts son equivalentes: texto texto texto texto texto Texto texto {\rm {\bf {\sf {\it {\sl {\sc {\tt texto} texto} texto} texto} texto} Texto} texto} \textrm{texto} \textbf{texto} \textsf{texto} \textit{texto} \textsl{texto} \textsc{texto} \texttt{texto}

\rm es el default para texto normal; \it es el default para texto enfatizado; \bf es el default para t´ ıtulos de cap´ ıtulos, secciones, subsecciones, etc. \textrm, \textbf, etc., s´lo permiten cambiar porciones definidas del texto, contenido o entre los par´ntesis cursivos. Con \rm, \bf, etc. podemos, omitiendo los par´ntesis, cambiar e e el font en todo el texto posterior:
Un cambio local de fonts y uno global, interminable e infinito. . . Un cambio {\sf local} de fonts \sl y uno global, interminable e infinito...

Tambi´n es posible tener combinaciones de estos fonts, por ejemplo, bold italic, pero no e sirven los comandos anteriores, sino versiones modificadas de \rm, \bf, etc.: \rmfamily \sffamily \ttfamily \mdseries

162 \bfseries \upshape \itshape \slshape \scshape

´ CAP´ ITULO 6. EL SISTEMA DE PREPARACION DE DOCUMENTOS TEX .

Por ejemplo: texto texto Texto texto texto {\bfseries\itshape texto} {\bfseries\upshape texto} (= {\bf texto}) {\ttfamily\scshape texto} {\sffamily\bfseries texto} {\sffamily\mdseries texto} (= {\sf texto})

Para entender el uso de estos comandos hay que considerar que un font tiene tres atributos: family (que distingue entre rm, sf y tt), series (que distingue entre md y bf), y shape (que distingue entre up, it, sl y sc). Cada uno de los comandos \rmfamily, \bfseries, etc., cambia s´lo uno de estos atributos. Ello permite tener versiones mixtas de los fonts, como o un slanted sans serif, imposible de obtener usando los comandos \sl y \sf. Los defaults para el texto usual son: \rmfamily, \mdseries y \upshape. Tama˜ o. n Los tama˜os de letras disponibles son: n
texto

\tiny \scriptsize \footnotesize \small

texto

\normalsize \large \Large

texto

\LARGE \huge \Huge

texto

texto

texto

texto

texto texto

texto

Se usan igual que los comandos de cambio de font \rm, \sf, etc., de la secci´n 6.3.13. o \normalsize es el default para texto normal; \scriptsize para sub o supra´ ındices; \footnotesize para notas a pie de p´gina. a

6.3.14.

Acentos y s´ ımbolos.

A L TEX provee diversos tipos de acentos, que se muestran en la Tabla 6.1 (como ejemplo consideramos la letra “o”, pero cualquiera es posible, por supuesto). (Hemos usado ac´ el a hecho de que cuando el argumento de un comando consta de un car´cter, las llaves son a omitibles.) Otros s´ ımbolos especiales y caracteres no ingleses disponibles se encuentran en la Tabla 6.2.

´ 6.3. INPUT BASICO. o ´ o ` o ˆ o ¨ \’o \‘o \^o \"o o ˜ o ¯ o ˙ o ˘ \~o \=o \. o \u o o ˇ o ˝ oo ˚ o \v o \H o \t{oo} \r o o \c o ¸ o \d o . o \b o ¯

163

Cuadro 6.1: Acentos. † ‡ § ¶ c a £ \dag \ddag \S \P \copyright \textcircled a \textvisiblespace \pounds œ Œ æ Æ ˚ a ˚ A ø Ø \oe \OE \ae \AE \aa \AA \o \O l L ß SS ¿ ¡ \l \L \ss \SS ?‘ !‘

Cuadro 6.2: S´ ımbolos especiales y caracteres no ingleses.

6.3.15.

Escritura de textos en castellano.

A L TEX emplea s´lo los caracteres ASCII b´sicos, que no contienen s´ o a ımbolos castellanos como ¿, ¡, n, etc. Ya hemos visto que existen comandos que permiten imprimir estos caracteres, ˜ y por tanto es posible escribir cualquier texto en castellano (y otros idiomas, de hecho).

Sin embargo, esto no resuelve todo el problema, porque en ingl´s y castellano las palabras e se cortan en “s´ ılabas” de acuerdo a reglas distintas, y esto es relevante cuando se debe cortar el A texto en l´ ıneas. L TEX tiene incorporados algoritmos para cortar palabras en ingl´s y, si se ha e A X en nuestro computador, tambi´n en castellano u otros hecho una instalaci´n especial de L TE o e A idiomas (a trav´s del programa babel, que es parte de la distribuci´n standard de L TEX 2ε ). e o En un computador con babel instalado y configurado para cortar en castellano basta incluir el comando \usepackage[spanish]{babel} en el pre´mbulo para poder escribir en castellano a cortando las palabras en s´ ılabas correctamente.3
A Sin embargo, ocasionalmente L TEX se encuentra con una palabra que no sabe cortar, en cuyo caso no lo intenta y permite que ella se salga del margen derecho del texto, o bien A toma decisiones no ´ptimas. La soluci´n es sugerirle a L TEX la silabaci´n de la palabra. Por o o o ejemplo, si la palabra conflictiva es matem\’aticas (generalmente hay problemas con las palabras acentuadas), entonces basta con reescribirla en la forma: ma\-te\-m\’a\-ti\-cas. A Con esto, le indicamos a L TEX en qu´ puntos es posible cortar la palabra. El comando \- no e tiene ning´n otro efecto, de modo que si la palabra en cuesti´n no queda al final de la l´ u o ınea, A L TEX por supuesto ignora nuestra sugerencia y no la corta. Consideremos el siguiente ejemplo:

Esto resuelve tambi´n otro problema: los encabezados de cap´ e ıtulos o ´ ındices, por ejemplo, son escritos Indice”, en vez de “Chapter” e “Index”, y cuando se usa el comando \date, la fecha aparece “Cap´ ıtulo” e “´ en castellano.

3

164

´ CAP´ ITULO 6. EL SISTEMA DE PREPARACION DE DOCUMENTOS TEX .
Podemos escribir matem\’aticas. O matem\’aticas. Podemos escribir ma\-te\-m\’a\-ti\-cas. O ma\-te\-m\’a\-ti\-cas.

Podemos escribir matem´tia cas. O matem´ticas. a Podemos escribir matem´tia cas. O matem´ticas. a

A En el primer caso, L TEX decidi´ por s´ mismo d´nde cortar “matem´ticas”. Como es una o ı o a palabra acentuada tuvo problemas y no lo hizo muy bien, pues qued´ demasiado espacio o A entre palabras en esa l´ ınea. En el segundo p´rrafo le sugerimos la silabaci´n y L TEX pudo a o tomar una decisi´n m´s satisfactoria. En el mismo p´rrafo, la segunda palabra “matem´ticas” o a a a tambi´n tiene sugerencias de corte, pero como no qued´ al final de l´ e o ınea no fueron tomadas en cuenta.

6.4.

F´rmulas matem´ticas. o a

Hemos mencionado tres formas de ingresar al modo matem´tico: $...$ (f´rmulas dentro a o del texto), $$...$$ (f´rmulas separadas del texto, no numeradas) y \begin{equation} ... o \end{equation} (f´rmulas separadas del texto, numeradas). Los comandos que revisaremos o en esta secci´n s´lo pueden aparecer dentro del modo matem´tico. o o a

6.4.1.
x2y x2y

Sub y supra´ ındices.
x^{2y} x_{2y} xy x y1
2

x^{y^{2}} (´ x^{y^2}) o x^{y_{1}} (´ x^{y_1}) o

xy 1

x^y_1 (´ x_1^y) o

\textsuperscript permite obtener supra´ ındices fuera del modo matem´tico: a
La 3a es la vencida. La 3\textsuperscript{a} es la vencida.

6.4.2.

Fracciones.

a) Horizontales n/2 n/2 b) Verticales 1 2 x= y + z/2 y2 + 1 x+y y 1 + z+1 \frac{1}{2}, \frac 1{2}, \frac{1}2 ´ \frac 12 o x = \frac{y + z/2}{y^2+1} \frac{x+y}{1 + \frac y{z+1}}

´ ´ 6.4. FORMULAS MATEMATICAS.

165

La forma a) es m´s adecuada y la preferida para fracciones dentro del texto, y la sea 1 gunda para f´rmulas separadas. \frac puede aparecer en f´rmulas dentro del texto ( 2 con o o $\frac 12$), pero esto es inusual y poco recomendable est´ticamente, salvo estricta necesie dad.

6.4.3.

Ra´ ıces.
√ √ n \sqrt{n} o ´ \sqrt n

a2 + b2 √ n 2

\sqrt{a^2 + b^2} \sqrt[n]{2}

6.4.4.
a)

Puntos suspensivos.
... \ldots

Para f´rmulas como o a1 a2 . . . an b) ··· \cdots a_1 a_2 \ldots a_n

Entre s´ ımbolos como +, −, = : x1 + · · · + xn c) . . . \vdots   x1  .   .  . xn d) ... \ddots  In×n   =   1 0 ··· 0 0 1 0   . ... .  . .  . . 0 0 ... 1 x_1 + \cdots + x_n

\ldots puede ser usado tambi´n en el texto usual: e
Arturo quiso salir. . . pero se detuvo. Arturo quiso salir\ldots pero se detuvo.

No corresponde usar tres puntos seguidos (...), pues el espaciado entre puntos es incorrecto.

166

´ CAP´ ITULO 6. EL SISTEMA DE PREPARACION DE DOCUMENTOS TEX . Min´sculas u α β γ δ ε ζ η \alpha \beta \gamma \delta \epsilon \varepsilon \zeta \eta θ ϑ ι κ λ µ ν ξ \theta \vartheta \iota \kappa \lambda \mu \nu \xi o π ρ σ ς o \pi \varpi \rho \varrho \sigma \varsigma τ υ φ ϕ χ ψ ω \tau \upsilon \phi \varphi \chi \psi \omega

May´sculas u Γ \Gamma ∆ \Delta Θ \Theta Λ \Lambda Ξ \Xi Π \Pi Σ \Sigma Υ \Upsilon Φ \Phi Ψ \Psi Ω \Omega

Cuadro 6.3: Letras griegas.

6.4.5.

Letras griegas.

Las letras griegas se obtienen simplemente escribiendo el nombre de dicha letra (en ingl´s): e \gamma. Para la may´scula correspondiente se escribe la primera letra con may´scula: \Gamma. u u 4 La lista completa se encuentra en la Tabla 6.3. No existen s´ ımbolos para α, β, η, etc. may´sculas, pues corresponden a letras romanas u (A, B, E, etc.).

6.4.6.

Letras caligr´ficas. a

Letras caligr´ficas may´sculas A, B, . . . , Z se obtienen con \cal. \cal se usa igual que a u los otros comandos de cambio de font (\rm, \it, etc.).
Sea F una funci´n con o F(x) > 0. Sea $\cal F$ una funci\’on con ${\cal F}(x) > 0$.

No son necesarios los par´ntesis cursivos la primera vez que se usan en este ejemplo, e porque el efecto de \cal est´ delimitado por los $. a

6.4.7.

S´ ımbolos matem´ticos. a

A L TEX proporciona una gran variedad de s´ ımbolos matem´ticos (Tablas 6.4, 6.5, 6.6, 6.7). a La negaci´n de cualquier s´ o ımbolo matem´tico se obtiene con \not: a

x<y a∈M
4

x \not < y a \not \in {\cal M}

Un ejemplo del uso de variantes de letras griegas, en el idioma griego σ se usa dentro de una palabra y ς se usa al finalizar una palabra. El nombre Felipe en griego, es Felip´s, y se escribe de la forma: Φεληπoς. El o ´ nombre Jos´, ser´ algo como Josu´ en griego: Ioσυ η o la palabra F´ e ıa e ´ ısica: Φυσικ´ η

´ ´ 6.4. FORMULAS MATEMATICAS.

167

± \pm \mp × \times ÷ \div ∗ \ast \star ◦ \circ • \bullet · \cdot

∩ \cap ∪ \cup \uplus \sqcap \sqcup ∨ \lor ∧ \land \ \setminus \wr

† ‡

\diamond \bigtriangleup \bigtriangledown \triangleleft \triangleright \bigcirc \dagger \ddagger \amalg

⊕ \oplus \ominus ⊗ \otimes \oslash \odot

Cuadro 6.4: S´ ımbolos de operaciones binarias.

⊂ ⊆

\leq \prec \preceq \ll \subset \subseteq \smile \frown \vdash

⊃ ⊇ ∈

\geq \succ \succeq \gg \supset \supseteq \sqsubseteq \in \dashv

≡ \equiv ∼ \sim \simeq \asymp ≈ \approx ∼ \cong = \sqsupseteq \ni

|= \models ⊥ \perp | \mid \parallel \bowtie = \neq . = \doteq ∝ \propto

Cuadro 6.5: S´ ımbolos relacionales.

← ⇐ → ⇒ ⇔ → ←

\gets \Leftarrow \to \Rightarrow \Leftrightarrow \mapsto \hookleftarrow \leftharpoonup \leftharpoondown \rightleftharpoons

←− ⇐= −→ =⇒ ⇐⇒ −→ →

\longleftarrow \Longleftarrow \longrightarrow \Longrightarrow \Longleftrightarrow \longmapsto \hookrightarrow \rightharpoonup \rightharpoondown

↑ ⇑ ↓ ⇓

\uparrow \Uparrow \downarrow \Downarrow \Updownarrow \nearrow \searrow \swarrow \nwarrow

Cuadro 6.6: Flechas

168

´ CAP´ ITULO 6. EL SISTEMA DE PREPARACION DE DOCUMENTOS TEX . ℵ \aleph \hbar ı \imath  \jmath \ell ℘ \wp \Re \Im \prime ∅ \emptyset √ \nabla \surd \top ⊥ \bot \| ∠ \angle ∀ \forall ∃ \exists ¬ \lnot \flat \natural \sharp \ \backslash ∂ \partial ∞ \infty \triangle ♣ \clubsuit ♦ \diamondsuit ♥ \heartsuit ♠ \spadesuit

Cuadro 6.7: S´ ımbolos varios. \sum \prod \coprod \int \oint \bigcap \bigcup \biguplus \bigvee \bigwedge \bigsqcup \bigodot \bigotimes \bigoplus

Cuadro 6.8: S´ ımbolos de tama˜o variable. n [Notemos, s´ en la Tabla 6.5, que existe el s´ ı, ımbolo = (\neq).] Algunos s´ ımbolos tienen tama˜o variable, seg´n aparezcan en el texto o en f´rmulas n u o separadas del texto. Se muestran en la Tabla 6.8. Estos s´ ımbolos pueden tener ´ ındices que se escriben como sub o supra´ ındices. Nuevamente, la ubicaci´n de estos ´ o ındices depende de si la f´rmula est´ dentro del texto o separada de ´l: o a e
n 1

xi =
i=1 n i=1 xi 0

f =
1 0 f

$$\sum_{i=1}^n x_i = \int_0^1 f $$ $\sum_{i=1}^n x_i = \int_0^1 f $

6.4.8.

Funciones tipo logaritmo.

Observemos la diferencia entre estas dos expresiones:
x = logy x = log y $x $x = log y$ = \log y$

A En el primer caso L TEX escribe el producto de cuatro cantidades, l, o, g e y. En el segundo, representa correctamente nuestro deseo: el logaritmo de y. Todos los comandos de la Tabla 6.9 generan el nombre de la funci´n correspondiente, en letras romanas. o Algunas de estas funciones pueden tener ´ ındices:

n→∞

l´ xn = 0 ım

$$\lim_{n\to\infty} x_n = 0 $$

´ ´ 6.4. FORMULAS MATEMATICAS. \arccos \arcsin \arctan \arg \cos \cosh \cot \coth \csc \deg \det \dim \exp \gcd \hom \inf \ker \lg \lim \liminf \limsup \ln \log \max \min \Pr \sec \sin \sinh \sup \tan \tanh

169

Cuadro 6.9: Funciones tipo logaritmo
l´ n→∞ xn = 0 ım $\lim_{n\to\infty} x_n = 0 $

6.4.9.

Matrices.

Ambiente array. Se construyen con el ambiente array. Consideremos, por ejemplo: a + b + c uv 27 a+b u+v 134 a 3u + vw 2.978 La primera columna est´ alineada al centro (c, center); la segunda, a la izquierda (l, left); la a tercera, a la derecha (r, right). array tiene un argumento obligatorio, que consta de tantas letras como columnas tenga la matriz, letras que pueden ser c, l o r seg´n la alineaci´n u o que queramos obtener. Elementos consecutivos de la misma l´ ınea se separan con & y l´ ıneas consecutivas se separan con \\. As´ el ejemplo anterior se obtiene con: ı, \begin{array}{clr} a+b+c & uv & 27 \\ a+b & u + v & 134 \\ a & 3u+vw & 2.978 \end{array} Delimitadores. Un delimitador es cualquier s´ ımbolo que act´e como un par´ntesis, encerrando una exu e presi´n, apareciendo a la izquierda y a la derecha de ella. La Tabla 6.10 muestra todos los o delimitadores posibles. Para que los delimitadores tengan el tama˜o correcto para encerrar la expresi´n corresponn o diente hay que anteponerles \left y \right. Podemos obtener as´ expresiones matriciales: ı
a b c d \left(\begin{array}{cc} a&b\\ c&d \end{array}\right) v = \left(\begin{array}{c} 1\\ 2\\ 3 \end{array}\right)

 1 v= 2  3

170

´ CAP´ ITULO 6. EL SISTEMA DE PREPARACION DE DOCUMENTOS TEX . ( ( [ [ { \{ \lfloor \lceil \langle / / | | ) ) ] ] } \} \rfloor \rceil \rangle \ \backslash \| Cuadro 6.10: Delimitadores ↑ \uparrow ↓ \downarrow \updownarrow ⇑ \Uparrow ⇓ \Downarrow \Updownarrow

∆=

a11 a12 a21 a22

\Delta = \left|\begin{array}{cc} a_{11} & a_{12}\\ a_{21} & a_{22} \end{array}\right|

\left y \right deben ir de a pares, pero los delimitadores no tienen por qu´ ser los e mismos:
a b \left(\begin{array}{c} a\\ b \end{array}\right[

Tampoco es necesario que los delimitadores encierren matrices. Comparemos, por ejemplo:
(A + B) = ( dF )x=a dx (\vec A + \vec B) = ( \frac{d \vec F}{dx} )_{x=a}

A+B =

dF dx

x=a

\left(\vec A + \vec B\right) = \left( \frac{d \vec F}{dx} \right)_{x=a}

El segundo ejemplo es mucho m´s adecuado est´ticamente. a e Algunas expresiones requieren s´lo un delimitador, a la izquierda o a la derecha. Un punto o (.) representa un delimitador invisible. Los siguientes ejemplos son t´ ıpicos:
b

dx
a

df = f (x) dx

b a

\left. \int_a^b dx \frac{df}{dx} = f(x) \right |_a^b f(x) = \left\{ \begin{array}{cl} 0 & x<0 \\ 1 & x>0 \end{array} \right.

f (x) =

0 x<0 1 x>0

´ ´ 6.4. FORMULAS MATEMATICAS. a \hat a ˆ a \check a ˇ a \breve a ˘ a \acute a ´ a \grave a ` a \tilde a ˜ a \bar a ¯ a \vec a a \dot a ˙ a \ddot a ¨

171

Cuadro 6.11: Acentos matem´ticos a F´rmulas de m´s de una l´ o a ınea. eqnarray ofrece una manera de ingresar a modo matem´tico (en reemplazo de $, $$ o a equation) equivalente a un array con argumentos {rcl}:
x = a+b+c+ d+e \begin{eqnarray*} x& = & a + b + c +\\ && d + e \end{eqnarray*}

El asterisco impide que aparezcan n´meros en las ecuaciones. Si deseamos que numere u cada l´ ınea como una ecuaci´n independiente, basta omitir el asterisco: o
x = 5 a + b = 60 (6.2) (6.3) \begin{eqnarray} x& = & 5 \\ a + b&= & 60 \end{eqnarray}

Si queremos que solamente algunas l´ ıneas aparezcan numeradas, usamos \nonumber:
x = a+b+c+ d+e (6.4) \begin{eqnarray} x& = & a + b + c + \nonumber\\ && d + e \end{eqnarray}

El comando \eqnarray es suficiente para necesidades sencillas, pero cuando se requiere escribir matem´tica de modo intensivo sus limitaciones comienzan a ser evidentes. Al agrea gar al pre´mbulo de nuestro documento la l´ a ınea \usepackage{amsmath} quedan disponibles muchos comandos mucho m´s utiles para textos matem´ticos m´s serios, como el ambiente a ´ a a equation*, \split, \multline o \intertext. En la secci´n 6.8.2 se encuentra una descripo ci´n de estos y otros comandos. o

6.4.10.

Acentos.

Dentro de una f´rmula pueden aparecer una serie de “acentos”, an´logos a los de texto o a usual (Tabla 6.11). Las letras i y j deben perder el punto cuando son acentuadas: i es incorrecto. Debe ser ı. \imath y \jmath generan las versiones sin punto de estas letras:
ı+ ˆ \vec \imath + \hat \jmath

172

´ CAP´ ITULO 6. EL SISTEMA DE PREPARACION DE DOCUMENTOS TEX .

6.4.11.
Vcr´ ıtico

Texto en modo matem´tico. a
V_{\mbox{\scriptsize cr\’{\i}tico}}

Para insertar texto dentro de modo matem´tico empleamos \mbox: a

Bastante m´s ´ptimo es utilizar el comando \text, disponible a trav´s de amsmath (secci´n a o e o 6.8.2).

6.4.12.

Espaciado en modo matem´tico. a

TEX ignora los espacios que uno escribe en las f´rmulas y los determina de acuerdo a sus propios o criterios. A veces es necesario ayudarlo para hacer ajustes finos. Hay cuatro comandos que agregan peque˜os espacios dentro de modo matem´tico: n a \, \! espacio peque˜o n espacio peque˜o (negativo) n √ \: \; espacio medio espacio grueso

Algunos ejemplos de su uso: √ 2x \sqrt 2 \, x en vez de n/log n n / \!\log n en vez de f dx \int f \, dx en vez de

2x n/ log n f dx

El ultimo caso es quiz´s el m´s frecuente, por cuanto la no inserci´n del peque˜o espacio adicional ´ a a o n entre f y dx hace aparecer el integrando como el producto de tres variables, f , d y x, que no es la idea.

6.4.13.

Fonts.

An´logamente a los comandos para texto usual (Sec. 6.3.13), es posible cambiar los fonts dentro a del modo matem´tico: a (A, x) (A, x) (A, B) (A, x) (A, x) (A, x) (A, x ) \mathrm{(A,x)} \mathnormal{(A,x)} \mathcal{(A,B)} \mathbf{(A,x)} \mathsf{(A,x)} \mathtt{(A,x)} \mathit{(A,x)}

(Recordemos que la letras tipo \cal s´lo existen en may´sculas.) o u Las declaraciones anteriores permiten cambiar los fonts de letras, d´ ıgitos y acentos, pero no de los otros s´ ımbolos matem´ticos: a ˜ A×1 \mathbf{\tilde A \times 1}

Como en todo ambiente matem´tico, los espacios entre caracteres son ignorados: a Hola \mathrm{H o l a}

Finalmente, observemos que \mathit corresponde al font it´lico, en tanto que \mathnormal al a font matem´tico usual, que es tambi´n it´lico. . . o casi: a e a

6.5. TABLAS.
dif f erent dif f erent different different $different$ $\mathnormal{different}$ $\mathit{different}$ \textit{different}

173

6.5.

Tablas.

array nos permiti´ construir matrices en modo matem´tico. Para tablas de texto existe tabular, o a que funciona de la misma manera. Puede ser usado tanto en modo matem´tico como fuera de ´l. a e Nombre Edad Profesi´n o : : : Juan P´rez e 26 Estudiante \begin{tabular}{lcl} Nombre&:&Juan P\’erez\\ Edad&:&26\\ Profesi\’on&:&Estudiante \end{tabular}

Si deseamos agregar l´ ıneas verticales y horizontales para ayudar a la lectura, lo hacemos insertando | en los puntos apropiados del argumento de tabular, y \hline al final de cada l´ ınea de la tabla: Item Vasos Botellas Platos Total Gastos $ 500 $ 1300 $ 500 $ 2300 \begin{tabular}{|l|r|}\hline Item&Gastos\\ \hline Vasos& \$ 500 \\ Botellas & \$ 1300 \\ Platos & \$ 500 \\ \hline Total& \$ 2300 \\ \hline \end{tabular}

6.6.

Referencias cruzadas.

Ecuaciones, secciones, cap´ ıtulos y p´ginas son entidades que van numeradas y a las cuales a podemos querer referirnos en el texto. Evidentemente no es ´ptimo escribir expl´ o ıcitamente el n´mero u correspondiente, pues la inserci´n de una nueva ecuaci´n, cap´ o o ıtulo, etc., su eliminaci´n o cambio de o orden del texto podr´ alterar la numeraci´n, oblig´ndonos a modificar estos n´meros dispersos en ıa o a u el texto. Mucho mejor es referirse a ellos de modo simb´lico y dejar que TEX inserte por nosotros o los n´meros. Lo hacemos con \label y \ref. u La ecuaci´n de Euler o eiπ + 1 = 0 (6.5) La ecuaci\’on de Euler \begin{equation} \label{euler} e^{i\pi} + 1 = 0 \end{equation} re\’une los n\’umeros m\’as importantes. La ecuaci\’on (\ref{euler}) es famosa.

re´ne los n´meros m´s imporu u a tantes. La ecuaci´n (6.5) es fao mosa.

El argumento de \label (reiterado luego en \ref) es una etiqueta simb´lica. Ella puede ser o cualquier secuencia de letras, d´ ıgitos o signos de puntuaci´n. Letras may´sculas y min´sculas son o u u

174

´ CAP´ ITULO 6. EL SISTEMA DE PREPARACION DE DOCUMENTOS TEX .

diferentes. As´ euler, eq:euler, euler_1, euler1, Euler, etc., son etiquetas v´lidas y distintas. ı, a Podemos usar \label dentro de equation, eqnarray y enumerate. Tambi´n podemos referenciar p´ginas con \pageref: e a Ver p´gina 174 para m´s dea a talles. [Texto en p´g. 174] a El significado de la vida. . . Ver p\’agina \pageref{significado} para m\’as detalles. ... El significado \label{significado} de la vida...

A L TEX puede dar cuenta de las referencias cruzadas gracias al archivo aux (auxiliar) generado durante la compilaci´n. o

Al compilar por primera vez el archivo, en el archivo aux es escrita la informaci´n de los \label o A X lee el archivo aux e incorpora esa informaci´n al encontrados. Al compilar por segunda vez, L TE o dvi. (En realidad, tambi´n lo hizo la primera vez que se compil´ el archivo, pero el aux no exist´ e o ıa entonces o no ten´ informaci´n util.) ıa o ´ Por tanto, para obtener las referencias correctas hay que compilar dos veces, una para generar el aux correcto, otra para poner la informaci´n en el dvi. Toda modificaci´n en la numeraci´n o o o tendr´ efecto s´lo despu´s de compilar dos veces m´s. Por cierto, no es necesario preocuparse de a o e a estos detalles a cada momento. Seguramente compilaremos muchas veces el archivo antes de tener A la versi´n final. En todo caso, L TEX avisa, tras cada compilaci´n, si hay referencias inexistentes o o u otras que pudieron haber cambiado, y sugiere compilar de nuevo para obtener las referencias correctas. (Ver Sec. 6.14.2.)

6.7.

Texto centrado o alineado a un costado.

Los ambientes center, flushleft y flushright permiten forzar la ubicaci´n del texto respecto o a los m´rgenes. L´ a ıneas consecutivas se separan con \\: Una l´ ınea centrada, otra y otra m´s. a Ahora el texto contin´a u alineado a la izquierda y finalmente dos l´ ıneas alineadas a la derecha. \begin{center} Una l\’{\i}nea centrada,\\ otra\\ y otra m\’as. \end{center} Ahora el texto contin\’ua \begin{flushleft} alineado a la izquierda \end{flushleft} y finalmente \begin{flushright} dos l\’{\i}neas\\ alineadas a la derecha. \end{flushright}

6.8. ALGUNAS HERRAMIENTAS IMPORTANTES

175

6.8.

Algunas herramientas importantes

A Hasta ahora hemos mencionado escencialmente comandos disponibles en L TEX standard. Sin A X, se vuelven insuficientes cuando embargo, ´stos, junto con el resto de los comandos b´sicos de L TE e a se trata de ciertas aplicaciones demasiado espec´ ıficas, pero no inimaginables: si queremos escribir A un texto de alta matem´tica, o usar L TEX para escribir partituras, o para escribir un archivo .tex a A en un teclado croata. . . . Es posible que con los comandos usuales L TEX responda a las necesidades, pero seguramente ello ser´ a un costo grande de esfuerzo por parte del autor del texto. Por esta a A raz´n, las distribuciones modernas de L TEX incorporan una serie de extensiones que hacen la vida o un poco m´s f´cil a los eventuales autores. En esta secci´n mencionaremos algunas extensiones muy a a o utiles. Muchas otras no est´n cubiertas, y se sugiere al lector consultar la documentaci´n de su ´ a o distribuci´n para saber qu´ otros paquetes se encuentran disponibles. o e A En general, las extensiones a L TEX vienen contenidas en paquetes (“packages”, en ingl´s), en e archivos .sty. As´ cuando mencionemos el paquete amsmath, nos referimos a caracter´ ı, ısticas disponibles en el archivo amsmath.sty. Para que los comandos de un paquete <package>.sty est´n e disponibles, deben ser cargados durante la compilaci´n, incluyendo en el pre´mbulo del documento o a la l´ ınea:

\usepackage{<package>} Si se requiere cargar m´s de un paquete adicional, se puede hacer de dos formas: a \usepackage{<package1>,<package2>} o \usepackage{<package1>} \usepackage{<package2>} Algunos paquetes aceptan opciones adicionales (del mismo modo que la clase article acepta la opci´n 12pt): o \usepackage[option1,option2]{<package1>} Revisemos ahora algunos paquetes utiles. ´

6.8.1.

babel

Permite el procesamiento de textos en idiomas distintos del ingl´s. Esto significa, entre otras e cosas, que se incorporan los patrones de silabaci´n correctos para dicho idioma, para cortar adecuao damente las palabras al final de cada l´ ınea. Adem´s, palabras claves como “Chapter”, “Index”, “List a of Figures”, etc., y la fecha dada por \date, son cambiadas a sus equivalentes en el idioma escogido. A La variedad de idiomas disponibles es enorme, pero cada instalaci´n de L TEX tiene s´lo algunos de o o ´ ellos incorporados. (Esta es una decisi´n que toma el administrador del sistema, de acuerdo a las o necesidades de los usuarios. Una configuraci´n usual puede ser habilitar la compilaci´n en ingl´s, o o e castellano, alem´n y franc´s.) a e Ya sabemos como usar babel para escribir en castellano: basta incluir en el pre´mbulo la l´ a ınea \usepackage[spanish]{babel}

176

´ CAP´ ITULO 6. EL SISTEMA DE PREPARACION DE DOCUMENTOS TEX .
A AMS-LTEX

6.8.2.

El paquete amsmath permite agregar comandos para escritura de textos matem´ticos profea sionales, desarrollados originalmente por la American Mathematical Society. Si un texto contiene abundante matem´tica, entonces seguramente incluir la l´ a ınea correspondiente en el pre´mbulo: a \usepackage{amsmath} aliviar´ mucho la tarea. He aqu´ algunas de las caracter´ a ı ısticas adicionales disponibles con AMSA L TEX.

Ambientes para ecuaciones
Con equation* generamos una ecuaci´n separada del texto, no numerada: o x = 2y − 3 \begin{equation*} x = 2y - 3 \end{equation*}

multline permite dividir una ecuaci´n muy larga en varias l´ o ıneas, de modo que la primera l´ ınea quede alineada con el margen izquierdo, y la ultima con el margen derecho: ´
15

= 1 + 2 + 3 + 4 + 5+
i=1

6 + 7 + 8 + 9 + 10+ 11 + 12 + 13 + 14 + 15 (6.6)

\begin{multline} \sum_{i=1}^{15} = 1 +2+3+4+5+\\ 6+7+8+9+10+\\ 11+12+13+14+15 \end{multline}

align permite reunir un grupo de ecuaciones consecutivas aline´ndolas (usando &, igual que la a alineaci´n vertical de tabular y array). gather hace lo mismo, pero centrando cada ecuaci´n en o o la p´gina independientemente. a

a1 = b1 + c1 a2 = b2 + c2 − d2 + e2

(6.7) (6.8)

\begin{align} a_1 &= b_1 + c_1 \\ a_2 &= b_2 + c_2 - d_2 + e_2 \end{align} \begin{gather} a_1 = b_1 + c_1 \\ a_2 = b_2 + c_2 - d_2 + e_2 \end{gather}

a1 = b1 + c1 a2 = b2 + c2 − d2 + e2

(6.9) (6.10)

Con multline*, align* y gather* se obtienen los mismos resultados, pero con ecuaciones no numeradas. split permite escribir una sola ecuaci´n separada en l´ o ıneas (como multline), pero permite alinear las l´ ıneas con & (como align). split debe ser usado dentro de un ambiente como equation, align o gather (o sus equivalentes con asterisco):

6.8. ALGUNAS HERRAMIENTAS IMPORTANTES

177

a1 = b1 + c1 = b2 + c2 − d2 + e2

(6.11)

\begin{equation} \begin{split} a_1& = b_1 + c_1 \\ & = b_2 + c_2 - d_2 + e_2 \end{split} \end{equation}

Espacio horizontal
\quad y \qquad insertan espacio horizontal en ecuaciones: x>y , x≤z , ∀x ∈ A ∀z ∈ B

\begin{gather*} x > y \ , \quad \forall\, x \in A \\ x \leq z \ , \qquad \forall\, z \in B \end{gather*}

Texto en ecuaciones
Para agregar texto a una ecuaci´n, usamos \text: o x = 2n − 1 , con n entero \begin{equation*} x = 2^n - 1 \ , \quad \text{con $n$ entero} \end{equation*}

\text se comporta como un buen objeto matem´tico, y por tanto se pueden agregar sub´ a ındices textuales m´s f´cilmente que con \mbox (ver secci´n 6.4.11): a a o Vcr´ ıtico $V_{\text{cr\’{\i}tico}}$

Referencia a ecuaciones
\eqref es equivalente a \ref, salvo que agrega los par´ntesis autom´ticamente: e a La ecuaci´n (6.5) era la de Euo ler. La ecuaci\’on \eqref{euler} era la de Euler.

Ecuaciones con casos
´ Esta es una construcci´n usual en matem´ticas: o a f(x)= \begin{cases} 1&\text{si $x<0$} \\ 0&\text{si $x>0$} \end{cases}

f (x) =

1 si x < 0 0 si x > 0

Notar c´mo es m´s simple que el ejemplo con los comandos convencionales en la secci´n 6.4.9. o a o

178

´ CAP´ ITULO 6. EL SISTEMA DE PREPARACION DE DOCUMENTOS TEX .

Texto insertado entre ecuaciones alineadas
Otra situaci´n usual es insertar texto entre ecuaciones alineadas, preservando la alineaci´n: o o x1 = a + b + c , x2 = d + e , y por otra parte x3 = f + g + h . \begin{align*} x_1 &= a + b + c \ , \\ x_2 &= d + e \ , \\ \intertext{y por otra parte} x_3 &= f + g + h \ . \end{align*}

Matrices y coeficientes binomiales
La complicada construcci´n de matrices usando array (secci´n 6.4.9), se puede reemplazar con o o ambientes como pmatrix y vmatrix, y comandos como \binom. a b c d \begin{pmatrix} a&b\\ c&d \end{pmatrix} \Delta = \begin{vmatrix} a_{11} & a_{12}\\ a_{21} & a_{22} \end{vmatrix} v = \binom{k}{2}

a a ∆ = 11 12 a21 a22 k 2

v=

Podemos observar que el espaciado entre los par´ntesis y el resto de la f´rmula es m´s adecuado e o a que el de los ejemplos en la secci´n 6.4.9. o

Flechas extensibles
Las flechas en la tabla 6.6 vienen en ciertos tama˜os predefinidos. amsmath proporciona flen chas extensibles \xleftarrow y \xrightarrow, para ajustar sub o super´ ındices demasiado anchos. Adem´s, tienen un argumento opcional y uno obligatorio, para colocar material sobre o bajo ellas: a A ← − − B −−→ C − D −− −− →
T U n+µ−1 n±i−1

A \xleftarrow{n+\mu-1} B \xrightarrow[T]{n\pm i-1} C \xrightarrow[U]{} D

Uso del paquete amssymb
Este paquete contiene s´ ımbolos matem´ticos muy est´ticos a la hora de referirse a los conjuntos a e de n´meros: u \mathbb{C} \mathbb{R} \mathbb{Z} para los n´meros complejos u para los n´meros reales u para los n´meros enteros u \mathbb{I} \mathbb{Q} \mathbb{N} para los n´meros imaginarios u para los n´meros racionales u para los n´meros naturales u

C R Z

I Q N

6.8. ALGUNAS HERRAMIENTAS IMPORTANTES
Otro sıımbolo interesante es: ∴ (\therefore) para “por lo tanto”.

179

6.8.3.

fontenc

A Ocasionalmente, L TEX tiene problemas al separar una palabra en s´ ılabas. T´ ıpicamente, eso ocurre con palabras acentuadas, pues, debido a la estructura interna del programa, un car´cter a como la “´” en “matem´ticas” no es tratado igual que los otros. Para solucionar el problema, y a a poder cortar en s´ ılabas palabras que contengan letras acentuadas (adem´s de acceder a algunos a caracteres adicionales), basta incluir el paquete fontenc:

\usepackage[T1]{fontenc} T´cnicamente, lo que ocurre es que la codificaci´n antigua para fonts es la OT1, que no contiene e o fonts acentuados, y que por lo tanto es util s´lo para textos en ingl´s. La codificaci´n T1 aumenta los ´ o e o fonts disponibles, permitiendo que los caracteres acentuados sean tratados en igual pie que cualquier otro.

6.8.4.

enumerate

A enumerate.sty define una muy conveniente extensi´n al ambiente enumerate de L TEX. El o comando se usa igual que siempre (ver secci´n 6.3.12), con un argumento opcional que determina o el tipo de etiqueta que se usar´ para la lista. Por ejemplo, si queremos que en vez de n´meros se a u usen letras may´sculas, basta usar \begin{enumerate}[A]: u

A Primer ´ ıtem. B Segundo ´ ıtem. Si queremos etiquetas de la forma “1.-”, \begin{enumerate}[1.-]: 1.- Primer ´ ıtem. 2.- Segundo ´ ıtem. Si deseamos insertar un texto que no cambie de una etiqueta a otra, hay que encerrarlo entre par´ntesis cursivos (\begin{enumerate}[{Caso} A:]): e Caso A: Primer ´ ıtem. Caso B: Segundo ´ ıtem.

6.8.5.

Color.

A A trav´s de PostScript es posible introducir color en documentos L TEX. Para ello, incluimos en e el pre´mbulo el paquete color.sty: a

\usepackage{color}

180

´ CAP´ ITULO 6. EL SISTEMA DE PREPARACION DE DOCUMENTOS TEX .

De este modo, est´ disponible el comando \color, que permite especificar un color, ya sea por a nombre (en el caso de algunos colores predefinidos), por su c´digo rgb (red-green-blue) o c´digo o o cmyk (cian-magenta-yellow-black). Por ejemplo: Un texto en azul Un texto en un segundo color Un texto en un tercer color Un texto en {\color{blue} azul} Un texto en un {\color[rgb]{1,0,1} segundo color} Un texto en un {\color[cmyk]{.3,.5,.75,0} tercer color} Los colores m´s frecuentes (azul, amarillo, rojo, etc.) se pueden dar por nombre, como en este a ejemplo. Si se da el c´digo rgb, se deben especificar tres n´meros entre 0 y 1, que indican la cantidad o u de rojo, verde y azul que constituyen el color deseado. En el ejemplo, le dimos m´xima cantidad de a rojo y azul, y nada de verde, con lo cual conseguimos un color violeta. Si se trata del c´digo cmyk los o n´meros a especificar son cuatro, indicando la cantidad de cian, magenta, amarillo y negro. En el u ejemplo anterior pusimos una cantidad arbitraria de cada color, y result´ un color caf´. Es evidente o e que el uso de los c´digos rgb y cmyk permite explorar infinidad de colores. o Observar que \color funciona de modo an´logo a los comandos de cambio de font de la secci´n a o 6.3.13, de modo que si se desea restringir el efecto a una porci´n del texto, hay que encerrar dicho o texto entre par´ntesis cursivos. An´logamente al caso de los fonts, existe el comando \textcolor, e a que permite dar el texto a colorear como argumento: Un texto en azul Un texto en un segundo color Un texto en un tercer color Un texto en \textcolor{blue}{azul} Un texto en un \textcolor[rgb]{1,0,1}{segundo color} Un texto en un \textcolor[cmyk]{.3,.5,.75,0}{tercer color}

6.9.

Modificando el estilo de la p´gina. a

TEX toma una serie de decisiones por nosotros. Ocasionalmente nos puede interesar alterar el comportamiento normal. Disponemos de una serie de comandos para ello, los cuales revisaremos a continuaci´n. Todos deben aparecer en el pre´mbulo, salvo en los casos que se indique. o a

6.9.1.

Estilos de p´gina. a

a) N´meros de p´gina. u a Si se desea que los n´meros de p´gina sean ar´bicos (1, 2, 3. . . ): u a a \pagenumbering{arabic} Para n´meros romanos (i, ii, iii,. . . ): u \pagenumbering{roman}

´ 6.9. MODIFICANDO EL ESTILO DE LA PAGINA.
arabic es el default. b) Estilo de p´gina. a El comando \pagestyle determina d´nde queremos que vayan los n´meros de p´gina: o u a \pagestyle{plain} N´meros de p´gina en el extremo inferior, u a al centro de la p´gina. (Default para estia los article, report.) N´meros de p´gina y otra informaci´n u a o (t´ ıtulo de secci´n, etc.) en la parte suo perior de la p´gina. (Default para estilo a book.) Sin n´meros de p´gina. u a

181

\pagestyle{headings}

\pagestyle{empty}

6.9.2.

Corte de p´ginas y l´ a ıneas.

TEX tiene modos internos de decidir cu´ndo cortar una p´gina o una l´ a a ınea. Al preparar la versi´n o final de nuestro documento, podemos desear coartar sus decisiones. En todo caso, no hay que hacer esto antes de preparar la versi´n verdaderamente final, porque agregar, modificar o quitar texto o puede alterar los puntos de corte de l´ ıneas y p´ginas, y los cortes inconvenientes pueden resolverse a solos. Los comandos de esta secci´n no van en el pre´mbulo, sino en el interior del texto. o a

Corte de l´ ıneas.
o ınea en un punto deseado En la p´gina 163 ya vimos un ejemplo de inducci´n de un corte de l´ a del texto, al dividir una palabra en s´ ılabas. Cuando el problema no tiene relaci´n con s´ o ılabas disponemos de dos comandos: \newline \linebreak Corta la l´ ınea y pasa a la siguiente en el punto indicado. Lo mismo, pero justificando la l´ ınea para adecuarla a los m´rgenes. a Un corte de l\’{\i}nea\newline no justificado a los m\’argenes en curso. Un corte de l\’{\i}nea\linebreak justificado a los m\’argenes en curso.

Un corte de l´ ınea no justificado a los m´rgenes a en curso. Un corte de l´ ınea justificado a los m´rgenes a en curso.

Observemos c´mo en el segundo caso, en que se usa \linebreak, la separaci´n entre palabras o o es alterada para permitir que el texto respete los m´rgenes establecidos. a

182

´ CAP´ ITULO 6. EL SISTEMA DE PREPARACION DE DOCUMENTOS TEX .

Corte de p´ginas. a
Como para cortar l´ ıneas, existe un modo violento y uno sutil: \newpage \clearpage Cambia de p´gina en el punto indicado. An´logo a a a \newline. Lo mismo, pero ajustando los espacios verticales en el texto para llenar del mejor modo posible la p´gina. a

\clearpage, sin embargo, no siempre tiene efectos visibles. Dependiendo de la cantidad y tipo de texto que quede en la p´gina, los espacios verticales pueden o no ser ajustados, y si no lo son, a el resultado termina siendo equivalente a un \newpage. TEX decide en ultima instancia qu´ es lo ´ e o ´ptimo. Adicionalmente, tenemos el comando: \enlargethispage{<longitud>} Cambia el tama˜o de la p´gina acn a tual en la cantidad <longitud>.

(Las unidades de longitud que maneja TEX se revisan a continuaci´n.) o

Unidades de longitud y espacios.
a) Unidades. TEX reconoce las siguientes unidades de longitud: cm mm in pt em ex cent´ ımetro mil´ ımetro pulgada punto (1/72 pulgadas) ancho de una “M” en el font actual altura de una “x” en el font actual

Las cuatro primeras unidades son absolutas; las ultimas dos, relativas, dependiendo del ta´ ma˜o del font actualmente en uso. n Las longitudes pueden ser n´meros enteros o decimales, positivos o negativos: u

1cm

1.6in

.58pt

-3ex

b) Cambio de longitudes. TEX almacena los valores de las longitudes relevantes al texto en comandos especiales:

´ 6.9. MODIFICANDO EL ESTILO DE LA PAGINA.
\parindent \textwidth \textheight \oddsidemargin \topmargin \baselineskip \parskip Sangr´ ıa. Ancho del texto. Altura del texto. Margen izquierdo menos 1 pulgada. Margen superior menos 1 pulgada. Distancia entre la base de dos l´ ıneas de texto consecutivas. Distancia entre p´rrafos. a

183

Todas estas variables son modificables con los comandos \setlength, que le da a una variable un valor dado, y \addtolength, que le suma a una variable la longitud especificada. Por ejemplo: \setlength{\parindent}{0.3em} \addtolength{\parskip}{1.5cm} (\parindent = 0.3 em.) (\parskip = \parskip + 1.5 cm.)

Por default, el ancho y altura del texto, y los m´rgenes izquierdo y superior, est´n definidos a a de modo que quede un espacio de una pulgada ( 2.56 cm) entre el borde del texto y el borde de la p´gina. a Un problema t´ ıpico es querer que el texto llene un mayor porcentaje de la p´gina. Por ejema plo, para que el margen del texto en los cuatro costados sea la mitad del default, debemos introducir los comandos: \addtolength{\textwidth}{1in} \addtolength{\textheight}{1in} \addtolength{\oddsidemargin}{-.5in} \addtolength{\topmargin}{-.5in} Las dos primeras l´ ıneas aumentan el tama˜o horizontal y vertical del texto en 1 pulgada. n Si luego restamos media pulgada del margen izquierdo y el margen superior, es claro que la distancia entre el texto y los bordes de la p´gina sera de media pulgada, como dese´bamos. a a c) Espacios verticales y horizontales. Se insertan con \vspace y \hspace: \vspace{3cm} \hspace{3cm} Algunos ejemplos: Un primer p´rrafo de un pea que˜o texto. n Un primer p\’arrafo de un peque\~no texto. \vspace{1cm} Y un segundo p\’arrafo separado del otro. Espacio vertical de 3 cm. Espacio horizontal de 3 cm.

Y un segundo p´rrafo separaa do del otro.

184

´ CAP´ ITULO 6. EL SISTEMA DE PREPARACION DE DOCUMENTOS TEX .
Tres palabras del resto. separadas Tres\hspace{.5cm}palabras \hspace{.5cm}separadas del resto.

Si por casualidad el espacio vertical impuesto por \vspace debiese ser colocado al comienzo de una p´gina, TEX lo ignora. Ser´ molesto visualmente que en algunas p´ginas el texto a ıa a comenzara algunos cent´ ımetros m´s abajo que en el resto. Lo mismo puede ocurrir si el a espacio horizontal de un \hspace queda al comienzo de una l´ ınea. Los comandos \vspace*{<longitud>} y \hspace*{<longitud>} permiten que el espacio en blanco de la <longitud> especificada no sea ignorado. Ello es util cuando invariablemente ´ queremos ese espacio vertical u horizontal, aunque sea al comienzo de una p´gina o una l´ a ınea —por ejemplo, para insertar una figura.

6.10.

Figuras.

A Lo primero que hay que decir en esta secci´n es que L TEX es un excelente procesador de texto, o tanto convencional como matem´tico. Las figuras, sin embargo, son un problema aparte. a A X provee un ambiente picture que permite realizar dibujos simples. Dentro de la estrucL TE tura \begin{picture} y \end{picture} se pueden colocar una serie de comandos para dibujar l´ ıneas, c´ ırculos, ´valos y flechas, as´ como para posicionar texto. Infortunadamente, el proceso de o ı ejecutar dibujos sobre un cierto umbral de complejidad puede ser muy tedioso para generarlo directamente. Existe software (por ejemplo, xfig) que permite superar este problema, pudi´ndose e A X. Sin embargo, picture dibujar con el mouse, exportando el resultado al formato picture de L TE tiene limitaciones (no se pueden hacer l´ ıneas de pendiente arbitraria), y por tanto no es una soluci´n o o ´ptima. Para obtener figuras de buena calidad es imprescindible recurrir a lenguajes gr´ficos externos, y a A X da la posibilidad de incluir esos formatos gr´ficos en un documento. De este modo, tanto el L TE a texto como las figuras ser´n de la m´s alta calidad. Las dos mejores soluciones son utilizar Metafont a a o PostScript. Metafont es un programa con un lenguaje de programaci´n gr´fico propio. De hecho, o a A X fueron creados usando Metafont, y sus capacidades permiten hacer dibujos los propios fonts de L TE de complejidad arbitraria. Sin embargo, los dibujos resultantes no son trivialmente reescalables, y exige aprender un lenguaje de programaci´n espec´ o ıfico. Una soluci´n mucho m´s vers´til, y adoptada como el est´ndar en la comunidad de usuarios o a a a A X, es el uso de PostScript. Como se mencion´ brevemente en la secci´n 1.13, al imprimir, de L TE o o una m´quina unix convierte el archivo a formato PostScript, y luego lo env´ a la impresora. Pero a ıa PostScript sirve m´s que para imprimir, siendo un lenguaje de programaci´n gr´fico completo, con a o a el cual podemos generar im´genes de gran calidad, y reescalables sin p´rdida de resoluci´n. Adem´s, a e o a muchos programas gr´ficos permiten exportar sus resultados en formato PostScript. Por lo tanto, a podemos generar nuestras figuras en alguno de estos programas (xfig es un excelente software, que satisface la mayor parte de nuestras necesidades de dibujos simples; octave o gnuplot pueden ser usados para generar figuras provenientes de c´lculos cient´ a ıficos, etc.), lo cual crear´ un archivo con a 5 Luego introducimos la figura en el extensi´n .ps (PostScript) o .eps (PostScript encapsulado). o A documento L TEX, a trav´s del paquete graphicx. e

eps es el formato preferido, pues contiene informaci´n sobre las dimensiones de la figura, informaci´n o o A que es utilizada por L TEX para insertar ´sta adecuadamente en el texto. e

5

6.10. FIGURAS.

185

6.10.1.

graphicx.sty

Si nuestra figura est´ en un archivo figura.eps, la instrucci´n a utilizar es: a o \documentclass[12pt]{article} \usepackage{graphicx} \begin{document} ... Texto ... \includegraphics[width=w, height=h]{figura.eps} ... \end{document} Los par´metros width y height son opcionales y puede omitirse uno para que el sistema escale a de acuerdo al par´metro dado. Es posible variar la escala completa de la figura o rotarla usando a comandos disponibles en graphicx. Una figura aqu´ ı: Una figura aqu\’{\i}: \begin{center} \includegraphics[height=3cm]{figura.eps} \end{center} puede hacer m\’as agradable el texto. puede hacer m´s agradable el a texto. En este ejemplo, indicamos s´lo la altura de la figura (3cm). El ancho fue determinado de modo o que las proporciones de la figura no fueran alteradas. Si no se especifica ni la altura ni el ancho, la figura es insertada con su tama˜o natural. n Observemos tambi´n que pusimos la figura en un ambiente center. Esto no es necesario, pero e normalmente uno desea que las figuras est´n centradas en el texto. e

6.10.2.

Ambiente figure.

Insertar una figura es una cosa. Integrarla dentro del texto es otra. Para ello est´ el ambiente a figure, que permite: (a) posicionar la figura autom´ticamente en un lugar predeterminado o espea cificado por el usuario; (b) numerar las figuras; y (c) agregar un breve texto explicativo junto a la figura. Coloquemos la misma figura de la secci´n anterior dentro de un ambiente figure. El input: o \begin{figure}[h] \begin{center} \includegraphics[height=3cm]{figura.eps} \end{center} \caption{Un sujeto caminando.} \label{caminando} \end{figure}

186

´ CAP´ ITULO 6. EL SISTEMA DE PREPARACION DE DOCUMENTOS TEX .

Figura 6.1: Un sujeto caminando.
da como resultado: figure delimita lo que en TEX se denomina un objeto flotante, es decir, un objeto cuya posici´n o no est´ determinada a priori, y se ajusta para obtener los mejores resultados posibles. TEX considera a (de acuerdo con la tradici´n), que la mejor posici´n para colocar una figura es al principio o al final o o de la p´gina. Adem´s, lo ideal es que cada p´gina tenga un cierto n´mero m´ximo de figuras, a a a u a que ninguna figura aparezca en el texto antes de que sea mencionada por primera vez, y que, por ´ supuesto, las figuras aparezcan en el orden en que son mencionadas. Estas y otras condiciones determinan la posici´n que un objeto flotante tenga al final de la compilaci´n. Uno puede forzar la o o A decisi´n de L TEX con el argumento opcional de figure: o t b h p (top) (bottom) (here) (page of floats) extremo superior de la p´gina a extremo inferior de la p´gina a aqu´ en el punto donde est´ el comando ı, a en una p´gina separada al final del texto a

El argumento adicional ! suprime, para ese objeto flotante espec´ ıfico, cualquier restricci´n que o exista sobre el n´mero m´ximo de objetos flotantes en una p´gina y el porcentaje de texto m´ u a a ınimo que debe haber en una p´gina. a Varios de estos argumentos se pueden colocar simult´nemente, su orden dictando la prioridad. a Por ejemplo,

\begin{figure}[htbp] ... \end{figure} indica que la figura se debe colocar como primera prioridad aqu´ mismo; si ello no es posible, al ı comienzo de p´gina (´sta o la siguiente, dependiendo de los detalles de la compilaci´n), y as´ sucea e o ı sivamente. Adem´s, figure numera autom´ticamente la figura, colocando el texto “Figura N :”, y \caption a a permite colocar una leyenda, centrada en el texto, a la figura. Puesto que la numeraci´n es autom´tio a ca, las figuras pueden ser referidas simb´licamente con \label y \ref (secci´n 6.6). Para que la o o referencia sea correcta, \label debe estar dentro del argumento de \caption, o despu´s, como e aparece en el ejemplo de la Figura 6.1 (\ref{caminando}!). Finalmente, notemos que la figura debi´ ser centrada expl´ o ıcitamente con center. figure no hace nada m´s que tratar la figura como un objeto flotante, proporcionar numeraci´n y leyenda. El a o resto es responsabilidad del autor.

6.11. CARTAS.

187

6.11.

Cartas.

Para escribir cartas debemos emplear el estilo letter en vez del que hemos utilizado hasta ahora, article. Comandos especiales permiten escribir una carta, poniendo en lugares adecuados la direcci´n del remitente, la fecha, la firma, etc. o A modo de ejemplo, consideremos el siguiente input: \documentclass[12pt]{letter} \usepackage[spanish]{babel} \begin{document} \address{Las Palmeras 3425\\ \~Nu\~noa, Santiago} \date{9 de Julio de 1998} \signature{Pedro P\’erez \\ Secretario} \begin{letter}{Dr.\ Juan P\’erez \\ Las Palmeras 3425 \\ \~Nu\~noa, Santiago} \opening{Estimado Juan} A\’un no tenemos novedades. Parece incre\’{\i}ble, pero los recientes acontecimientos nos han superado, a pesar de nuestros esfuerzos. Esperamos que mejores tiempos nos aguarden. \closing{Saludos,} \cc{Arturo Prat \\ Luis Barrios} \end{letter} \end{document} El resultado se encuentra en la pr´xima p´gina. o a

188

´ CAP´ ITULO 6. EL SISTEMA DE PREPARACION DE DOCUMENTOS TEX .

Las Palmeras 3425 ˜ n Nu˜oa, Santiago 9 de Julio de 1998 Dr. Juan P´rez e Las Palmeras 3425 ˜ n Nu˜oa, Santiago Estimado Juan A´n no tenemos novedades. u Parece incre´ ıble, pero los recientes acontecimientos nos han superado, a pesar de nuestros esfuerzos. Esperamos que mejores tiempos nos aguarden. Saludos,

Pedro P´rez e Secretario Copia a: Arturo Prat Luis Barrios

A 6.12. L TEX Y EL FORMATO PDF.

189

Observemos que el texto de la carta est´ dentro de un ambiente letter, el cual tiene un argua mento obligatorio, donde aparece el destinatario de la carta (con su direcci´n opcionalmente). o Los comandos disponibles son: \address{<direccion>} \signature{<firma>} \opening{<apertura>} \closing{<despedida>} \cc{<copias>} <direccion> del remitente. <firma> del remitente. F´rmula de <apertura>. o F´rmula de <despedida>. o Receptores de <copias> (si los hubiera).

Uno puede hacer m´s de una carta con distintos ambientes letter en un mismo archivo. Caa da una tomar´ el mismo remitente y firma dados por \address y \signature. Si deseamos que a \address o \signature valgan s´lo para una carta particular, basta poner dichos comandos entre o el \begin{letter} y el \opening correspondiente. Por ejemplo, la siguiente estructura: \documentclass[12pt]{letter} \begin{document} \address{<direccion remitente>} \date{<fecha>} \signature{<firma>} \begin{letter}{<destinatario 1>} \opening<apertura 1> ... \end{letter} \begin{letter}{<destinatario 2>} \address{<direccion remitente 2>} \signature{<firma 2>} \opening<apertura 2> ... \end{letter} \begin{letter}{<destinatario 3>} \opening<apertura 3> ... \end{letter} \end{document} dar´ origen a tres cartas con la misma direcci´n de remitente y firma, salvo la segunda. a o En todos estos comandos, l´ ıneas sucesivas son indicadas con \\.

6.12.

A LTEX y el formato pdf.

Junto con PostScript, otro formato ampliamente difundido para la transmisi´n de archivos, o especialmente a trav´s de Internet, es el formato pdf (Portable Document Format). Para generar un e

190

´ CAP´ ITULO 6. EL SISTEMA DE PREPARACION DE DOCUMENTOS TEX .

A archivo pdf con L TEX es necesario compilarlo con pdflatex. As´ pdflatex <archivo> generar´ un ı, a archivo <archivo>.pdf en vez del <archivo>.dvi generado por el compilador usual. Si nuestro documento tiene figuras, s´lo es posible incluirlas en el documento si est´n tambi´n o a e en formato pdf. Por tanto, si tenemos un documento con figuras en PostScript, debemos introducir dos modificaciones antes de compilar con pdflatex:

a) Cambiar el argumento de \includegraphics (secci´n 6.10) de <archivo_figura>.eps o a <archivo_figura>.pdf. b) Convertir las figuras PostScript a pdf (con epstopdf, por ejemplo). Si tenemos una figura en el archivo <archivo_figura>.eps, entonces epstopdf <archivo_figura>.eps genera el archivo correspondiente <archivo_figura>.pdf. Observar que el mismo paquete graphicx descrito en la secci´n 6.10 para incluir figuras o PostScript permite, sin modificaciones, incluir figuras en pdf.

6.13.

A Modificando LTEX.

Esta secci´n se puede considerar “avanzada”. Normalmente uno se puede sentir satisfecho con o A el desempe˜o de L TEX, y no es necesaria mayor intervenci´n. A veces, dependiendo de la aplicaci´n n o o y del autor, nos gustar´ modificar el comportamiento default. Una alternativa es definir nuevos ıa comandos que sean utiles para nosotros. Si esos nuevos comandos son abundantes, o queremos reu´ tilizarlos frecuentemente en otros documentos, lo conveniente es considerar crear un nuevo paquete o incluso una nueva clase. Examinaremos a continuaci´n los elementos b´sicos de estas modificaciones. o a

6.13.1.

Definici´n de nuevos comandos. o

El comando \newcommand
Un nuevo comando se crea con: \newcommand{<comando>}{<accion>} El caso m´s sencillo es cuando una estructura se repite frecuentemente en nuestro documento. a Por ejemplo, digamos que un sujeto llamado Crist´bal no quiere escribir su nombre cada vez que o aparece en su documento: Mi nombre es S´ como oyes, ı, Crist´bal Loyola. o Crist´bal. o Crist´bal. o \newcommand{\nombre}{Crist\’obal} ... \begin{document} ... Mi nombre es \nombre. S\’{\i}, como oyes, \nombre. \nombre\ Loyola.

Un \newcommand puede aparecer en cualquier parte del documento, pero lo mejor es que est´ en e el pre´mbulo, de modo que sea evidente qu´ nuevos comandos est´n disponibles en el presente a e a documento. Observemos adem´s que la definici´n de un comando puede contener otros comandos a o (en este caso, \’). Finalmente, notamos que ha sido necesario agregar un espacio expl´ ıcito con \ , al escribir “Crist´bal Loyola”: recordemos que un comando comienza con un backslash y termina o

A 6.13. MODIFICANDO L TEX.

191

con el primer car´cter que no es letra. Por tanto, \nombre Loyola ignora el espacio al final de a \nombre, y el output ser´ “Crist´balLoyola”. ıa o Tambi´n es posible definir comandos que funcionen en modo matem´tico: e a Sea x la velocidad, de modo ˙ que x(t) > 0 si t < 0. ˙ \newcommand{\vel}{\dot x} Sea $\vel$ la velocidad, de modo que $ \vel(t)> 0$ si $t<0$. Como \vel contiene un comando matem´tico (\dot), \vel s´lo puede aparecer en modo maa o tem´tico. a Podemos tambi´n incluir la apertura de modo matem´tico en la definici´n de \vel: e a o \newcommand{\vel}{$\dot x$}. De este modo, \vel (no $\vel$) da como output directamente x. Sin embargo, esta soluci´n no es ´ptima, porque la siguiente ocurrencia de \vel da un error. ˙ o o A En efecto, si \vel = $\dot x$, entonces $ \vel(t)>0$ = $ $\dot x$> 0$. En tal caso, L TEX ve que un modo matem´tico se ha abierto y cerrado inmediatamente, conteniendo s´lo un espacio a o A X acusa un entremedio, y luego, en modo texto, viene el comando \dot, que es matem´tico: L TE a error y la compilaci´n se detiene. o La soluci´n a este problema es utilizar el comando \ensuremath, que asegura que haya modo o matem´tico, pero si ya hay uno abierto, no intenta volverlo a abrir: a Sea x la velocidad, de modo ˙ que x(t) > 0 si t < 0. ˙ \newcommand{\vel}{\ensuremath{\dot x}} Sea \vel\ la velocidad, de modo que $ \vel(t)> 0$ si $t<0$. Un caso especial de comando matem´tico es el de operadores tipo logaritmo (ver Tabla 6.9). Si a queremos definir una traducci´n al castellano de \sin, debemos usar el comando \DeclareMathOperator o disponible via amsmath: Ahora podemos escribir en castellano, sen x. \usepackage{amsmath} \DeclareMathOperator{\sen}{sen} ... Ahora podemos escribir en castellano, $\sen x$.

A diferencia de \newcommand, \DeclareMathOperator s´lo puede aparecer en el pre´mbulo del o a documento. Un nuevo comando puede tambi´n ser usado para ahorrar tiempo de escritura, reemplazando e A X: comandos largos de L TE 1. El primer caso. 2. Ahora el segundo. 3. Y el tercero. \newcommand{\be}{\begin{enumerate}} \newcommand{\ee}{\end{enumerate}} \be \item El primer caso. \item Ahora el segundo. \item Y el tercero. \ee

192

´ CAP´ ITULO 6. EL SISTEMA DE PREPARACION DE DOCUMENTOS TEX .

Nuevos comandos con argumentos
Podemos tambi´n definir comandos que acepten argumentos. Si el sujeto anterior, Crist´bal, e o desea escribir cualquier nombre precedido de “Nombre:” en it´lica, entonces puede crear el siguiente a comando: Nombre: Crist´bal o Nombre: Violeta \newcommand{\nombre}[1]{\textit{Nombre:} #1} \nombre{Crist\’obal} \nombre{Violeta} Observemos que \newcommand tiene un argumento opcional, que indica el n´mero de argumentos u que el nuevo comando va a aceptar. Esos argumentos se indican, dentro de la definici´n del comando, o con #1, #2, etc. Por ejemplo, consideremos un comando que acepta dos argumentos: \newcommand{\fn}[2]{f(#1,#2)} f (x, y) + f (x3 , y∗) = 0 . $$ \fn{x}{y} + \fn{x_3}{y*} = 0 \ . $$

A En los casos anteriores, todos los argumentos son obligatorios. L TEX permite definir comandos con un (s´lo un) argumento opcional. Si el comando acepta n argumentos, el argumento opcional es o el #1, y se debe indicar, en un segundo par´ntesis cuadrado, su valor default. As´ podemos modificar e ı, el comando \fn del ejemplo anterior para que el primer argumento sea opcional, con valor default x:

\newcommand{\fn}[2][x]{f(#1,#2)} f (x, y) + f (x3 , y∗) = 0 . $$ \fn{y} + \fn[x_3]{y*} = 0 \ . $$

Redefinici´n de comandos o
Ocasionalmente no nos interesa definir un nuevo comando, sino redefinir la acci´n de un comando o preexistente. Esto se hace con \renewcommand: La antigua versi´n de ldots: o ... La nueva versi´n de ldots: o ••• La antigua versi\’on de {\tt ldots}: \ldots

\renewcommand{\ldots}{\textbullet \textbullet \textbullet} La nueva versi\’on de {\tt ldots}: \ldots

P´rrafos y cambios de l´ a ınea dentro de comandos
En el segundo argumento de \newcommand o \renewcommand puede aparecer cualquier comando A de L TEX, pero ocasionalmente la aparici´n de l´ o ıneas en blanco (para forzar un cambio de p´rrafo) a puede provocar problemas. Si ello ocurre, podemos usar \par, que hace exactamente lo mismo. Adem´s, la definici´n del comando queda m´s compacta: a o a

A 6.13. MODIFICANDO L TEX.

193

\newcommand{\comandolargo}{\par Un nuevo comando que incluye un cambio de p\’arrafo, porque deseamos incluir bastante texto.\par \’Este es el nuevo p\’arrafo.\par} Observemos en acci\’on el comando: \comandolargo Listo. da como resultado: Observemos en acci´n el comando: o Un nuevo comando que incluye un cambio de p´rrafo, pora que deseamos incluir bastante texto. ´ Este es el nuevo p´rrafo. a Listo. Un ejemplo m´s util ocurre cuando queremos asegurar un cambio de p´rrafo, por ejemplo, para a ´ a colocar un t´ ıtulo de secci´n: o Observemos comando: en acci´n o el \newcommand{\seccion}[1]{\par\vspace{.5cm} {\bf Secci\’on: #1}\par\vspace{.5cm}} Observemos en acci\’on el comando: \seccion{Ejemplo} Listo.

Secci´n: Ejemplo o Listo.

Adem´s de las l´ a ıneas en blanco, los cambios de l´ ınea pueden causar problemas dentro de la definici´n de un nuevo comando. El ejemplo anterior, con el comando \seccion, es un buen ejemplo: o notemos que cuando se defini´, pusimos un cambio de l´ o ınea despu´s de \vspace{.5cm}. Ese cambio e de l´ ınea es interpretado (como todos los cambios de l´ ınea) como un espacio en blanco, y es posible que, bajo ciertas circunstancias, ese espacio en blanco produzca un output no deseado. Para ello basta utilizar sabiamente el car´cter %, que permite ignorar todo el resto de la l´ a ınea, incluyendo el cambio de l´ ınea. Ilustremos lo anterior con los siguientes tres comandos, que subrayan (comando \underline) una palabra, y difieren s´lo en el uso de % para borrar cambios de l´ o ınea: Notar la diferencia entre: Un texto de prueba , Un texto de prueba , y Un texto de prueba. \newcommand{\texto}{ Un texto de prueba } \newcommand{\textodos}{% Un texto de prueba } \newcommand{\textotres}{% Un texto de prueba% } Notar la diferencia entre: \underline{\texto}, \underline{\textodos}, y \underline{\textotres}. \texto conserva espacios en blanco antes y despu´s del texto, \textodos s´lo el espacio en e o

194

´ CAP´ ITULO 6. EL SISTEMA DE PREPARACION DE DOCUMENTOS TEX .

blanco despu´s del texto, y \textotres no tiene espacios en blanco alrededor del texto. e

Nuevos ambientes
A Nuevos ambientes en L TEX se definen con \newenvironment:

\newenvironment{<ambiente>}{<comienzo ambiente>}{<final ambiente>} define un ambiente <ambiente>, tal que \begin{ambiente} ejecuta los comandos <comienzo ambiente>, y \end{ambiente} ejecuta los comandos <final ambiente>. Definamos un ambiente que, al comenzar, cambia el font a it´lica, pone una l´ a ınea horizontal (\hrule) y deja un espacio vertical de .3cm, y que al terminar cambia de p´rrafo, coloca XXX en a sans serif, deja un nuevo espacio vertical de .3cm, y vuelve al font roman: \newenvironment{na}{\it \hrule \vspace{.3cm}}{\par\sf XXX \vspace{.3cm}\rm} Entonces, con \begin{na} Hola a todos. Es un placer saludarlos en este d\’{\i}a tan especial. Nunca esper\’e una recepci\’on tan calurosa. \end{na} obtenemos:

Hola a todos. Es un placer saludarlos en este d´ tan especial. ıa Nunca esper´ una recepci´n tan calurosa. e o XXX Los nuevos ambientes tambi´n pueden ser definidos de modo que acepten argumentos. Como con e \newcommand, basta agregar como argumento opcional a \newenvironment un n´mero que indique u cu´ntos argumentos se van a aceptar: a \newenvironment{<ambiente>}[n]{<comienzo ambiente>}{<final ambiente>} Dentro de <comienzo ambiente>, se alude a cada argumento como #1, #2, etc. Los argumentos no pueden ser usados en los comandos de cierre del ambiente (<final ambiente>). Por ejemplo, modifiquemos el ambiente na anterior, de modo que en vez de colocar una l´ ınea horizontal al comienzo, coloque lo que le indiquemos en el argumento: \newenvironment{na}[1]{\it #1 \vspace{.3cm}}{\par\sf XXX\hrule\vspace{.3cm}\rm} Ahora us´moslo dos veces, cada una con un argumento distinto: e

A 6.13. MODIFICANDO L TEX.

195
El mismo ejemplo anterior, ahora es \begin{na}{\hrule} Hola a todos... \end{na} Pero podemos ahora cambiar el comienzo: \begin{na}{\it XXX} Hola a todos... \end{na}

El mismo ejemplo anterior, ahora es Hola a todos. . . XXX Pero podemos ahora cambiar el comienzo: XXX Hola a todos. . . XXX

6.13.2.

Creaci´n de nuevos paquetes y clases o

Si la cantidad de nuevos comandos y/o ambientes que necesitamos en nuestro documento es suficientemente grande, debemos considerar crear un nuevo paquete o una nueva clase. Para ello hay que tener clara la diferencia entre uno y otro. En general, se puede decir que si nuestros comandos involucran alterar la apariencia general del documento, entonces corresponde crear una nueva clase (.cls). Si, por el contrario, deseamos que nuestros comandos funcionen en un amplio rango de circunstancias, para diversas apariencias del documento, entonces lo adecuado es un paquete (.sty). Consideremos por ejemplo la experiencia de los autores de estos apuntes. Para crear estos apuntes necesitamos b´sicamente la clase book, con ciertas modificaciones: m´rgenes m´s peque˜os, inclusi´n a a a n o autom´tica de los paquetes amsmath, babel y graphicx, entre otros, y definici´n de ciertos ambientes a o espec´ ıficos. Todo ello afecta la apariencia de este documento, cambi´ndola de manera apreciable, a pero a la vez de un modo que en general no deseamos en otro tipo de documento. Por ello lo hemos compilado usando una clase adecuada, llamada mfm2.cls. Por otro lado, uno de los autores ha necesitado escribir muchas tareas, pruebas y controles de ayudant´ en su vida, y se ha convencido de que su trabajo es m´s f´cil creando una clase tarea.cls, ıa a a que sirve para esos tres prop´sitos, definiendo comandos que le permiten especificar f´cilmente la o a fecha de entrega de la tarea, o el tiempo disponible para una prueba, los nombres del profesor y el ayudante, etc., una serie de comandos espec´ ıficos para sus necesidades. Sin embargo, tanto en este documento que usa mfm2.cls, como en las tareas y pruebas que A usan tarea.cls, se utilizan algunos comandos matem´ticos que no vienen con L TEX, pero que a son recurrentes, como \sen (la funci´n seno en castellano), \modulo (el m´dulo de un vector), o o o \TLaplace (la transformada de Laplace). Para que estos comandos est´n disponibles en cualquier e tipo de documento, necesitamos reunirlos en un paquete, en este caso addmath.sty. De este modo, mfm2.cls, tarea.cls o cualquier otra clase pueden llamar a este paquete y utilizar sus comandos.

Estructura b´sica. a
La estructura b´sica de un paquete o una clase es: a a) Identificaci´n: Informaci´n general (nombre del paquete, fecha de creaci´n, etc.). (Obligatoria.) o o o b) Declaraciones preliminares: Opcionales, dependiendo del paquete o clase en cuesti´n. o c) Opciones: Comandos relacionados con el manejo de las opciones con las cuales el paquete o clase pueden ser invocados. (Opcional.)

196

´ CAP´ ITULO 6. EL SISTEMA DE PREPARACION DE DOCUMENTOS TEX .

d) M´s declaraciones: Aqu´ van los comandos que constituyen el cuerpo de la clase o paquete. a ı (Obligatoria: si no hay ninguna declaraci´n, el paquete o clase no hace nada, naturalmente.) o La identificaci´n est´ consituida por las siguientes dos l´ o a ıneas, que deben ir al comienzo del archivo: \NeedsTeXFormat{LaTeX2e} \ProvidesPackage{<paquete>}[<fecha> <otra informacion>]
A A La primera l´ ınea indica a L TEX que ´ste es un archivo para L TEX 2ε . La segunda l´ e ınea especifica que se trata de un paquete, indicando el nombre del mismo (es decir, el nombre del archivo sin extensi´n) y, opcionalmente, la fecha (en formato YYYY/MM/DD) y otra informaci´n relevante. Por o o ejemplo, nuestro paquete addmath.sty comienza con las l´ ıneas:

\NeedsTeXFormat{LaTeX2e} \ProvidesPackage{addmath}[1998/09/30 Macros matematicos adicionales (VM)] Si lo que estamos definiendo es una clase, usamos el comando \ProvidesClass. Para nuestra clase mfm2.cls: \NeedsTeXFormat{LaTeX2e} \ProvidesClass{mfm2}[2002/03/25 Estilo para apuntes MFM II (VM)] A continuaci´n de la identificaci´n vienen los comandos que se desean incorporar a trav´s de o o e este paquete o clase. Como hemos dicho, addmath.sty contiene muchos nuevos comandos matem´ticos que considea ramos necesario definir mientras escrib´ ıamos estos apuntes. Veamos los contenidos de una versi´n o simplificada de dicho paquete: \NeedsTeXFormat{LaTeX2e} \ProvidesPackage{addmath}[1998/09/30 Macros matematicos adicionales (VM)] \newcommand{\prodInt}[2]{\ensuremath \left(\, #1\, |\, #2\, \right ) } \newcommand{\promedio}[1]{\langle #1 \rangle} \newcommand{\intii}{\int_{-\infty}^{\infty}} \newcommand{\grados}{\ensuremath{^\circ}} \newcommand{\Hipergeometrica}[4]{{}_2F_1\left (#1, #2, #3\, ; #4\right )} ... De este modo, incluyendo en nuestro documento el paquete con \usepackage{addmath}, varios nuevos comandos est´n disponibles: a (x|y) x

\prodInt{x}{y} \promedio{x}

dz f (z) ∠ ABC = 90◦
2 F1 (a, b, c ; d) −∞

\intii dz\, f(z) \angle\, ABC = 90\grados \Hipergeometrica{a}{b}{c}{d}

A 6.13. MODIFICANDO L TEX.

197

Incluyendo otros paquetes y clases
Los comandos \RequirePackage y \LoadClass permiten cargar un paquete o una clase, respectivamente.6 . Esto es de gran utilidad, pues permite construir un nuevo paquete o clase aprovechando la funcionalidad de otros ya existentes. As´ nuestro paquete addmath.sty define bastantes comandos, pero nos gustar´ definir vaı, ıa A rios m´s que s´lo pueden ser creados con las herramientas de AMS-L TEX. Cargamos entonces a o en addmath.sty el paquete amsmath y otros relacionados, y estamos en condiciones de crear m´s a comandos: \NeedsTeXFormat{LaTeX2e} \ProvidesPackage{addmath}[1998/09/30 Macros matematicos adicionales (VM)] \RequirePackage{amsmath} \RequirePackage{amssymb} \RequirePackage{euscript} ... \newcommand{\norma}[1]{\ensuremath \left\lVert\, #1 \,\right\rVert} \newcommand{\intC}{{\sideset{^*}{}\int}} \DeclareMathOperator{\senh}{senh} ... Por ejemplo: x

\norma{x} dz f (z) \intC dz \, f(z) \senh (2y)

senh(2y)

La posibilidad de basar un archivo .sty o .cls en otro es particularmente importante para una clase, ya que contiene una gran cantidad de comandos y definiciones necesarias para compilar el documento exitosamente. Sin embargo, un usuario normal, aun cuando desee definir una nueva clase, estar´ interesado en modificar s´lo parte del comportamiento. Con \LoadClass, dicho usuario a o puede cargar la clase sobre la cual se desea basar, y luego introducir las modificaciones necesarias, facilitando enormemente la tarea. Por ejemplo, al preparar este documento fue claro desde el comienzo que se necesitaba esencialmente la clase book, ya que ser´ un texto muy extenso, pero tambi´n era claro que se requer´ ıa e ıan ciertas modificaciones. Entonces, en nuestra clase mfm2.cls lo primero que hacemos es cargar la clase book, m´s algunos paquetes necesarios (incluyendo nuestro addmath), y luego procedemos a a modificar o a˜adir comandos: n \NeedsTeXFormat{LaTeX2e} \ProvidesClass{mfm2}[2002/03/25 Estilo para apuntes MFM II (VM)] \LoadClass[12pt]{book} \RequirePackage[spanish]{babel}
Estos comandos s´lo se pueden usar en un archivo .sty o .cls Para documentos normales, la manera o de cargar un paquete es \usepackage, y para cargar una clase es \documentclass.
6

198

´ CAP´ ITULO 6. EL SISTEMA DE PREPARACION DE DOCUMENTOS TEX .

\RequirePackage{enumerate} \RequirePackage{addmath} En un archivo .sty o un .cls se pueden cargar varios paquetes con \RequirePackage. \LoadClass, en cambio, s´lo puede aparecer en un .cls, y s´lo es posible usarlo una vez (ya que normalmente o o clases distintas son incompatibles entre s´ ı).

Manejo de opciones
En el ultimo ejemplo anterior, la clase mfm2 carga la clase book con la opci´n 12pt. Esto significa ´ o que si nuestro documento comienza con \documentclass{mfm2}, ser´ compilado de acuerdo a la a clase book, en 12 puntos. No es posible cambiar esto desde nuestro documento. Ser´ mejor que ıa pudi´ramos especificar el tama˜o de letra fuera de la clase, de modo que \documentclass{mfm2} e n d´ un documento en 10 puntos, y \documentclass[12pt]{mfm2} uno en 12 puntos. Para lograr e esto hay que poder pasar opciones desde la clase mfm2 a book. El modo m´s simple de hacerlo es con \LoadClassWithOptions. Si mfm2.cls ha sido llamada a con opciones <opcion1>,<opcion2>, etc., entonces book ser´ llamada con las mismas opciones. a Por tanto, basta modificar en mfm2.cls la l´ ınea \LoadClass[12pt]{book} por: \LoadClassWithOptions{book} \RequirePackageWithOptions es el comando an´logo para paquetes. Si una clase o un paquete a llaman a un paquete <paquete_base> y desean pasarle todas las opciones con las cuales han sido invocados, basta indicarlo con: \RequirePackageWithOptions{<paquete_base>} El ejemplo anterior puede ser suficiente en muchas ocasiones, pero en general uno podr´ llamar ıa a nuestra nueva clase, mfm2, con opciones que no tienen nada que ver con book. Por ejemplo, podr´ ıamos llamarla con opciones spanish,12pt. En tal caso, deber´ pasarle spanish a babel, y ıa 12pt a book. M´s a´n, podr´ a u ıamos necesitar definir una nueva opci´n, que no existe en ninguna de o las clases o paquetes cargados por book, para modificar el comportamiento de mfm2.cls de cierta manera espec´ ıfica no prevista. Estas dos tareas, discriminar entre opciones antes de pasarla a alg´n u paquete determinado, y crear nuevas opciones, constituyen un manejo m´s avanzado de opciones. a A continuaci´n revisaremos un ejemplo combinado de ambas tareas, extraido de la clase con la cual o compilamos este texto, mfm2.cls. La idea es poder llamar a mfm2 con una opci´n adicional keys, que permita agregar al dvi o informaci´n sobre las etiquetas (dadas con \label) de ecuaciones, figuras, etc., que aparezcan en o el documento (veremos la utilidad y un ejemplo de esto m´s adelante). Lo primero es declarar una a nueva opci´n, con: o \DeclareOption{<opcion>}{<comando>} <opcion> es el nombre de la nueva opci´n a declarar, y <comando> es la serie de comandos que se o ejecutan cuando dicha opci´n es especificada. o As´ nuestro archivo mfm2.cls debe ser modificado: ı, \NeedsTeXFormat{LaTeX2e} \ProvidesClass{mfm2}[2002/03/25 Estilo para apuntes MFM II (VM)] ... \DeclareOption{keys}{...}

A 6.13. MODIFICANDO L TEX.

199

... \ProcessOptions\relax ... Observamos que despu´s de declarar la o las opciones (en este caso keys), hay que procesarlas, e con \ProcessOptions.7

Las l´ ıneas anteriores permiten que \documentclass{mfm2} y \documentclass[keys]{mfm2} sean ambas v´lidas, ejecut´ndose o no ciertos comandos dependiendo de la forma utilizada. a a Si ahora queremos que \documentclass[keys,12pt]{mfm2} sea una l´ ınea v´lida, dea bemos procesar keys dentro de mfm2.cls, y pasarle a book.cls las opciones restantes. El siguiente es el c´digo definitivo: o \NeedsTeXFormat{LaTeX2e} \ProvidesClass{mfm2}[2002/03/25 Estilo para apuntes MFM II (VM)] \newif\ifkeys\keysfalse \DeclareOption{keys}{\keystrue} \DeclareOption*{\PassOptionsToClass{\CurrentOption}{book}} \ProcessOptions\relax \LoadClass{book} \RequirePackage[spanish]{babel} \RequirePackage{amsmath} \RequirePackage{theorem} \RequirePackage{epsfig} \RequirePackage{ifthen} \RequirePackage{enumerate} \RequirePackage{addmath} \ifkeys\RequirePackage[notref,notcite]{showkeys}\fi <nuevos comandos de la clase mfm2.cls> Sin entrar en demasiados detalles, digamos que la opci´n keys tiene el efecto de hacer o que una cierta variable l´gica \ifkeys, sea verdadera (cuarta l´ o ınea del c´digo). La siguieno te l´ ınea (\DeclareOption*...) hace que todas las opciones que no han sido procesadas (12pt, por ejemplo) se pasen a la clase book. A continuaci´n se procesan las opciones con o \ProcessOptions, y finalmente se carga la clase book. Las l´ ıneas siguientes cargan todos los paquetes necesarios, y finalmente se encuentran todos los nuevos comandos y definiciones que queremos incluir en mfm2.cls. ´ Observemos que la forma particular en que se carga el paquete showkeys. Esa es precisamente la funci´n de la opci´n keys que definimos: showkeys.sty se carga con ciertas o o opciones s´lo si se da la opci´n keys. o o ¿Cu´l es su efecto? Consideremos el siguiente texto de ejemplo, en que mfm2 ha sido a llamada sin la opci´n keys: o
\relax es un comando de TEX que, esencialmente, no hace nada, ni siquiera introduce un espacio en blanco, y es util incluirlo en puntos cr´ ´ ıticos de un documento, como en este ejemplo.
7

200

´ CAP´ ITULO 6. EL SISTEMA DE PREPARACION DE DOCUMENTOS TEX .

\documentclass[12pt]{mfm2} \begin{document} La opci\’on \verb+keys+ resulta muy \’util cuando tengo objetos numerados autom\’aticamente, como una ecuaci\’on: \begin{equation} \label{newton} \vec F = m \vec a \ . \end{equation} y luego quiero referirme a ella: Ec.\ \eqref{newton}. En el primer caso, se ha compilado sin la opci´n keys, y en el segundo con ella. El efecto o es que, si se usa un \label en cualquier parte del documento, aparece en el margen derecho una caja con el nombre de dicha etiqueta (en este caso, newton). Esto es util para cualquier ´ tipo de documentos, pero lo es especialmente en textos como estos apuntes, muy extensos y con abundantes referencias. En tal caso, tener un modo visual, r´pido, de saber los nombres a de las ecuaciones sin tener que revisar trabajosamente el archivo fuente es una gran ayuda. As´ versiones preliminares pueden ser compiladas con la opci´n keys, y la versi´n final sin ı, o o ella, para no confesar al lector nuestra mala memoria o nuestra comodidad.

A 6.13. MODIFICANDO L TEX.

201

Caso 1: \documentclass[12pt]{mfm2} La opci´n keys resulta muy util cuando tengo objetos numeo ´ rados autom´ticamente, como una ecuaci´n: a o F = ma . y luego quiero referirme a ella: Ec. (1). (1)

Caso 2: \documentclass[keys,12pt]{mfm2} La opci´n keys resulta muy util cuando tengo objetos numeo ´ rados autom´ticamente, como una ecuaci´n: a o F = ma . y luego quiero referirme a ella: Ec. (1). (1) newton

202

´ CAP´ ITULO 6. EL SISTEMA DE PREPARACION DE DOCUMENTOS TEX .

6.14.
6.14.1.

Errores y advertencias.
Errores.

Un mensaje de error t´ ıpico tiene la forma: LaTeX error. See LaTeX manual for explanation. Type H <return> for immediate help. ! Environment itemie undefined. \@latexerr ...or immediate help.}\errmessage {#1} \endgroup l.140 \begin{itemie} ?
A La primera l´ ınea nos comunica que L TEX ha encontrado un error. A veces los errores tienen que ver con procesos m´s internos, y son encontrados por TEX. Esta l´ a ınea nos informa qui´n encontr´ el error. e o La tercera l´ ınea comienza con un signo de exclamaci´n. Este es el indicador del error. Nos o ´ dice de qu´ error se trata. e Las dos l´ ıneas siguientes describen el error en t´rminos de comandos de bajo nivel. e La l´ ınea 6 nos dice d´nde ocurri´ el error: la l´ o o ınea 140 en este caso. Adem´s nos informa a del texto conflictivo: \begin{itemie}. A En realidad, el mensaje nos indica d´nde L TEX advirti´ el error por primera vez, que no o o es necesariamente el punto donde el error se cometi´. Pero la gran mayor´ de las veces la o ıa indicaci´n es precisa. De hecho, es f´cil darse cuenta, con la tercera l´ o a ınea (Environment itemie undefined) y la sexta (\begin{itemie}) que el error consisti´ en escribir itemie en vez de itemize. La o A X es clara en este caso y nos dice correctamente qu´ ocurri´ y d´nde. informaci´n de L TE o e o o A Luego viene un ?. L TEX est´ esperando una respuesta de nosotros. Tenemos varias altera nativas. Comentaremos s´lo cuatro, t´ o ıpicamente usadas:

(a) h <Enter> Solicitamos ayuda. TEX nos explica brevemente en qu´ cree ´l que consiste el error y/o e e nos da alguna recomendaci´n. o (b) x <Enter> Abortamos la compilaci´n. Deberemos volver al editor y corregir el texto. Es la opci´n o o m´s t´ a ıpica cuando uno tiene ya cierta experiencia, pues el mensaje basta para reconocer el error. (c) <Enter> Ignoramos el error y continuamos la compilaci´n. TEX hace lo que puede. En algunos o casos esto no tiene consecuencias graves y podremos llegar hasta el final del archivo sin mayores problemas. En otros casos, ignorar el error puede provocar que ulteriores comandos —perfectamente v´lidos en principio— no sean reconocidos y, as´ acumular a ı,

6.14. ERRORES Y ADVERTENCIAS.

203

muchos errores m´s. Podemos continuar con <Enter> sucesivos hasta llegar al final de a la compilaci´n. o (d) q <Enter> La acci´n descrita en el punto anterior puede llegar a ser tediosa o infinita. q hace o ingresar a TEX en batchmode, modo en el cual la compilaci´n prosigue ignorando todos o los errores hasta el final del archivo, sin enviar mensajes a pantalla y por ende sin que debamos darle infinitos <Enter>. Las opciones (c) y (d) son utiles cuando no entendemos los mensajes de error. Como ´ TEX seguir´ compilando haciendo lo mejor posible, al mirar el dvi puede que veamos m´s a a claramente d´nde comenzaron a ir mal las cosas y, por tanto, por qu´. o e
A Como dijimos, L TEX indica exactamente d´nde encontr´ el error, de modo que hemos de o o ponerle atenci´n. Por ejemplo, si tenemos en nuestro documento la l´ o ınea:

... un error inesperado\fotnote{En cualquier punto.} puede decidir... generar´ el mensaje de error: ıa ! Undefined control sequence. l.249 ...un error inesperado\fotnote {En cualquier punto.} ? En la l´ ınea de localizaci´n, L TEX ha cortado el texto justo despu´s del comando inexiso A e A X no s´lo indica la l´ tente. L TE o ınea en la cual detect´ el error, sino el punto de ella donde ello o ocurri´. (En realidad, hizo lo mismo —cortar la l´ o ınea para hacer resaltar el problema— en el o ı caso expuesto en la p´g. 202, pero ello ocurri´ en medio de comandos de bajo nivel, as´ que a no era muy informativo de todos modos.) Errores m´s comunes. a Los errores m´s comunes son: a a) Comando mal escrito. b) Par´ntesis cursivos no apareados. e c) Uso de uno de los caracteres especiales #, $, %, &, _, {, }, ~, ^, \ como texto ordinario. d) Modo matem´tico abierto de una manera y cerrado de otra, o no cerrado. a e) Ambiente abierto con \begin... y cerrado con un \end... distinto. f) Uso de un comando matem´tico fuera de modo matem´tico. a a g) Ausencia de argumento en un comando que lo espera. h) L´ ınea en blanco en ambiente matem´tico. a

204

´ CAP´ ITULO 6. EL SISTEMA DE PREPARACION DE DOCUMENTOS TEX .

Algunos mensajes de error.
A A continuaci´n, una peque˜a lista de errores (de L TEX y TEX) en orden alfab´tico, y sus o n e posibles causas.

* Falta \end{document}. (Dar Ctrl-C o escribir \end{document} para salir de la compilaci´n.) o ! \begin{...} ended by \end{...} Error e) de la Sec. 6.14.1. El nombre del ambiente en \end{...} puede estar mal escrito, sobra un \begin o falta un \end. ! Double superscript (o subscript). Una expresi´n como x^2^3 o x_2_3. Si se desea obtener x2 (x23 ), escribir {x^2}^3 ({x_2}_3). o ! Environment ... undefined. \begin{...} con un argumento que corresponde a un ambiente no definido. ! Extra alignment tab has been changed. En un tabular o array sobra un &, falta un \\, o falta una c, l ´ r en el argumento o obligatorio. ! Misplaced alignment tab character &. Un & aparece fuera de un tabular o array. ! Missing $ inserted. Errores c), d), f), h) de la Sec. 6.14.1. ! Missing { (o }) inserted. Par´ntesis cursivos no apareados. e ! Missing \begin{document}. Falta \begin{document} o hay algo incorrecto en el pre´mbulo. a ! Missing number, treated as zero.
A Falta un n´mero u donde L TEX \setlength{\textwidth}{a}, etc. 3

lo

espera:

\hspace{},

\vspace cm,

! Something’s wrong -- perhaps a missing \item. Posiblemente la primera palabra \begin{itemize} no es \item. ! Undefined control sequence. Aparece una secuencia \<palabra>, donde <palabra> no es un comando. despu´s e de un \begin{enumerate} o

6.14. ERRORES Y ADVERTENCIAS.

205

6.14.2.

Advertencias.

A La estructura de una advertencia de L TEX es:

LaTeX warning. <mensaje>. Algunos ejemplos: Label ‘...’ multiply defined. Dos \label tienen el mismo argumento. Label(s) may have changed. Rerun to get cross-references right. Los n´meros impresos por \ref y \pageref pueden ser incorrectos, pues los valores corresu pondientes cambiaron respecto al contenido del aux generado en la compilaci´n anterior. o Reference ‘...’ on page ... undefined. El argumento de un \ref o un \pageref no fue definido por un \label. TEX tambi´n env´ advertencias. Se reconocen porque no comienzan con TeX warning. e ıa Algunos ejemplos. Overfull \hbox ... TEX no encontr´ un buen lugar para cortar una l´ o ınea, y puso m´s texto en ella que lo a conveniente. Overfull \vbox ... TEX no encontr´ un buen lugar para cortar una p´gina, y puso m´s texto en ella que lo o a a conveniente. Underfull \hbox ... TEX construy´ una l´ o ınea con muy poco material, de modo que el espacio entre palabras puede ser excesivo. Underfull \vbox ... TEX construy´ una p´gina con muy poco material, de modo que los espacios verticales (entre o a p´rrafos) pueden ser excesivos. a
A Las advertencias de L TEX siempre deben ser atendidas. Una referencia doblemente definiA da, o no compilar por segunda vez cuando L TEX lo sugiere, generar´ un resultado incorrecto a en el dvi. Una referencia no definida, por su parte, hace aparecer un signo ?? en el texto final. Todos resultados no deseados, por cierto. Las advertencias de TEX son menos decisivas. Un overfull o underfull puede redundar en que alguna palabra se salga del margen derecho del texto, que el espaciado entre palabras en una l´ ınea sea excesivo, o que el espacio vertical entre p´rrafos sea demasiado. Los est´ndares a a de calidad de TEX son altos, y por eso env´ advertencias frecuentemente. Pero generalmente ıa los defectos en el resultado final son imperceptibles a simple vista, o por lo menos no son suficientes para molestarnos realmente. A veces s´ por supuesto, y hay que estar atentos. ı, Siempre conviene revisar el texto y prestar atenci´n a estos detalles, aunque ello s´lo tiene o o sentido al preparar la versi´n definitiva del documento. o

206

´ CAP´ ITULO 6. EL SISTEMA DE PREPARACION DE DOCUMENTOS TEX .

Parte II M´todos Num´ricos. e e

207

Cap´ ıtulo 7 Preliminares.
versi´n 4.1, 6 de Noviembre del 2007 1 . o

7.1.

Programas y funciones.

En esta secci´n nosotros escribiremos algunos programas simples usando Python, C++ y o Octave. En nuestro primer ejemplo, llamado orthog, probaremos si dos vectores son ortogonales calculando su producto punto. Este simple programa lo bosquejamos a continuaci´n o Inicializamos los vectores a y b. Evaluamos el producto punto como a · b = a1 b1 + a2 b2 + a3 b3 . Imprimir el producto punto y establecer si los vectores son ortogonales. Programa de ortogonalidad en Python. Escribimos una clase en Python de vectores en tres dimensiones en el archivo vector3d.py, el constructor y sobrecargamos la multiplicaci´n y la impresi´n o o from math import sqrt class Vec3: def __init__(self, x=0, y=0, z=0): self.x = x self.y = y self.z = z def __mul__(self,new): return self.x*new.x+self.y*new.y+self.z*new.z def __repr__(self): return ‘‘(%1.5f,%1.5f,%1.5f)’’ % (self.x,self.y,self.z)
Este cap´ ıtulo est´ basado en el primer cap´ a ıtulo del libro: Numerical Methods for Physics, second edition de Alejandro L. Garcia, editorial Prentice Hall
1

209

210

CAP´ ITULO 7. PRELIMINARES.

Escribimos el programa, orthog, usando la clase anterior #!/usr/bin/env python from vector3d import * def main(): x1=input(‘‘Ingrese la primera coordenada del 1er vector : ‘‘) x2=input(‘‘Ingrese la segunda coordenada del 1er vector : ‘‘) x3=input(‘‘Ingrese la tercera coordenada del 1er vector : ‘‘) c=Vec3(x1,x2,x3) x1=input(‘‘Ingrese la primera coordenada del 2do vector : ‘‘) x2=input(‘‘Ingrese la segunda coordenada del 2do vector : ‘‘) x3=input(‘‘Ingrese la tercera coordenada del 2do vector : ‘‘) d=Vec3(x1,x2,x3) if c*d==0: print ‘‘Los vectores ingresados son ortogonales’’ else: print ‘‘Los vectores ingresados no son ortogonales’’

if __name__ == ‘__main__’: main() Primero cambiamos los permisos del archivo orthog.py para que sea ejecutable y luego usamos el programa jrogan@huelen:~/programas_metodos_numericos/pyhton$ chmod 744 orthog.py%$ jrogan@huelen:~/programas_metodos_numericos/pyhton$ orthog.py%$ Ingrese la primera coordenada del 1er vector : 1 Ingrese la segunda coordenada del 1er vector : 0 Ingrese la tercera coordenada del 1er vector : 0 Ingrese la primera coordenada del 2do vector : 0 Ingrese la segunda coordenada del 2do vector : 1 Ingrese la tercera coordenada del 2do vector : 0 Los vectores ingresados son ortogonales Programa de ortogonalidad en C++. Ahora consideremos la versi´n en C++ del programa orthog, el cual prueba si dos vectores o son ortogonales mediante el c´lculo de su producto punto. Primero escribiremos una clase a muy b´sica de vectores en tres dimensiones. a

7.1. PROGRAMAS Y FUNCIONES. Las declaraciones est´n en vector3d.h a #ifndef _vector_3d_h #define _vector_3d_h // // Clase basica de vectores 3d // #include <iostream> class Vector{ private: double c_x; double c_y; double c_z; public: Vector():c_x(0),c_y(0),c_z(0) {} ; Vector(double x, double y, double z):c_x(x),c_y(y),c_z(z) {} ; ~Vector() {} ; double x() const {return c_x;}; double y() const {return c_y;}; double z() const {return c_z;}; }; double operator * (const Vector &, const Vector &) ; istream & operator >> (istream &, Vector &) ; #endif

211

La peque˜a implementaci´n necesaria para esta clase la escribimos en vector3d.cc el cual n o es listado a continuaci´n o #include "vector3d.h" double operator * (const Vector & v1, const Vector &v2) { return v1.x()*v2.x()+v1.y()*v2.y()+ v1.z()*v2.z() ; } istream & operator >> (istream & is, Vector & v) { double x,y,z ; is >> x >> y>>z ; v= Vector(x,y,z) ; return is; } Ahora estamos en condiciones de escribir el programa propiamente tal. Las primeras l´ ıneas son

212

CAP´ ITULO 7. PRELIMINARES.

// orthog - Programa para probar si un par de vectores es ortogonal. // Supondremos vectores en 3D. #include ‘‘vector3d.h’’ using namespace std; Las primeras l´ ıneas son comentarios que nos recuerdan lo que el programa hace. La l´ ınea siguiente incluye las definiciones de nuestra reci´n creada clase. Luego inclu´ e ımos una l´ ınea dice que vamos a usar el namespace std. A continuaci´n comienza el programa o // // orthog - Programa para probar si un par de vectores es ortogonal. Usaremos vectores en 3D.

#include "vector3d.h" using namespace std; int main() { Vector a, b; cout << "Ingrese el primer vector : "; cin >> a ; cout << "Ingrese el segundo vector : "; cin >> b ; if(a*b==0) { cout <<"Son ortogonales" << endl; } else { cout << "No son ortogonales"<< endl ; } return 0; } Declaramos dos objetos tipo Vector, a y b para almacenar los vectores que entran. La instrucci´n de salida despliega sobre la pantalla: o Ingrese el primer vector : La instrucci´n de entrada lee el Vector en a y luego, de la misma manera, el Vector b. Las o pr´ximas l´ o ıneas hacen el trabajo if(a*b==0) { cout <<"Son ortogonales" << endl; } else { cout << "No son ortogonales"<< endl ; } y despliega el resultados. Aqu´ los comandos de compilaci´n y una salida t´ ı o ıpica del programa.

7.1. PROGRAMAS Y FUNCIONES. jrogan@pucon:~$ g++ -Wall -o orthog orthog.cc vector3d.cc jrogan@pucon:~$ orthog Ingrese el primer vector : 1 0 0 Ingrese el segundo vector : 0 1 0 Son ortogonales Programa de ortogonalidad en Octave.

213

Primero consideremos la versi´n en Octave del programa que llamaremos orthog.m. Las o primeras l´ ıneas de orthog son: % orthog - Programa para probar si un par de vectores es ortogonal. % Supondremos vectores en 3D. clear all; % Borra la memoria Las primeras dos l´ ıneas son comentarios; si tipeamos help orthog desde la l´ ınea de comandos, Octave desplegar´ estas l´ a ıneas. El comando clear all en la tercera l´ ınea borra la memoria. Las pr´ximas l´ o ıneas del programa %* Inicializa los vectores a y b a= input(’Entre el primer vector: ’); b= input(’Entre el segundo vector: ’); Los vectores entran usando el comando input en estas l´ ıneas. Los comentarios que comienzan con %* son aquellos que corresponden al bosquejo del programa que hicimos. En las l´ ıneas siguientes se eval´a el producto punto. u %* Evalua el producto punto como la suma sobre el producto de los elementos adotb=0; for i=1:3 adotb=adotb+a(i)*b(i); end El ciclo for, usando el ´ ındice i, recorre las componentes de los vectores. Una manera h´bil a de hacer lo mismo podr´ ser usar ıa %* Evalua el producto punto como el producto de dos vectores adotb=a*b’ ; En este caso, hemos usado la multiplicaci´n de matrices de Octave para calcular el producto o punto como el producto vectorial del vector fila a y el columna b’ (donde hemos usado el operador Herm´ ıtico conjugado ’). Las ultimas l´ ´ ıneas del programa %* Imprime el producto punto y si los vectores son ortogonales if(adotb==0) disp(’Los vectores son ortogonales’); else disp(’Los vectores no son ortogonales’); printf(’Producto punto = %g \n’, adotb); end

214

CAP´ ITULO 7. PRELIMINARES.

De acuerdo al valor de adotb el programa despliega una de las dos posibles respuestas. A continuaci´n la salida al ejecutar el help del programa o octave> help orthog orthog is the file: /home/jrogan/orthog.m orthog - Programa para probar si un par de vectores es ortogonal. Supondremos vectores en 3D.

Additional help for builtin functions, operators, and variables is available in the on-line version of the manual. Use the command ‘help -i <topic>’ to search the manual index. Help and information about Octave is also available on the WWW at http://www.che.wisc.edu/octave/octave.html and via the help-octave@bevo.che.wisc.edu mailing list. Ahora ejecutamos el programa con diferentes vectores. octave> orthog Entre el primer vector: [1 1 1] Entre el segundo vector: [1 -2 1] Los vectores son ortogonales octave> orthog Entre el primer vector: [1 1 1] Entre el segundo vector: [2 2 2] Los vectores no son ortogonales Producto punto = 6 Interpolaci´n. o Es bien sabido que dados tres pares (x, y), se puede encontrar una cuadr´tica que pasa a por los puntos deseados. Hay varias maneras de encontrar el polinomio y varias maneras de escribirlo. La forma de Lagrange del polinomio es (x − x1 )(x − x3 ) (x − x1 )(x − x2 ) (x − x2 )(x − x3 ) y1 + y2 + y3 , (7.1) p(x) = (x1 − x2 )(x1 − x3 ) (x2 − x1 )(x2 − x3 ) (x3 − x1 )(x3 − x2 ) donde (x1 , y1 ), (x2 , y2 ), (x3 , y3 ), son los tres puntos por los que queremos pasar. Com´nmente u tales polinomios son usados para interpolar entre los puntos dados. A continuaci´n el bosquejo o de un programa simple de interpolaci´n, que llamaremos interp o Inicializa los puntos (x1 , y1 ), (x2 , y2 ) y (x3 , y3 ) para ser ajustados por el polinomio. Establece el intervalo de la interpolaci´n (desde xm´ hasta xm´x ) o ın a Encuentra y ∗ para los valores deseados de x∗ , usando la funci´n intrpf. o Finalmente, podemos graficar la curva dada por (x∗ , y ∗ ), y marcar los puntos originales para comparar.

7.1. PROGRAMAS Y FUNCIONES. Programa de interpolaci´n en Python. o Las primeras l´ ıneas de la versi´n en Python del programa interp son o #!/usr/bin/env python # -*- coding: iso-8859-1 -*# interp - Programa para interpolar datos usando # el polinomio de Lagrange cuadratico para tres puntos dados. # Importa un modulo que permite graficar. from pylab import * # Definicion de la funcion que evalua el polinomio. def intrpf(x,x_i,y_i): t0=y_i[0]*(x-x_i[1])*(x-x_i[2])/((x_i[0]-x_i[1])*(x_i[0]-x_i[2])) t1=y_i[1]*(x-x_i[0])*(x-x_i[2])/((x_i[1]-x_i[0])*(x_i[1]-x_i[2])) t2=y_i[2]*(x-x_i[0])*(x-x_i[1])/((x_i[2]-x_i[0])*(x_i[2]-x_i[1])) return t0+t1+t2 def main(): # Se ingresan los tres puntos y se almacenan en dos listas x_i e y_i x_i=[] y_i=[] print "Ingrese tres puntos (x,y)" x0=input("Coordenada x, primer punto : ") y0=input("Coordenada y, primer punto : ") x1=input("Coordenada x, segundo punto : ") y1=input("Coordenada y, segundo punto : ") x2=input("Coordenada x, tercer punto : ") y2=input("Coordenada y, tercer punto : ") x_i.append(x0) x_i.append(x1) x_i.append(x2) y_i.append(y0) y_i.append(y1) y_i.append(y2) # Se ingresa el intervalo donde se evaluara el polinomio print "Ingrese intervalo para hacer la interpolacion" x_min=input("Coordenada x minimo : ") x_max=input("Coordenada x maximo : ") # Grafica t=arange(x_min,x_max,(x_max-x_min)/100.0) plot(x_i, y_i,’ro’,t, intrpf(t,x_i,y_i)) title("Polinomio de interpolacion de Lagrange") grid(True) show() if __name__==’__main__’: main()

215

216 Usando el programa

CAP´ ITULO 7. PRELIMINARES.

jrogan@huelen:~/programas_metodos_numericos/pyhton$ interp.py Ingrese tres puntos (x,y) Coordenada x, primer punto : 0.5 Coordenada y, primer punto : 0.25 Coordenada x, segundo punto : 1 Coordenada y, segundo punto : 1 Coordenada x, tercer punto : 2 Coordenada y, tercer punto : 4 Ingrese intervalo para hacer la interpolacion Coordenada x minimo : -3 Coordenada x maximo : 3 El uso de las instrucci´n plot en el programa levanta una ventana independiente con el o siguiente gr´fico: a

Figura 7.1: Salida gr´fica del programa interp. a

7.1. PROGRAMAS Y FUNCIONES. Programa de interpolaci´n en C++. o Las primeras l´ ıneas de la versi´n en C++ del programa interp son o // interp - Programa para interpolar datos usando // el polinomio de Lagrange cuadratico para tres puntos dados. #include "NumMeth.h" double intrpf(double xi, double x[], double y[]); int main() {

217

Comentarios m´s una instrucci´n para incluir el archivo de encabezamiento NumMeth.h, lisa o tado a continuaci´n o #include #include #include #include <iostream> <fstream> <cmath> <cstdlib>

using namespace std; La declaraci´n double intrpf(..) afirma que el programa pretende llamar una funci´n o o intrpf, la cual tiene tres argumentos de tipo double y devuelve un double. Las pr´ximas o l´ ıneas del programa // Inicializa los puntos a ser ajustados con una cuadratica double x[3], y[3] ; cout << "Entre los puntos como pares x,y (e.g., [1 2])" << endl ; for(int i=0; i<3; i++) { cout << "x["<<i<<"] = "; cin>> x[i]; cout << "y["<<i<<"] = "; cin >> y[i]; } // Establece el intervalo de interpolacion (desde x_min a x_max) double xmin, xmax; cout <<"Entre el valor minimo de x: "; cin >> xmin ; cout <<"Entre el valor maximo de x: "; cin >> xmax ; El programa pregunta por los puntos para ajustar el polinomio de Lagrange (7.1) y por el intervalo de interpolaci´n. Lo siguiente, los arreglos xi y yi son declarados: o // Encontrar yi para los valores deseados de interpolacion xi // usando la funcion intrpf int nplot= 100; // Numero de puntos para la curva interpolada double * xi = new double[nplot] ; // Reserva memoria para double * yi = new double[nplot] ; // estos arreglos.

218 Estas l´ ıneas tambi´n podr´ reemplazarse por e ıan

CAP´ ITULO 7. PRELIMINARES.

int nplot = 100; // Numero de puntos para la curva interpolada double xi[nplot], yi[nplot] ; En ambos casos hay asignamiento din´mico de memoria, nplot podr´ ser una entrada del a ıa programa. Los valores interpolados son calculados en un for for(int i=0; i<nplot;i++) { xi[i] = xmin+(xmax-xmin)*double(i)/double(nplot-1); yi[i] = intrpf(xi[i], x, y); // Usando intrpf para interpolar } Notemos que xi[1]=xm´ , xi[nplot]=xm´x , con valores equiespaciados entre ellos. Los vaın a lores de yi (y ∗ = p(x∗ )) son evaluados usando la ecuaci´n (7.1) en la funci´n intrpf. La o o salida del programa // Imprime las variables para graficar: x, y, xi, yi ofstream xOut("x.txt"), yOut("y.txt"), xiOut("xi.txt"), yiOut("yi.txt"); for(int i =0; i <3; i++) { xOut << x[i] << endl; yOut << y[i] << endl; } for(int i =1; i <=nplot; i++) { xiOut << xi[i] << endl; yiOut << yi[i] << endl; } xOut.close() ; yOut.close() ; xiOut.close(); yiOut.close() ; Estos cuatro archivos de datos (x.txt, y.txt, etc.) son creados. Desgraciadamente, C++ carece de una biblioteca gr´fica est´ndar, as´ que necesitamos a a ı una aplicaci´n gr´fica adicional para graficar la salida. Tambi´n podemos usar un peque˜o o a e n script en Octave: #!/usr/bin/octave load x.txt; load y.txt; load xi.txt; load yi.txt; %* Grafica la curva dada por (xi,yi) y marca los puntos originales xlabel(’x’); ylabel(’y’); title(’Interpolacion de tres puntos’); gset nokey; plot(x,y, ’*’,xi,yi,’-’); pause Al cual, incluso, podemos llamar desde el mismo programa mediante system( "grafica.m" ) ;

7.1. PROGRAMAS Y FUNCIONES.
Interpolacion de tres puntos 9 8 7 6 5 y 4 3 2 1 0 -3 -2 -1 0 x 1 2 3

219

Figura 7.2: Salida gr´fica del programa interp. a

La ultima l´ ´ ınea del programa delete [] xi, yi ; // Libera la memoria pedida con "new" return 0; } Esta l´ ınea no es absolutamente necesaria, por que al salir el programa liberar´ la memoria a de todas maneras. Sin embargo, se considera como buen estilo de programaci´n, limpiar uno o la memoria que requiri´ durante la ejecuci´n del programa. o o La funci´n intrpf, la cual eval´a el polinomio de Lagrange, comienza por las siguientes o u l´ ıneas double intrpf( double xi, double x[], double y[]) { // Funcion para interpolar entre puntos // usando polinomio de Lagrange (cuadratico) // Entradas // x Vector de las coordenadas x de los puntos dados (3 valores) // y Vector de las coordenadas y de los puntos dados (3 valores) // Salida // yi El polinomio de interpolacion evaluado en xi Especifica los argumentos de llamada y lo que devuelve. Todas las variables dentro de la funci´n son locales. El C++ pasa las variables por valor, por defecto, la funci´n recibe una o o copia que se destruye cuando termina la funci´n, si se desea pasar una variable double a o por referencia debemos anteponerle el signo &, es decir, pasarla como double &a. De esta manera la funci´n puede modificar el valor que ten´ la variable en el programa principal. o ıa El resto de la funci´n o

220

CAP´ ITULO 7. PRELIMINARES.

//* Calcula yi=p(xi) usando Polinomio de Lagrange double yi = (xi-x[2])*(xi-x[3])/((x[1]-x[2])*(x[1]-x[3]))*y[1] + (xi-x[1])*(xi-x[3])/((x[2]-x[1])*(x[2]-x[3]))*y[2] + (xi-x[1])*(xi-x[2])/((x[3]-x[1])*(x[3]-x[2]))*y[3]; return yi ; Estas l´ ıneas eval´an el polinomio. Inicialmente pondremos esta funci´n en el mismo archivo, u o luego la podemos separar en otro archivo y escribir un Makefile que genere el ejecutable. Programa de interpolaci´n en Octave. o Las primeras l´ ıneas del programa % interp - Programa para interpolar datos usando % el polinomio de Lagrange cuadratico para tres puntos dados. clear all; %* Inicializa los puntos a ser ajustados con una cuadratica disp(’Entre los puntos como pares x,y (e.g., [1 2])’); for i=1:3 temp =input(’Ingrese el punto: ’); x(i)=temp(1); y(i)=temp(2) ; end %* Establece el intervalo de interpolacion (desde x_min a x_max) xr = input (’Ingrese el intervalo de valores de x como [x_min x_max]: ’); Aqu´ el programa lee los tres pares (x, y) y el intervalo de valores entre los cuales ser´ interı a polado. Los valores interpolados y ∗ = p(x∗ ) son calculados por la funci´n intrpf desde x∗ = xm´ o ın a x∗ = xm´x . Estos valores de y ∗ (yi) son calculados en el ciclo. a %* Encontrar yi para los valores deseados de interpolacion xi % usando la funcion intrpf nplot= 100; % Numero de puntos para la curva interpolada for i=1:nplot xi(i) = xr(1)+(xr(2)-xr(1))*(i-1)/(nplot-1); yi(i) = intrpf(xi(i), x, y); % Usando intrpf para interpolar end Finalmente, los resultados son graficados usando las funciones gr´ficas de Octave. a %* Grafica la curva dada por (xi,yi) y marca los puntos originales xlabel(’x’); ylabel(’y’); title(’Interpolacion de tres puntos’); gset nokey; plot(x,y, ’*’,xi,yi,’-’);

´ 7.2. ERRORES NUMERICOS.

221

Los puntos de la interpolaci´n (x∗ , y ∗ ) son graficados con l´ o ınea segmentada y los datos originales con c´ ırculos, ver figura (7.2). El trabajo real es hecho por la funci´n intrpf. Un o bosquejo de lo que queremos que haga esta funci´n a continuaci´n. o o Entrada: x = [x1 x2 x3 ], y = [y1 y2 y3 ], y x∗ . Salida: y ∗ . C´lculo de y ∗ = p(x∗ ) usando el polinomio de Lagrange (7.1). a Las funciones en Octave est´n implementadas como en la mayor´ de los lenguajes, excepto a ıa que aqu´ cada funci´n tiene que ir en un archivo separado. El nombre del archivo debe ı o coincidir con el nombre de la funci´n (la funci´n intrpf est´ en el archivo intrpf.m). o o a function yi=intrpf(xi,x,y) % Funcion para interpolar entre puntos % usando polinomio de Lagrange (cuadratico) % Entradas % x Vector de las coordenadas x de los puntos dados (3 valores) % y Vector de las coordenadas y de los puntos dados (3 valores) % Salida % yi El polinomio de interpolacion evaluado en xi La funci´n intrpf tiene tres argumentos de entrada y uno de salida. El resto de la funci´n o o o o es directa, s´lo eval´a el polinomio definido en (7.1). El cuerpo de la funci´n a continuaci´n o u yi = (xi-x(2))*(xi-x(3))/((x(1)-x(2))*(x(1)-x(3)))*y(1) ... + (xi-x(1))*(xi-x(3))/((x(2)-x(1))*(x(2)-x(3)))*y(2) ... + (xi-x(1))*(xi-x(2))/((x(3)-x(1))*(x(3)-x(2)))*y(3); return;

7.2.
7.2.1.

Errores num´ricos. e
Errores de escala.

Un computador almacena n´meros de punto flotante usando s´lo una peque˜a cantidad u o n de memoria. T´ ıpicamente, a una variable de precisi´n simple (un float en C++) se le o asignan 4 bytes (32 bits) para la representaci´n del n´mero, mientras que una variable de o u doble precisi´n (double en C++, por defecto en Python y Octave) usa 8 bytes. Un n´mero de o u punto flotante es representado por su mantisa y su exponente (por ejemplo, para 6.625×10−27 la mantisa decimal es 6.625 y el exponente es −27). El formato IEEE para doble precisi´n o usa 53 bits para almacenar la mantisa (incluyendo un bit para el signo) y lo que resta, 11 bit para el exponente. La manera exacta en que el computador maneja la representaci´n de o los n´meros no es tan importante como saber el intervalo m´ximo de valores y el n´mero de u a u cifras significativas. El intervalo m´ximo es el l´ a ımite sobre la magnitud de los n´meros de punto flotante u impuesta por el n´mero de bit usados para el exponente. Para precisi´n simple un valor u o

222

CAP´ ITULO 7. PRELIMINARES.

t´ ıpico es 2±127 ≈ 10±38 ; para precisi´n doble es t´ o ıpicamente 2±1024 ≈ 10±308 . Exceder el intervalo de la precisi´n simple no es dif´ o ıcil. Consideremos, por ejemplo, la evaluaci´n del o radio de Bohr en unidades SI, a0 = 4πε0 2 ≈ 5.3 × 10−11 [m] . 2 me e (7.2)

Mientras sus valores caen dentro del intervalo de un n´mero de precisi´n simple, el intervalo u o 2 −78 2 es excedido en el c´lculo del numerador (4πε0 ≈ 1.24 × 10 a [kg C m]) y del denominador (me e2 ≈ 2.34 × 10−68 [kg C2 ]). La mejor soluci´n para lidiar con este tipo de dificultades de o intervalo es trabajar en un conjunto de unidades naturales al problema (e.g. para problemas at´micos se trabaja en las distancias en ˚ngstroms y la carga en unidades de la carga del o A electr´n). o Algunas veces los problemas de intervalo no son causados por la elecci´n de las unidao des, sino porque los n´meros en el problema son inherentemente grandes. Consideremos un u importante ejemplo, la funci´n factorial. Usando la definici´n o o n! = n × (n − 1) × (n − 2) × . . . × 3 × 2 × 1 , es f´cil evaluar n! en Python, a nFactorial=1; for i in range(1,n+1): nFactorial *=i o en C++, double nFactorial=1; for(int i=1; i <=n; i++) nFactorial *=i ; donde n es un n´mero dado. u En Octave, usando el operador dos puntos este c´lculo puede ser realizado como a nFactorial = prod(1:n); donde prod(x) es el producto de los elementos del vector x y 1:n=[1,2. . . , n]. Infortunadamente, debido a problemas de intervalo, no podemos calcular n! para n > 170 usando estos m´todos directos de evaluaci´n (7.3). e o Una soluci´n com´n para trabajar con n´meros grandes es usar su logaritmo. Para el o u u factorial log(n!) = log(n) + log(n − 1) + . . . + log(3) + log(2) + log(1) . (7.4) En Octave, esto puede ser evaluado como log_nFactorial = sum( log(1:n) ) ; donde sum(x) es la suma de los elementos del vector x. Sin embargo, este esquema es computacionalmente pesado si n es grande. Una mejor estrategia es combinar el uso de logaritmos con la f´rmula de Stirling2 o √ 1 1 n! = 2nπnn e−n 1 + + + ··· (7.5) 12n 288n2
2

(7.3)

M. Abramowitz and I. Stegun, Handbook of Mathematical Functions ( New York: Dover 1972).

´ 7.2. ERRORES NUMERICOS. o log(n!) = 1 1 1 log(2nπ) + n log(n) − n + log 1 + + + ··· 2 12n 288n2 .

223

(7.6)

Esta aproximaci´n puede ser usada cuando n es grande (n > 30), de otra manera es preferible o la definici´n original. o Finalmente, si el valor de n! necesita ser impreso, podemos expresarlo como n! = (mantisa) × 10(exponente) , (7.7)

donde el exponente es la parte entera de log10 (n!), y la mantisa es 10a donde a es la parte fraccionaria de log10 (n!). Recordemos que la conversi´n entre logaritmo natural y logaritmo o en base 10 es log10 (x) = log10 (e) log(x).

7.2.2.

Errores de redondeo.

Supongamos que deseamos calcular num´ricamente f (x), la derivada de una funci´n e o conocida f (x). En c´lculo se aprendi´ que la f´rmula para la derivada es a o o f (x) = f (x + h) − f (x) , h (7.8)

en el l´ ımite en que h → 0. ¿Qu´ sucede si evaluamos el lado derecho de esta expresi´n, e o poniendo h = 0?. Como el computador no entiende que la expresi´n es v´lida s´lo como un o a o l´ ımite, la divisi´n por cero tiene varias posibles salidas. El computador puede asignar el valor, o Inf, el cual es un n´mero de punto flotante especial reservado para representar el infinito. Ya u que el numerador es tambi´n cero el computador podr´ evaluar el cociente siendo indefinido e ıa (Not-a-Number), NaN, otro valor reservado. O el c´lculo podr´ parar y arrojar un mensaje a ıa de error. a ´ Claramente, poniendo h = 0 para evaluar (7.8) no nos dar´ nada util, pero ¿si le ponemos −300 a h un valor muy peque˜o, digamos h = 10 n , usamos doble precisi´n? La respuesta a´n o u ser´ incorrecta debido a la segunda limitaci´n sobre la representaci´n de n´meros con punto a o o u flotante: el n´mero de d´ u ıgitos en la mantisa. Para precisi´n simple, el n´mero de d´ o u ıgitos significantes es t´ ıpicamente 6 o 7 d´ ıgitos decimales; para doble precisi´n es sobre 16 d´ o ıgitos. As´ en doble precisi´n, la operaci´n 3 + 10−20 retorna una respuesta 3 por el redondeo; ı, o o usando h = 10−300 en la ecuaci´n (7.8) casi con seguridad regresar´ 0 cuando evaluemos el o a numerador. La figura 7.3 ilustra la magnitud del error de redondeo en un c´lculo t´ a ıpico de derivada. Definimos el error absoluto ∆(h) = f (x) − f (x + h) − f (x) h . (7.9)

Notemos que ∆(h) decrece cuando h se hace m´s peque˜o, lo cual es esperado, dado que a n la ecuaci´n (7.8) es exacta cuando h → 0. Por debajo de h = 10−10 , el error comienza a o incrementarse debido a efectos de redondeo. En valores menores de h el error es tan grande

224

CAP´ ITULO 7. PRELIMINARES.

10

0

10

−2

∆(h)

10

−4

10

−6

10

−8

10

−10

10

−20

10

−16

10

−12

10

−8

10

−4

10

0

h
Figura 7.3: Error absoluto ∆(h), ecuaci´n (7.9), versus h para f (x) = x2 y x = 1. o

que la respuesta carece de sentido. Volveremos en el pr´ximo cap´ o ıtulo a la pregunta de c´mo o mejorar el c´lculo de la derivada num´ricamente. a e Para testear la tolerancia del redondeo, definimos εΓ como el m´s peque˜o n´mero que, a n u cuando es sumado a uno, regresa un valor distinto de 1. En Octave, la funci´n integrada o eps devuelve εΓ ≈ 2.22 × 10−16 . En C++, el archivo de encabezamiento <cfloat> define DBL_EPSILON (2.2204460492503131e-16) como εΓ para doble precisi´n. o Debido a los errores de redondeo la mayor´ de los c´lculos cient´ ıa a ıficos usan doble precisi´n. o Las desventajas de la doble precisi´n son que requieren m´s memoria y que algunas veces (no o a siempre) es m´s costosa computacionalmente. Los procesadores modernos est´n construidos a a para trabajar en doble precisi´n, tanto que puede ser m´s lento trabajar en precisi´n simple. o a o Usar doble precisi´n algunas veces s´lo desplaza las dificultades de redondeo. Por ejemplo, el o o c´lculo de la inversa de una matriz trabaja bien en simple precisi´n para matrices peque˜as a o n de 50 × 50 elementos, pero falla por errores de redondeo para matrices m´s grandes. La a doble precisi´n nos permite trabajar con matrices de 100 × 100, pero si necesitamos resolver o sistemas a´n m´s grandes debemos usar un algoritmo diferente. La mejor manera de trabajar u a es usar algoritmos robustos contra el error de redondeo.

Cap´ ıtulo 8 Ecuaciones diferenciales ordinarias: M´todos b´sicos. e a
versi´n 4.0, 6 de Noviembre del 20071 . o

En este cap´ ıtulo resolveremos uno de los primeros problemas abordados por un estudiante de f´ ısica: el vuelo de un proyectil y, en particular, el de una pelota de baseball. Sin la resistencia del aire el problema es f´cil de resolver. Sin embargo, incluyendo un arrastre realista, nosotros a necesitamos calcular la soluci´n num´ricamente. Para analizar este problema definiremos o e primero la diferenciaci´n num´rica. De hecho antes de aprender f´ o e ısica uno aprende c´lculo a as´ que no debemos sorprendernos si este es nuestro punto de partida. En la segunda mitad del ı cap´ ıtulo nos ocuparemos de otro viejo conocido, el p´ndulo simple, pero sin la aproximaci´n a e o a ´ngulos peque˜os. Los problemas oscilatorios, tales como el p´ndulo, nos revelar´n una falla n e a fatal en algunos de los m´todos num´ricos de resolver ecuaciones diferenciales ordinarias. e e

8.1.
8.1.1.

Movimiento de un proyectil.
Ecuaciones b´sicas. a

Consideremos el simple movimiento de un proyectil, digamos un pelota de baseball. Para describir el movimiento, nosotros debemos calcular el vector posici´n r(t) y el vector velocidad o v(t) del proyectil. Las ecuaciones b´sicas de movimiento son a dv 1 = Fa (v) − g y , ˆ dt m dr =v , dt (8.1)

donde m es la masa del proyectil. La fuerza debido a la resistencia del aire es Fa (v), la aceleraci´n gravitacional es g, e y es un vector unitario en la direcci´n y. El movimiento es o ˆ o bidimensional, tal que podemos ignorar la componente z y trabajar en el plano xy. La resistencia del aire se incrementa con la velocidad del objeto, y la forma precisa para Fa (v) depende del flujo alrededor del proyectil. Com´nmente, esta fuerza es aproximada por u 1 Fa (v) = − Cd ρA | v | v , 2
1

(8.2)

Este cap´ ıtulo est´ basado en el segundo cap´ a ıtulo del libro: Numerical Methods for Physics, second edition de Alejandro L. Garcia, editorial Prentice Hall

225

226

´ ´ CAP´ ITULO 8. EDO: METODOS BASICOS.

donde Cd es el coeficiente de arrastre, ρ es la densidad del aire, y A es el ´rea de la secci´n a o transversal del proyectil. El coeficiente de arrastre es un par´metro adimensional que depende a de la geometr´ del proyectil, entre m´s aerodin´mico el objeto, el coeficiente es menor. ıa a a Para una esfera suave de radio R movi´ndose lentamente a trav´s del fluido, el coeficiente e e de arrastre es dado por la Ley de Stokes, Cd = 12ν 24 = , Rv Re (8.3)

donde ν es la viscosidad del fluido (ν ≈ 1.5 × 10−5 [m2 /s] para el aire) y Re = 2Rv/ν es el adimensional n´mero de Reynolds. Para un objeto del tama˜o de una pelota de baseball u n movi´ndose a trav´s del aire, la ley de Stokes es v´lida s´lo si la velocidad es menor que e e a o 0.2˜ [mm/s] (Re≈ 1). A velocidades altas (sobre 20 [cm/s], Re> 103 ), la estela detr´s de la esfera desarrolla a v´rtices y el coeficiente de arrastre es aproximadamente constante (Cd ≈ 0.5) para un amplio o intervalo de velocidades. Cuando el n´mero de Reynolds excede un valor cr´ u ıtico, el flujo en la estela llega a ser turbulento y el coeficiente de arrastre cae dram´ticamente. Esta reducci´n a o ocurre porque la turbulencia rompe la regi´n de bajas presiones en la estela detr´s de la o a esfera2 . Para una esfera suave este n´mero cr´ u ıtico de Reynolds es aproximadamente 3 × 105 . Para una pelota de baseball, el coeficiente de arrastre es usualmente m´s peque˜o que el de a n una esfera suave, porque las costuras rompen el flujo laminar precipitando el inicio de la turbulencia. Nosotros podemos tomar Cd = 0.35 como un valor promedio para el intervalo de velocidades t´ ıpicas de una pelota de baseball. Notemos que la fuerza de arrastre, ecuaci´n (8.2), var´ como el cuadrado de la magnitud o ıa 2 de la velocidad (Fa ∝ v ) y, por supuesto, act´a en la direcci´n opuesta a la velocidad. La u o masa y el di´metro de una pelota de baseball son 0.145 [kg] y 7.4 [cm]. Para una pelota de a baseball, el arrastre y la fuerza gravitacional son iguales en magnitud cuando v ≈ 40 [m/s]. Nosotros sabemos c´mo resolver las ecuaciones de movimiento si la resistencia del aire es o despreciable. La trayectoria es 1 ˆ (8.4) r(t) = r1 + v1 t − gt2 y , 2 donde r1 ≡ r(0) y v1 ≡ v(0) son la posici´n y la velocidad inicial. Si el proyectil parte del o origen y la velocidad inicial forma un ´ngulo θ con la horizontal, entonces a xm´x = a
2 2v1 sen θ cos θ , g

ym´x = a

2 v1 sen2 θ , 2g

(8.5)

son el alcance horizontal y la altura m´xima. El tiempo de vuelo es a tf l = 2v1 sen θ . g (8.6)

Nuevamente estas expresiones son v´lidas s´lo cuando no hay resistencia con el aire. a o Es f´cil demostrar que el m´ximo alcance horizontal se obtiene cuando la velocidad forma a a un ´ngulo de 45◦ con la horizontal. Deseamos mantener esta informaci´n en mente cuando a o construyamos nuestra simulaci´n. Si se sabe la soluci´n exacta para un caso especial, se debe o o comparar constantemente que el programa trabaje bien para este caso.
2

D.J. Tritton, Physical Fluid Dynamics, 2d ed. (Oxford: Clarendon Press, 1988).

8.1. MOVIMIENTO DE UN PROYECTIL.

227

8.1.2.

Derivada avanzada.

e e Para resolver las ecuaciones de movimiento (8.1) necesitamos un m´todo num´rico para evaluar la primera derivada. La definici´n formal de la derivada es o f (t + τ ) − f (t) , (8.7) τ →0 τ donde τ es el incremento temporal o paso en el tiempo. Como ya vimos en el cap´ ıtulo pasado esta ecuaci´n debe ser tratada con cuidado. La figura 7.3 ilustra que el uso de un valor o extremadamente peque˜o para τ causa un gran error en el c´lculo de (f (t + τ ) − f (t))/τ . n a Espec´ ıficamente, los errores de redondeo ocurren en el c´lculo de t + τ , en la evaluaci´n de la a o funci´n f y en la sustracci´n del numerador. Dado que τ no puede ser elegido arbitrariamente o o peque˜o, nosotros necesitamos estimar la diferencia entre f (t) y (f (t + τ ) − f (t))/τ para un n τ finito. Para encontrar esta diferencia usaremos una expansi´n de Taylor. Como f´ o ısicos usualmente vemos las series de Taylor expresadas como f (t) ≡ l´ ım τ2 f (t) + . . . (8.8) 2 donde el s´ ımbolo (. . . ) significa t´rminos de m´s alto orden que son usualmente despreciados. e a Una alternativa, forma equivalente de la serie de Taylor usada en an´lisis num´rico es a e f (t + τ ) = f (t) + τ f (t) + τ2 f (ζ) . (8.9) 2 donde ζ es un valor entre t y t + τ . No hemos botado ning´n t´rmino, esta expansi´n tiene u e o un n´mero finito de t´rminos. El teorema de Taylor garantiza que existe alg´n valor ζ para u e u a el cual (8.9) es cierto, pero no sabemos cu´l valor es este. La ecuaci´n previa puede ser rescrita o f (t + τ ) = f (t) + τ f (t) + f (t + τ ) − f (t) 1 − τ f (ζ) , (8.10) τ 2 donde t ≤ ζ ≤ t + τ . Esta ecuaci´n es conocida como la f´rmula de la derivada derecha o o o derivada adelantada. El ultimo t´rmino de la mano derecha es el error de truncamiento; este ´ e error es introducido por cortar la serie de Taylor. o En otras palabras, si mantenemos el ultimo t´rmino en (8.10), nuestra expresi´n para ´ e f (t) es exacta. Pero no podemos evaluar este t´rmino porque no conocemos ζ, todo lo que e conocemos es que ζ yace en alg´n lugar entre t y t + τ . As´ despreciamos el t´rmino f (ζ) u ı e (truncamos) y decimos que el error que cometemos por despreciar este t´rmino es el error de e truncamiento. No hay que confundir ´ste con el error de redondeo discutido anteriormente. El e error de redondeo depende del hardware, el error de truncamiento depende de la aproximaci´n o usada en el algoritmo. Algunas veces veremos la ecuaci´n (8.10) escrita como o f (t) = f (t + τ ) − f (t) + O(τ ) (8.11) τ donde el error de truncamiento es ahora especificado por su orden en τ , en este caso el error de truncamiento es lineal en τ . En la figura 7.3 la fuente de error predominante en estimar f (x) como [f (x + h) − f (x)]/h es el error de redondeo cuando h < 10−10 y es el error de truncamiento cuando h > 10−10 . f (t) =

228

´ ´ CAP´ ITULO 8. EDO: METODOS BASICOS.

8.1.3.

M´todo de Euler. e

Las ecuaciones de movimiento que nosotros deseamos resolver num´ricamente pueden ser e escritas como: dr dv = a(r, v) , =v , (8.12) dt dt donde a es la aceleraci´n. Notemos que esta es la forma m´s general de las ecuaciones. En o a el movimiento de proyectiles la aceleraci´n es s´lo funci´n de v (debido al arrastre), en otros o o o problemas (e.g., ´rbitas de cometas) la aceleraci´n depender´ de la posici´n. o o a o Usando la derivada adelantada (8.11), nuestras ecuaciones de movimiento son v(t + τ ) − v(t) + O(τ ) = a(r(t), v(t)) , τ r(t + τ ) − r(t) + O(τ ) = v(t) , τ o bien v(t + τ ) = v(t) + τ a(r(t), v(t)) + O(τ 2 ) , r(t + τ ) = r(t) + τ v(t) + O(τ 2 ) . (8.15) (8.16) (8.13) (8.14)

notemos que τ O(τ ) = O(τ 2 ). Este esquema num´rico es llamado el m´todo de Euler. Antes de e e discutir los m´ritos relativos de este acercamiento, veamos c´mo ser´ usado en la pr´ctica. e o ıa a Primero, introducimos la notaci´n o fn = f (tn ) , tn = (n − 1)τ , n = 1, 2, . . . (8.17)

tal que f1 = f (t = 0). Nuestras ecuaciones para el m´todo de Euler (despreciando el t´rmino e e del error) ahora toma la forma vn+1 = vn + τ an , rn+1 = rn + τ vn , donde an = a(rn , vn ). El c´lculo de la trayectoria podr´ proceder as´ a ıa ı: 1. Especifique las condiciones iniciales, r1 y v1 . 2. Elija un paso de tiempo τ . 3. Calcule la aceleraci´n dados los actuales r y v. o 4. Use las ecuaciones (8.18) y (8.19) para calcular los nuevos r y v. 5. Vaya al paso 3 hasta que suficientes puntos de trayectoria hayan sido calculados. El m´todo calcula un conjunto de valores para rn y vn que nos da la trayectoria, al menos e en un conjunto discreto de valores. La figura 8.1 ilustra el c´lculo de la trayectoria para un a unico paso de tiempo. ´ (8.18) (8.19)

8.1. MOVIMIENTO DE UN PROYECTIL.

229

an

vn

x

τ vn

vn vn+1 τ an

rn

rn+1 y

Figura 8.1: Trayectoria de una part´ ıcula despu´s de un unico paso de tiempo con el m´todo e ´ e de Euler. S´lo para efectos ilustrativos τ es grande. o

8.1.4.

M´todos de Euler-Cromer y de Punto Medio. e

Una simple (y por ahora injustificada) modificaci´n del m´todo de Euler es usar las o e siguientes ecuaciones: vn+1 = vn + τ an , rn+1 = rn + τ vn+1 . (8.20) (8.21)

Notemos el cambio sutil: La velocidad actualizada es usada en la segunda ecuaci´n. Esta o 3 f´rmula es llamada m´todo de Euler-Cromer . El error de truncamiento es a´n del orden o e u 2 de O(τ ), no parece que hemos ganado mucho. Veremos que esta forma es marcadamente superior al m´todo de Euler en algunos casos. e En el m´todo del punto medio usamos e vn+1 = vn + τ an , vn+1 + vn rn+1 = rn + τ . 2 (8.22) (8.23)

Notemos que hemos promediado las dos velocidades. Usando la ecuaci´n para la velocidad o en la ecuaci´n de la posici´n, vemos que o o 1 rn+1 = rn + τ vn + an τ 2 , 2 (8.24)

lo cual realmente hace esto lucir atractivo. El error de truncamiento es a´n del orden de u τ 2 en la ecuaci´n velocidad, pero para la posici´n el error de truncamiento es ahora τ 3 . o o Realmente, para el movimiento de proyectiles este m´todo trabaja mejor que los otros dos. e Infortunadamente, en otros sistemas f´ ısicos este m´todo da pobres resultados. e

8.1.5.

Errores locales, errores globales y elecci´n del paso de tiemo po.

Para juzgar la precisi´n de estos m´todos necesitamos distinguir entre errores de truno e camiento locales y globales. Hasta ahora, el error de truncamiento que hemos discutido ha
3

A. Cromer, “Stable solutions using the Euler approximation”, Am. J. Phys., 49 455-9 (1981).

230

´ ´ CAP´ ITULO 8. EDO: METODOS BASICOS.

sido el error local, el error cometido en un unico paso de tiempo. En un problema t´ ´ ıpico nosotros deseamos evaluar la trayectoria desde t = 0 a t = T . El n´mero de pasos de tiempo u es NT = T /τ ; notemos que si reducimos τ , debemos tomar m´s pasos. Si el error local es a O(τ n ), entonces estimamos el error global como error global ∝ NT × (error local) T = NT O(τ n ) = O(τ n ) = T O(τ n−1 ) . τ (8.25)

Por ejemplo, el m´todo de Euler tiene un error local de truncamiento de O(τ 2 ), pero un error e global de truncamiento de O(τ ). Por supuesto, este an´lisis nos da s´lo una estimaci´n ya que a o o no sabemos si los errores locales se acumular´n o se cancelar´n (i.e. interferencia constructiva a a o destructiva). El verdadero error global para un esquema num´rico es altamente dependiente e del problema que se est´ estudiando. a Una pregunta que siempre aparece es ¿c´mo elegir el τ ? Tratemos de responderla. Primero, o supongamos que los errores de redondeo son despreciables tal que s´lo debemos preocuparnos o por los errores de truncamiento. Desde (8.10) y (8.16), el error local de truncamiento en el c´lculo de la posici´n usando el m´todo de Euler es aproximadamente τ 2 r = τ 2 a. Usando a o e s´lo estimaciones del orden de magnitud, tomamos a ≈ 10 [m/s2 ], el error en un solo paso o en la posici´n es de 10−1 [m], cuando τ = 10−1 [s]. Si el tiempo de vuelo T ≈ 100 [s], o entonces el error global es del orden de metros. Si un error de esta magnitud es inaceptable entonces debemos disminuir el paso en el tiempo. Finalmente usando un paso de tiempo 10−1 [s] no introducir´ ıamos ning´n error significativo de redondeo dada la magnitud de los u otros par´metros del problema. a En el mundo real, a menudo no podemos hacer un an´lisis tan elegante por una variedad a de razones (ecuaciones complicadas, problemas con el redondeo, flojera, etc.). Sin embargo, a menudo podemos usar la intuici´n f´ o ısica. Resp´ndase usted mismo “¿en qu´ escala de o e tiempo el movimiento es casi lineal?”. Por ejemplo, para la trayectoria completa de una pelota de baseball que es aproximadamente parab´lica, el tiempo en el aire son unos pocos o segundos, entonces el movimiento es aproximadamente lineal sobre una escala de tiempo de unos pocos cent´simos de segundo. Para revisar nuestra intuici´n, nosotros podemos comparar e o −1 −2 los resultados obtenidos usando τ = 10 [s] y τ = 10 [s] y, si ellos son suficientemente cercanos, suponemos que todo est´ bien. A veces automatizamos la prueba de varios valores a de τ ; el programa es entonces llamado adaptativo (construiremos un programa de este tipo m´s adelante). Como con cualquier m´todo num´rico, la aplicaci´n ciega de esta t´cnica es a e e o e poco recomendada, aunque con s´lo un poco de cuidado ´sta puede ser usada exitosamente. o e

8.1.6.

Programa de la pelota de baseball.

e La tabla 8.1 bosqueja un simple programa, llamado balle, que usa el m´todo de Euler para calcular la trayectoria de una pelota de baseball. Antes de correr el programa, establezcamos algunos valores razonables para tomar como entradas. Una velocidad inicial de | v1 | =15 [m/s] nos da una pelota que le han pegado d´bilmente. Partiendo del origen y e despreciando la resistencia del aire, el tiempo de vuelo es de 2.2 [s], y el alcance horizontal es sobre los 23 [m] cuando el ´ngulo inicial θ = 45◦ . A continuaci´n, mostramos la salida a a o pantalla del programa balle en C++ cuando es corrido bajo estas condiciones:

8.1. MOVIMIENTO DE UN PROYECTIL.

231

Fijar la posici´n inicial r1 y la velocidad inicial v1 de la pelota de baseball. o Fijar los par´metros f´ a ısicos ( m, Cd , etc.). Iterar hasta que la bola golp´e en el piso o el m´ximo n´mero de pasos sea completado. e a u • Grabar posici´n (calculada y te´rica) para graficar. o o • Calcular la aceleraci´n de la pelota de baseball. o • Calcular la nueva posici´n y velocidad, rn+1 y vn+1 , Usando el m´todo de Euler, o e (8.18) y (8.19). • Si la pelota alcanza el suelo (y < 0) para la iteraci´n. o Imprimir el alcance m´ximo y el tiempo de vuelo. a Graficar la trayectoria de la pelota de baseball. Cuadro 8.1: Bosquejo del programa balle, el cual calcula la trayectoria de una pelota de baseball usando el m´todo de Euler. e
Movimiento de Proyectil
Método de Euler Teoría (sin aire)

6

Altura [m]

4

2

0

0

5

10

15

20

25

Alcance [m]

Figura 8.2: Salida del programa balle para una altura inicial de 0 [m], una velocidad inicial de 15 [m/s], y un paso de tiempo τ =0.1 [s]. No hay resistencia del aire. La l´ ınea continua es la te´rica y los puntos son los calculados, la diferencia se debe a errores de truncamiento. o

jrogan@huelen:~/programas$ balle Ingrese la altura inicial [m] : 0 Ingrese la velocidad inicial [m/s]: 15 Ingrese angulo inicial (grados): 45

232

´ ´ CAP´ ITULO 8. EDO: METODOS BASICOS.

Ingrese el paso en el tiempo, tau en [s]: 0.1 Tiempo de vuelo: 2.2 Alcance: 24.3952 La salida en Octave debiera ser muy similar. La trayectoria calculada por el programa es mostrada en la figura 8.2. Usando un paso de τ = 0.1 [s], el error en el alcance horizontal es sobre un metro, como esper´bamos del a error de truncamiento. A velocidades bajas los resultados no son muy diferentes si incluimos la resistencia con el aire, ya que |Fa (v1 )|/m ≈ g/7. Ahora tratemos de batear un cuadrangular. Consideremos una velocidad inicial grande | v1 | = 50 [m/s]. Debido a la resistencia, encontramos que el alcance es reducido a alrededor de 125 [m], menos de la mitad de su m´ximo te´rico. La trayectoria es mostrada figura 8.3, a o notemos c´mo se aparta de la forma parab´lica. o o En nuestras ecuaciones para el vuelo de una pelota de baseball no hemos incluido todos los factores en el problema. El coeficiente de arrastre no es constante sino m´s bien una a complicada funci´n de la velocidad. Adem´s, la rotaci´n de la pelota ayuda a levantar la o a o pelota (efecto Magnus).
Movimiento de Proyectil
Método de Euler Teoría (sin aire)
60

Altura [m]

40

20

0 0 50 100 150 200 250

Alcance [m]

Figura 8.3: Salida del programa balle para una altura inicial de 1 [m], una velocidad inicial de 50 [m/s], y un paso de tiempo τ =0.1 [s]. Con resistencia del aire.

8.2.
8.2.1.

P´ndulo simple. e
Ecuaciones b´sicas. a

El movimiento de los p´ndulos ha fascinado a f´ e ısicos desde que Galileo fue hipnotizado por la l´mpara en la Catedral de Pisa. El problema es tratado en los textos de mec´nica a a b´sica pero antes de apresurarnos a calcular con el computador, revisemos algunos resultados a

´ 8.2. PENDULO SIMPLE.

233

b´sicos. Para un p´ndulo simple es m´s conveniente describir la posici´n en t´rminos del a e a o e desplazamiento angular, θ(t). La ecuaci´n de movimiento es o d2 θ g = − sen θ , 2 dt L (8.26)

donde L es la longitud del brazo y g es la aceleraci´n de gravedad. En la aproximaci´n para o o a ´ngulo peque˜o, sen θ ≈ θ, la ecuaci´n (8.26) se simplifica a n o d2 θ g =− θ. 2 dt L Esta ecuaci´n diferencial ordinaria es f´cilmente resuelta para obtener o a θ(t) = C1 cos 2πt + C2 Ts , (8.28) (8.27)

donde las constantes C1 y C2 est´n determinadas por los valores iniciales de θ y ω = dθ/dt. a El per´ ıodo para ´ngulos peque˜os, Ts es a n Ts = 2π L . g (8.29)

Esta aproximaci´n es razonablemente buena para oscilaciones con amplitudes menores o o ◦ iguales a 20 . Sin la aproximaci´n para ´ngulos peque˜os, la ecuaci´n de movimiento es m´s dif´ de o a n o a ıcil resolver. Sin embargo, sabemos de la experiencia que el movimiento es todav´ peri´dico. En ıa o efecto, es posible obtener una expresi´n para el per´ o ıodo sin resolver expl´ ıcitamente θ(t). La energ´ total es ıa 1 (8.30) E = mL2 ω 2 − mgL cos θ , 2 donde m es la masa de la lenteja. La energ´ total es conservada e igual a E = −mgL cos θm , ıa donde θm es el ´ngulo m´ximo. De lo anterior, tenemos a a 1 mL2 ω 2 − mgL cos θ = mgL cos θm , 2 o ω2 = Ya que ω = dθ/dt, dt = dθ 2g (cos θ − cos θm ) L . (8.33) 2g (cos θ − cos θm ) . L (8.31)

(8.32)

En un per´ ıodo el p´ndulo se balancea de θ = θm a θ = −θm y regresa a θ = θm . As´ en medio e ı, per´ ıodo el p´ndulo se balancea desde θ = θm a θ = −θm . Por ultimo, por el mismo argumento, e ´

234

´ ´ CAP´ ITULO 8. EDO: METODOS BASICOS.

en un cuarto de per´ ıodo el p´ndulo se balancea desde θ = θm a θ = 0, as´ integrando ambos e ı lados de la ecuaci´n (8.33) o T = 4 L 2g
θm 0

dθ (cos θ − cos θm )

.

(8.34)

Esta integral podr´ ser reescrita en t´rminos de funciones especiales usando la identidad ıa e 2 cos 2θ = 1 − 2 sen θ, tal que T =2 L g
θm 0

dθ (sen2 θm /2 − sen2 θ/2)

.

(8.35)

Introduciendo K(x), la integral el´ ıptica completa de primera especie,4
π/2

K(x) ≡
0

dz , 1 − x2 sen2 z

(8.36)

podr´ ıamos escribir el per´ ıodo como T =4 L K(sen θm /2) , g (8.37)

usando el cambio de variable sen z = sen(θ/2)/ sen(θm /2). Para valores peque˜os de θm , n podr´ ıamos expandir K(x) para obtener T = 2π L g 1+ 1 2 θ + ... 16 m . (8.38)

Note que el primer t´rmino es la aproximaci´n para ´ngulo peque˜o (8.29). e o a n

8.2.2.

F´rmulas para la derivada centrada. o

Antes de programar el problema del p´ndulo miremos un par de otros esquemas para e calcular el movimiento de un objeto. El m´todo de Euler est´ basado en la formulaci´n de la e a o derivada derecha para df /dt dado por (8.7). Una definici´n equivalente para la derivada es o f (t) = l´ ım
τ →0

f (t + τ ) − f (t − τ ) . 2τ

(8.39)

Esta f´rmula se dice centrada en t. Mientras esta f´rmula parece muy similar a la ecuaci´n o o o (8.7), hay una gran diferencia cuando τ es finito. Nuevamente, usando la expansi´n de Taylor, o 1 1 f (t + τ ) = f (t) + τ f (t) + τ 2 f (t) + τ 3 f (3) (ζ+ ) , 2 6 1 2 1 f (t − τ ) = f (t) − τ f (t) + τ f (t) − τ 3 f (3) (ζ− ) , 2 6
4

(8.40) (8.41)

I.S. Gradshteyn and I.M. Ryzhik, Table of Integral, Series and Products (New York: Academic Press, 1965)

´ 8.2. PENDULO SIMPLE.

235

donde f (3) es la tercera derivada de f (t) y ζ± es un valor ente t y t ± τ . Restando las dos ecuaciones anteriores y reordenando tenemos, f (t) = f (t + τ ) − f (t − τ ) 1 2 (3) − τ f (ζ) , 2τ 6 (8.42)

donde f (3) (ζ) = (f (3) (ζ+ ) + f (3) (ζ− ))/2 y t − τ ≤ ζ ≤ t + τ . Esta es la aproximaci´n en la o primera derivada centrada. El punto clave es que el error de truncamiento es ahora cuadr´tico a en τ , lo cual es un gran progreso sobre la aproximaci´n de las derivadas adelantadas que tiene o un error de truncamiento O(τ ). Usando las expansiones de Taylor para f (t + τ ) y f (t − τ ) podemos construir una f´rmula o centrada para la segunda derivada. La que tiene la forma f (t) = f (t + τ ) + f (t − τ ) − 2f (t) 1 − τ 2 f (4) (ζ) , 2 τ 12 (8.43)

donde t − τ ≤ ζ ≤ t + τ . De nuevo, el error de truncamiento es cuadr´tico en τ . La mejor a manera de entender esta f´rmula es pensar que la segunda derivada est´ compuesta de una o a derivada derecha y de una derivada izquierda, cada una con incrementos de τ /2. Usted podr´ pensar que el pr´ximo paso ser´ preparar f´rmulas m´s complicadas que ıa o ıa o a tengan errores de truncamiento a´n m´s peque˜os, quiz´s usando ambas f (t ± τ ) y f (t ± 2τ ). u a n a Aunque tales f´rmulas existen y son ocasionalmente usadas, las ecuaciones (8.10), (8.42) y o (8.43) sirven como el “caballo de trabajo” para calcular las derivadas primera y segunda.

8.2.3.

M´todos del “salto de la rana” y de Verlet. e

Para el p´ndulo, las posiciones y velocidades generalizadas son θ y ω, pero para mantener e la misma notaci´n anterior trabajaremos con r y v. Comenzaremos de las ecuaciones de o movimiento escritas como dv = a(r(t)) , dt dr = v(t) . dt (8.44) (8.45)

Note que expl´ ıcitamente escribimos la aceleraci´n dependiente solamente de la posici´n. Diso o cretizando la derivada temporal usando la aproximaci´n de derivada centrada da, o v(t + τ ) − v(t − τ ) + O(τ 2 ) = a(r(t)) , 2τ (8.46)

para la ecuaci´n de la velocidad. Note que aunque los valores de velocidad son evaluados en o t + τ y t − τ , la aceleraci´n es evaluada en el tiempo t. o Por razones que pronto ser´n claras, la discretizaci´n de la ecuaci´n de posici´n estar´ cena o o o a trada entre t + 2τ y t, r(t + 2τ ) − r(t) + O(τ 2 ) = v(t + τ ) . (8.47) 2τ

236

´ ´ CAP´ ITULO 8. EDO: METODOS BASICOS.

De nuevo usamos la notaci´n fn ≡ f (t = (n − 1)τ ), en la cual las ecuaciones (8.47) y (8.46) o son escritas como, vn+1 − vn−1 + O(τ 2 ) = a(rn ) , 2τ rn+2 − rn + O(τ 2 ) = vn+1 . 2τ Reordenando los t´rminos para obtener los valores futuros a la izquierda, e vn+1 = vn−1 + 2τ a(rn ) + O(τ 3 ) , rn+2 = rn + 2τ vn+1 + O(τ 3 ) . (8.50) (8.51) (8.48) (8.49)

Este es el m´todo del “salto de la rana” (leap frog). Naturalmente, cuando el m´todo es usado e e 3 en un programa, el t´rmino O(τ ) no va y por lo tanto constituye el error de truncamiento e para el m´todo. e El nombre “salto de la rana” es usado ya que la soluci´n avanza en pasos de 2τ , con la o posici´n evaluada en valores impares (r1 , r3 , r5 , . . . ), mientras que la velocidad est´ calculada o a en los valores pares (v2 , v4 , v6 , . . . ). Este entrelazamiento es necesario ya que la aceleraci´n, o la cual es una funci´n de la posici´n, necesita ser evaluada en un tiempo que est´ centrado o o a entre la velocidad nueva y la antigua. Algunas veces el esquema del “salto de la rana” es formulado como vn+1/2 = vn−1/2 + τ a(rn ) , rn+1 = rn + τ vn+1/2 , (8.52) (8.53)

con vn±1/2 ≡ v(t = (n − 1 ± 1/2)τ ). En esta forma, el esquema es funcionalmente equivalente al m´todo de Euler-Cromer. e Para el ultimo esquema num´rico de este cap´ ´ e ıtulo tomaremos una aproximaci´n diferente o y empezaremos con, dr = v(t) , dt d2 r = a(r) . dt2 (8.54) (8.55)

Usando las f´rmulas diferenciales centradas para la primera y segunda derivada, tenemos o rn+1 − rn−1 + O(τ 2 ) = vn , 2τ rn+1 + rn−1 − 2rn + O(τ 2 ) = an , τ2 donde an ≡ a(rn ). Reordenando t´rminos, e vn = rn+1 − rn−1 + O(τ 2 ) , 2τ (8.58) (8.59) (8.56) (8.57)

rn+1 = 2rn − rn−1 + τ 2 an + O(τ 4 ) .

´ 8.2. PENDULO SIMPLE.

237

Estas ecuaciones, conocidas como el m´todo de Verlet 5 , podr´ parecer extra˜as a prie ıan n mera vista, pero ellas son f´ciles de usar. Suponga que conocemos r0 y r1 ; usando la ecuaci´n a o (8.59), obtenemos r2 . Conociendo r1 y r2 podr´ ıamos ahora calcular r3 , luego usando la ecuaı ci´n (8.58) obtenemos v2 , y as´ sucesivamente. o Los m´todos del “salto de la rana” y de Verlet tienen la desventaja que no son “autoinie ciados”. Usualmente tenemos las condiciones iniciales r1 = r(t = 0) y v1 = v(t = 0), pero no v0 = v(t = −τ ) [necesitado por el “salto de la rana” en la ecuaci´n (8.50)] o r0 = r(t = −τ ) o [necesitado por Verlet en la ecuaci´n (8.59)]. Este es el precio que hay que pagar para los o esquemas centrados en el tiempo. Para lograr que estos m´todos partan, tenemos una variedad de opciones. El m´todo de e e Euler-Cromer, usando la ecuaci´n (8.53), toma v1/2 = v1 , lo cual es simple pero no muy o preciso. Una alternativa es usar otro esquema para lograr que las cosas partan, por ejemplo, en el “salto de la rana” uno podr´ tomar un paso tipo Euler para atr´s, v0 = v1 − τ a1 . ıa a Algunas precauciones deber´ ser tomadas en este primer paso para preservar la precisi´n ıan o del m´todo; usando e τ2 r0 = r1 − τ v1 + a(r1 ) , (8.60) 2 es una buena manera de comenzar el m´todo de Verlet. e Adem´s de su simplicidad, el m´todo del “salto de la rana” a menudo tiene propiedades a e favorables (e.g. conservaci´n de la energ´ cuando resuelve ciertos problemas. El m´todo de o ıa) e Verlet tiene muchas ventajas. Primero, la ecuaci´n de posici´n tiene un error de truncamiento o o menor que otros m´todos. Segundo, si la fuerza es solamente una funci´n de la posici´n y si e o o nos preocupamos s´lo de la trayectoria de la part´ o ıcula y no de su velocidad (como en muchos problemas de mec´nica celeste), podemos saltarnos completamente el c´lculo de velocidad. a a El m´todo es popular para el c´lculo de las trayectorias en sistemas con muchas part´ e a ıculas, por ejemplo, el estudio de fluidos a nivel microsc´pico. o

8.2.4.

Programa de p´ndulo simple. e

Las ecuaciones de movimiento para un p´ndulo simple son e dω = α(θ) dt dθ =ω , dt (8.61)

donde la aceleraci´n angular α(θ) = −g sen θ/L. El m´todo de Euler para resolver estas o e ecuaciones diferenciales ordinarias es iterar las ecuaciones: θn+1 = θn + τ ωn , ωn+1 = ωn + τ αn . (8.62) (8.63)

Si estamos interesados solamente en el ´ngulo y no la velocidad, el m´todo de Verlet s´lo usa a e o la ecuaci´n o θn+1 = 2θn − θn−1 + τ 2 αn . (8.64)
L.Verlet, “Computer experiments on classical fluid I. Thermodynamical properties of Lennard-Jones molecules”, Phys. Rev. 159, 98-103 (1967).
5

238

´ ´ CAP´ ITULO 8. EDO: METODOS BASICOS.

Seleccionar el m´todo a usar: Euler o Verlet. e Fijar la posici´n inicial θ1 y la velocidad ω1 = 0 del p´ndulo. o e Fijar los par´metros f´ a ısicos y otras variables. Tomar un paso para atr´s para partir Verlet; ver ecuaci´n (8.60). a o Iterar sobre el n´mero deseado de pasos con el paso de tiempo y m´todo num´rico dado. u e e • Grabar ´ngulo y tiempo para graficar. a • Calcular la nueva posici´n y velocidad usando el m´todo de Euler o de Verlet. o e • Comprobar si el p´ndulo a pasado a trav´s de θ = 0; si es as´ usar el tiempo e e ı transcurrido para estimar el per´ ıodo. Estima el per´ ıodo de oscilaci´n, incluyendo barra de error. o Graficar las oscilaciones como θ versus t. Cuadro 8.2: Bosquejo del programa p´ndulo, el cual calcula el tiempo de evoluci´n de un e o p´ndulo simple usando el m´todo de Euler o Verlet. e e

En vez de usar las unidades SI, usaremos las unidades adimensionales naturales del problema. Hay solamente dos par´metros en el problema, g y L y ellos siempre aparecen en la a raz´n g/L. Fijando esta raz´n a la unidad, el per´ o o ıodo para peque˜as amplitudes Ts = 2π. n En otras palabras, necesitamos solamente una unidad en el problema: una escala de tiempo. Ajustamos nuestra unidad de tiempo tal que el per´ ıodo de peque˜as amplitudes sea 2π. n La tabla 8.2 presenta un bosquejo del programa pendulo, el cual calcula el movimiento de un p´ndulo simple usando o el m´todo de Euler o el de Verlet. El programa estima el e e per´ ıodo por registrar cuando el ´ngulo cambia de signo; esto es verificar si θn y θn+1 tienen a signos opuestos probando si θn ∗ θn+1 < 0. Cada cambio de signo da una estimaci´n para el o ˜k = 2τ (nk+1 − nk ), donde nk es el paso de tiempo en el cual el k-´simo cambio de per´ ıodo, T e signo ocurre. El per´ ıodo estimado de cada inversi´n de signo es registrado, y el valor medio o calculado como M 1 ˜ ˜ T = Tk , (8.65) M k=1 ˜ donde M es el n´mero de veces que T es evaluado. La barra de error para esta medici´n del u o √ per´ ıodo es estimada como σ = s/ M , donde s= 1 M −1
M

˜ ˜ Tk − T
k=1

2

,

(8.66)

˜ es la desviaci´n est´ndar de la muestra T . Note que cuando el n´mero de medidas se increo a u

´ 8.2. PENDULO SIMPLE.

239

menta, la desviaci´n est´ndar de la muestra tiende a una constante, mientras que la barra o a de error estimado decrece. Para comprobar el programa pendulo, primero tratamos con ´ngulos iniciales peque˜os, a n θm , ya que conocemos el per´ ıodo T ≈ 2π. Tomando τ = 0.1 tendremos sobre 60 puntos por oscilaci´n; tomando 300 pasos deber´ o ıamos tener como cinco oscilaciones. Para θm = 10◦ , ˜ el m´todo de Euler calcula un per´ e ıodo estimado de T = 6.375 ± 0.025 sobre un 1.5 % mayor que el esperado T = 2π(1.002) dado por la ecuaci´n (8.38). Nuestro error estimado o ˜ para el per´ ıodo es entorno a ±τ en cada medida. Cinco oscilaciones son 9 medidas de T , √ as´ que nuestro error estimado para el per´ ı ıodo deber´ ser (τ /2)/ 9 ≈ 0.02. Notemos que la ıa estimaci´n est´ en buen acuerdo con los resultados obtenidos usando la desviaci´n est´ndar. o a o a Hasta aqu´ todo parece razonable. ı
40

30

20

Angulo [grados]

10

0

−10

−20

−30

−40

−50 0 5 10 15 20 25 30

Tiempo

Figura 8.4: Salida del programa p´ndulo usando el m´todo de Euler. El ´ngulo inicial es e e a ◦ θm = 10 , el paso en el tiempo es τ = 0.1, y 300 iteraciones fueron calculadas. Infortunadamente si miramos el gr´fico 8.4 nos muestra los problemas del m´todo de Euler. a e La amplitud de oscilaci´n crece con el tiempo. Ya que la energ´ es proporcional al ´ngulo o ıa a m´ximo, esto significa que la energ´ total se incrementa en el tiempo. El error global de a ıa truncamiento en el m´todo de Euler se acumula en este caso. Para pasos de tiempos peque˜os e n τ = 0.05 e incrementos en el n´mero de pasos (600) podemos mejorar los resultados, ver figura u 8.5, pero no eliminamos el error. El m´todo del punto medio tiene la misma inestabilidad e num´rica. e Usando el m´todo de Verlet con θm = 10◦ , el paso en el tiempo τ = 0.1 y 300 iteraciones e obtenemos los resultados graficados en 8.5. Estos resultados son mucho mejores; la amplitud ˜ de oscilaci´n se mantiene cerca de los 10◦ y T = 6.275 ± 0.037. Afortunadamente el m´todo o e de Verlet, el del “salto de rana” y el de Euler-Cromer no sufren de la inestabilidad num´rica e encontrada al usar el m´todo de Euler. e Para θm = 90◦ , la primera correcci´n para la aproximaci´n de ´ngulo peque˜o, ecuaci´n o o a n o (8.38), da T = 7.252. Usando el m´todo de Verlet, el programa da un per´ e ıodo estimado de ˜ T = 7.414 ± 0.014, lo cual indica que (8.38) es una buena aproximaci´n (alrededor de un o

240
20

´ ´ CAP´ ITULO 8. EDO: METODOS BASICOS.

15

10

Angulo [grados]

5

0

−5

−10

−15

−20

−25 0 5 10 15 20 25 30

Tiempo

Figura 8.5: Salida del programa p´ndulo usando el m´todo de Euler. El ´ngulo inicial es e e a θm = 10◦ , el paso en el tiempo es τ = 0.05 y 600 iteraciones fueron calculadas.

15

10

Angulo [grados]

5

0

−5

−10

−15 0 5 10 15 20 25 30

Tiempo

Figura 8.6: Salida del programa p´ndulo usando el m´todo de Verlet. El ´ngulo inicial es e e a ◦ θm = 10 , el paso en el tiempo es τ = 0.1 y 300 iteraciones fueron calculadas.

2 % de error), a´n para ´ngulos grandes. Para el ´ngulo muy grande de θm = 170◦ , vemos u a a la trayectoria en la figura 8.6. Notemos como la curva tiende a aplanarse en los puntos de ˜ retorno. En este caso el per´ ıodo estimado es T = 15.3333 ± 0.0667, mientras que (8.38) da T = 9.740, indicando que esta aproximaci´n para (8.37) deja de ser v´lida para este ´ngulo o a a tan grande.

8.3. LISTADO DE LOS PROGRAMAS EN PYTHON.
200

241

150

100

Angulo [grados]

50

0

−50

−100

−150

−200 0 5 10 15 20 25 30

Tiempo

Figura 8.7: Salida del programa p´ndulo usando el m´todo de Verlet. El ´ngulo inicial es e e a θm = 170◦ , el paso en el tiempo es τ = 0.1 y 300 iteraciones fueron calculadas.

8.3.
8.3.1.

Listado de los programas en python.
balle.py

#!/usr/bin/env python # -*- coding: iso-8859-1 -*import math from pylab import * Cd=0.35 rho=1.293 radio=0.037 A=math.pi*radio*radio m=0.145 g=9.8 a=-Cd*rho*A/(2.0*m)

# [kg/m^3] # [m] # [kg] # [m/s^2]

def main(): salida=open("salida.txt", "w") salidaT=open("salidaT.txt", "w") x0=0 y0=input("Ingrese la altura inicial [m] :") v0=input("Ingrese la velocidad inicial [m/s]:") theta0=input("Ingrese el angulo inicial (grados):")

242

´ ´ CAP´ ITULO 8. EDO: METODOS BASICOS.

flagRA=2 while flagRA !=0 and flagRA !=1: flagRA=input("Con resistencia del aire, Si=1, No=0: ") tau=input("Ingrese el paso en el tiempo, tau en [s]: ") vxn=v0*math.cos(math.pi*theta0/180.0) vyn=v0*math.sin(math.pi*theta0/180.0) xn=x0 yn=y0 tiempo = -tau l_xT=[] l_yT=[] l_xn=[] l_yn=[] while yn >= y0: tiempo = tiempo+tau l_xT.append(x0+v0*math.cos(math.pi*theta0/180.0)*tiempo) l_yT.append(y0+v0*math.sin(math.pi*theta0/180.0)*tiempo-g*tiempo*tiempo/2.0) print >> salidaT,x0+v0*math.cos(math.pi*theta0/180)*tiempo, print >> salidaT,y0+v0*math.sin(math.pi*theta0/180)*tiempo-g*tiempo*tiempo/2.0 l_xn.append(xn) l_yn.append(yn) print >> salida, xn, yn if flagRA==0: a=0.0 v=math.sqrt(vxn*vxn + vyn*vyn) axn=a*v*vxn ayn=a*v*vyn - g xnp1 = xn + tau * vxn ynp1 = yn + tau * vyn vxnp1 = vxn + tau*axn vynp1 = vyn + tau*ayn vxn=vxnp1 vyn=vynp1 xn=xnp1 yn=ynp1 print "Tiempo de vuelo: ",tiempo print "Alcance: ",xn

8.3. LISTADO DE LOS PROGRAMAS EN PYTHON. salida.close() salidaT.close() plot(l_xn, l_yn,’ro’,l_xT, l_yT,linewidth=1.0) title("Trayectoria de balle") grid(True) show() # if __name__==’__main__’: main()

243

8.3.2.

pendulo.py

#!/usr/bin/env python # -*- coding: iso-8859-1 -*import math from matplotlib import rc from pylab import * rc(’text’, usetex=True) def main(): respuesta = 2 while respuesta !=0 and respuesta != 1: respuesta = input("Elija el metodo Euler=0 o Verlet=1 : ") omega1=0 theta1=input("Ingrese el angulo inicial (en grados) : ") theta1*=math.pi/180.0 tau = input("Ingrese el paso del tiempo : ") pasos = input("Ingrese el numero de pasos : ") periodo = [] salida = open("salidaPendulo.txt", "w") theta0=theta1-tau*omega1-tau*tau*math.sin(theta1) thetaNm1=theta0 thetaN=theta1 omegaN=omega1 nK=1 M=0

244

´ ´ CAP´ ITULO 8. EDO: METODOS BASICOS. l_t=[] l_theta=[] for i in range(1,pasos): alphaN=-math.sin(thetaN) if respuesta==0: # Euler thetaNp1=thetaN+tau*omegaN omegaNp1=omegaN+tau*alphaN else: # Verlet thetaNp1=2.0*thetaN-thetaNm1+tau*tau*alphaN omegaNp1=0.0 #solo por completitud l_t.append((i-1)*tau) l_theta.append(thetaNp1*180/math.pi) print >> salida, (i-1)*tau,thetaNp1*180/math.pi if thetaNp1*thetaN<0: if M==0: M+=1 periodo.append(0.0) nK=i else: M+=1 periodo.append(2.0*tau*(i-nK)) nK=i thetaNm1=thetaN thetaN=thetaNp1 omegaN=omegaNp1 Tprom=0 for i in range(1,M): Tprom += periodo[i] Tprom /= float(M-1) ssr=0 for i in range(1,M): ssr+=(periodo[i]-Tprom)*(periodo[i]-Tprom) ssr/=float(M-2) sigma=math.sqrt(ssr/float(M-1)) print "Periodo = ", Tprom, "+/-", sigma salida.close() plot(l_t, l_theta,’ro’) xlabel(r’\textbf{\Large Tiempo (s)}’) ylabel(r’\textbf{\Large\’Angulo (grados)}’) title(r’\textbf{\Huge P\’endulo no lineal}’)

8.4. LISTADO DE LOS PROGRAMAS EN C++. grid(True) show() # if __name__==’__main__’: main()

245

8.4.
8.4.1.

Listado de los programas en c++.
balle.cc

#include "NumMeth.h" int main() { const double Cd=0.35; const double rho=1.293; // [kg/m^3] const double radio=0.037; // [m] double A= M_PI*radio*radio ; double m=0.145; // [kg] double g=9.8; // [m/s^2] double a = -Cd*rho*A/(2.0e0*m) ; double v0, theta0, tau; ofstream salida ("salida.txt") ; ofstream salidaT ("salidaT.txt") ; double x0, y0; x0=0.0e0 ; cout << "Ingrese la altura inicial [m] : "; cin >> y0; cout << "Ingrese la velocidad inicial [m/s]: "; cin >> v0; cout <<"Ingrese angulo inicial (grados): "; cin >> theta0; int flagRA = 2 ; while (flagRA!=0 && flagRA !=1) { cout <<"Con resistencia del aire, Si= 1, No= 0: "; cin >> flagRA; } cout <<"Ingrese el paso en el tiempo, tau en [s]: "; cin >> tau ; double vxn=v0*cos(M_PI*theta0/180.0) ;

246

´ ´ CAP´ ITULO 8. EDO: METODOS BASICOS.

double vyn=v0*sin(M_PI*theta0/180.0) ; double xn=x0 ; double yn=y0 ; double tiempo = -tau; while( yn >= y0) { tiempo +=tau ; salidaT << x0+v0*cos(M_PI*theta0/180.0) *tiempo <<" " ; salidaT << y0+v0*sin(M_PI*theta0/180.0) *tiempo -g*tiempo*tiempo/2.0e0<< endl; salida << xn << " " << yn << endl; if(flagRA==0) a=0.0e0 ; double v=sqrt(vxn*vxn+vyn*vyn) ; double axn= a*v*vxn ; double ayn= a*v*vyn -g ; double xnp1 = xn + tau*vxn ; double ynp1 = yn + tau*vyn ; double vxnp1 = vxn + tau*axn; double vynp1 = vyn + tau*ayn; vxn=vxnp1; vyn=vynp1; xn=xnp1 ; yn=ynp1 ; } cout << "Tiempo de vuelo: " << tiempo<< endl; cout << "Alcance: " << xn<<endl; salida.close(); salidaT.close(); return 0; }

8.4.2.

pendulo.cc

#include "NumMeth.h" int main() { int respuesta=2 ; while(respuesta != 0 && respuesta !=1 ) { cout << "Elija el metodo: Euler=0 y Verlet=1 : " ; cin >> respuesta ; } double theta1 ; double omega1 = 0.0e0; cout << "Ingrese el angulo inicial (grados): "; cin >> theta1 ; theta1*=M_PI/180.0e0 ;

8.4. LISTADO DE LOS PROGRAMAS EN C++. double tau ; cout << "Ingrese el paso de tiempo: "; cin >> tau ; int pasos ; cout << "Ingrese el numero de pasos: "; cin >> pasos ; double * periodo = new double[pasos] ; ofstream salida ("salidaPendulo.txt"); double theta0= theta1-tau*omega1-tau*tau*sin(theta1) ; double thetaNm1=theta0 ; double thetaN=theta1 ; double omegaN=omega1; double thetaNp1, omegaNp1 ; int nK=1; int M=0 ; for(int i=1; i< pasos; i++) { double alphaN=-sin(thetaN); if(respuesta==0) { // Euler thetaNp1=thetaN+tau*omegaN ; omegaNp1=omegaN+tau*alphaN ; } else { thetaNp1=2.0e0*thetaN-thetaNm1+tau*tau*alphaN ; } salida << (i-1)*tau<<" " <<thetaNp1*180/M_PI<< endl ; if (thetaNp1*thetaN<0) { if(M==0) { periodo[M++]=0.0e0; nK=i ; } else { periodo[M++] = 2.0e0*tau*double(i-nK); nK=i ; } } thetaNm1=thetaN ; thetaN=thetaNp1 ; omegaN=omegaNp1 ; }

247

248

´ ´ CAP´ ITULO 8. EDO: METODOS BASICOS.

double Tprom=0.0e0; for (int i=1; i < M; i++) Tprom+=periodo[i] ; Tprom/=double(M-1) ; double ssr=0.0 ; for (int i=1; i < M; i++) ssr+=(periodo[i]-Tprom)* (periodo[i]-Tprom); ssr/=double(M-2); double sigma =sqrt(ssr/double(M-1)) ; cout <<" Periodo = "<< Tprom << "+/-"<< sigma << endl ; salida.close() ; delete [] periodo; return 0; }

Cap´ ıtulo 9 Ecuaciones Diferenciales Ordinarias II: M´todos Avanzados. e
versi´n 3.2 16 Diciembre 20031 o

En el cap´ ıtulo anterior aprendimos c´mo resolver ecuaciones diferenciales ordinarias usano do algunos m´todos simples. En este cap´ e ıtulo haremos algo de mec´nica celeste b´sica comena a zando con el problema de Kepler. Al calcular la ´rbita de un sat´lite peque˜o alrededor de o e n un cuerpo masivo (e.g un cometa orbitando el Sol), descubriremos que m´todos mucho m´s e a sofisticados son necesarios para manipular sistemas simples de dos cuerpos.

9.1.
9.1.1.

´ Orbitas de cometas.
Ecuaciones b´sicas. a

Considere el problema de Kepler en el cual un peque˜o sat´lite, tal como un cometa, orbita n e el Sol. Usamos un sistema de coordenadas Copernicano y fijamos el Sol en el origen. Por ahora, consideremos solamente la fuerza gravitacional entre el cometa y el Sol, y despreciemos todas las otras fuerzas (e.g., fuerzas debidas a los planetas, viento solar). La fuerza sobre el cometa es GmM r, (9.1) F =− | r |3 donde r es la posici´n del cometa, m es su masa, M = 1.99 × 1030 [kg] es la masa del Sol, y o −11 G = 6.67 × 10 [m3 /kg s2 ] es la constante gravitacional. Las unidades naturales de longitud y tiempo para este problema no son metros ni segundos. Como unidad de distancia usaremos la unidad astron´mica [AU], 1 AU=1.496×1011 [m], o la cual es igual a la distancia media de la Tierra al Sol. La unidad de tiempo ser´ el [a˜o] a n AU (el per´ ıodo de una ´rbita circular de radio 1 [AU]). En estas unidades, el producto o GM = 4π 2 [AU3 /a˜o2 ]. Tomaremos la masa del cometa, m, como la unidad; en unidades n MKS la masa t´ ıpica de un cometa es 1015±3 [kg]. Ahora tenemos suficiente para ensamblar nuestro programa, pero antes hagamos una r´pida revisi´n de lo que sabemos de ´rbitas. Para un tratamiento completo podemos recurrir a o o
Este cap´ ıtulo est´ basado en el tercer cap´ a ıtulo del libro: Numerical Methods for Physics, second edition de Alejandro L. Garcia, editorial Prentice Hall.
1

249

250

´ CAP´ ITULO 9. EDO II: METODOS AVANZADOS.

a algunos textos de mec´nica est´ndar, tales como Symon2 o Landau y Lifshitz3 . La energ´ a a ıa total del sat´lite es e 1 GM m E = mv 2 − , (9.2) 2 r donde r = | r | y v = | v |. Esta energ´ total es conservada, tal como el momento angular, ıa L = r × (mv) . (9.3)

Ya que este problema es bidimensional, consideraremos el movimiento en el plano x-y. El unico componente distinto de cero del momento angular est´ en la direcci´n z. ´ a o Cuando la ´rbita es circular, en el sistema de referencia que gira con el sat´lite, la fuerza o e centr´ ıfuga es compensada por la fuerza gravitacional, GM m mv 2 = , r r2 o GM . (9.5) r Por colocar algunos valores, en una ´rbita circular en r = 1 [AU] la velocidad orbital es v = 2π o ıa [AU/a˜o] (cerca de 30.000 [km/h]). Reemplazando la ecuaci´n (9.5) en (9.2), la energ´ total n o en una ´rbita circular es o GM m E=− . (9.6) 2r En una ´rbita el´ o ıptica, los semiejes mayores y menores, a y b, son desiguales (figura 9.1). La v= (9.4)

y q 2b r Q 2a
´ Figura 9.1: Orbita el´ ıptica alrededor del Sol. excentricidad, e, est´ definida como a e=
2 3

x

1−

b2 . a2

(9.7)

K. Symon, Mechanics (Reading Mass.: Addison-Wesley, 1971). L. Landau and E. Lifshitz, Mechanics (Oxford: Pergamon, 1976).

´ 9.1. ORBITAS DE COMETAS. Nombre del Cometa Encke Biela Schwassmann-Wachmann 1 Halley Grigg-Mellish Hale-Bopp T [a˜os] n 3.30 6.62 16.10 76.03 164.3 2508.0 e q [AU] i 0.847 0.339 12.4◦ 0.756 0.861 12.6◦ 0.132 5.540 9.5◦ 0.967 0.587 162.2◦ 0.969 0.923 109.8◦ 0.995 0.913 89.4◦ Primera pasada 1786 1772 1925 239 a.c. 1742 1995

251

Cuadro 9.1: Datos orbitales de algunos cometas.

La excentricidad de la Tierra es e = 0.017, por lo tanto esta ´rbita est´ muy cercana de ser o a circular. La distancia del Sol al perihelio (punto de mayor aproximaci´n) es q = (1 − e)a; la o distancia del Sol al afelio es Q = (1 + e)a. La ecuaci´n (9.6) tambi´n se mantiene para una ´rbita el´ o e o ıptica, si reemplazamos el radio con el semieje mayor; por lo tanto la energ´ total es ıa E=− GM m . 2a (9.8)

Note que E ≤ 0. De las ecuaciones (9.2) y (9.8), encontramos que la velocidad orbital como funci´n de la distancia radial es o v= GM 2 1 − r a . (9.9)

La velocidad es m´xima en el perihelio y m´ a ınima en el afelio, la raz´n entre las velocidades o est´ dada por Q/q. Finalmente, usando la conservaci´n de momento angular, podr´ a o ıamos derivar la tercera ley de Kepler, 4π 2 3 a , (9.10) T2 = GM donde T es el per´ ıodo de la ´rbita. o Los datos orbitales para unos pocos cometas bien conocidos est´n dados en la tabla 9.1. a La inclinaci´n, i, es el ´ngulo entre el plano orbital del cometa y el plano ecl´ o a ıptico (el plano ◦ de la ´rbita de los planetas). Cuando la inclinaci´n es menor que los 90 , se dice que la ´rbita o o o es directa, cuando es mayor que 90◦ , se dice que la ´rbita es retr´grada (i.e., orbita el Sol en o o la direcci´n opuesta a la de los planetas). o

9.1.2.

Programa orbita.

Un programa simple, llamado orbita, que calcula las ´rbitas para el problema de Kepler o usando varios m´todos num´ricos es propuesto en la tabla 9.2. El m´todo de Euler, descrito e e e en el cap´ ıtulo anterior, calcula la trayectoria del cometa como rn+1 = rn + τ vn , vn+1 = vn + τ a(rn ) , (9.11) (9.12)

252

´ CAP´ ITULO 9. EDO II: METODOS AVANZADOS.

Fijar la posici´n y velocidad inicial del cometa. o Fijar los par´metros f´ a ısicos (m, G, etc.). Iterar sobre el n´mero deseado de pasos usando el m´todo num´rico especificado. u e e • Grabar posici´n y la energ´ para graficar. o ıa • Calcular la nueva posici´n y velocidad usando: o ◦ ◦ ◦ ◦ M´todo e M´todo e M´todo e M´todo e de Euler (9.11), (9.12) o; de Euler-Cromer (9.13), (9.14) o; Runge-Kutta de cuarto orden (9.30), (9.31) o; de Runge-Kutta adaptativo.

Graficar la trayectoria del cometa. Graficar la energ´ del cometa versus el tiempo. ıa

Cuadro 9.2: Bosquejo del programa orbita, el cual calcula la trayectoria de un cometa usando varios m´todos num´ricos. e e donde a es la aceleraci´n gravitacional. De nuevo, discretizamos el tiempo y usamos la notao ci´n fn ≡ f (t = (n − 1)τ ), donde τ es el paso tiempo. o El caso de prueba m´s simple es una ´rbita circular. Para un radio orbital de 1 [AU], la a o ecuaci´n (9.5) da una velocidad tangencial de 2π [AU/a˜o]. Unos 50 puntos por revoluci´n o n o orbital nos dar´ una suave curva, tal que τ = 0.02 [a˜os] (o cercano a una semana) es ıa n un paso de tiempo razonable. Con esos valores, el programa orbita usando el m´todo de e o Euler, da los resultados mostrados en la figura 9.2. Inmediatamente vemos que la ´rbita no es circular, pero una espiral hacia fuera. La raz´n es clara desde el gr´fico de energ´ en vez de o a ıa; ser constante, la energ´ total aumenta continuamente. Este tipo de inestabilidad se observa, ıa tambi´n, en el m´todo de Euler para el p´ndulo simple. Afortunadamente hay una soluci´n e e e o simple a este problema: el m´todo Euler-Cromer para calcular la trayectoria e vn+1 = vn + τ a(rn ) , rn+1 = rn + τ vn+1 . (9.13) (9.14)

Note que el s´lo cambio del m´todo de Euler en que primero calculamos la nueva velocidad, o e vn+1 , y luego la usamos en el c´lculo de la nueva posici´n. Para las mismas condiciones a o iniciales y paso de tiempo, el m´todo de Euler-Cromer da resultados mucho mejores, como e los mostrados en la figura 9.3. La ´rbita es casi circular, y la energ´ total se conserva. o ıa Las energ´ potencial y cin´tica no son constantes, pero este problema podr´ ser mejorado ıas e ıa usando un paso de tiempo peque˜o. El programa ´rbita tambi´n da la opci´n de usar el n o e o m´todo de Runge-Kutta, el cual es descrito en las pr´ximas dos secciones. e o Aunque el m´todo de Euler-Cromer hace un buen trabajo para bajas excentricidades, e tiene problemas con ´rbitas m´s el´ o a ıpticas, como se muestra en la figura 9.4. Note que si la

´ 9.1. ORBITAS DE COMETAS.
90 o
30 Energía Cinética Energía Potencial Energía Total

253

Energía [M AU*AU/año*año]

20

10

0

180o

0o

−10

−20

−30

−40 3 2 1

Distancia [AU]

270o

0

1

2

3

0

0.5

1

1.5

2

2.5

3

3.5

4

Tiempo [años]

Figura 9.2: Gr´fico de la trayectoria y la energ´ desde el programa orbita usando el m´todo a ıa e de Euler. La distancia radial inicial es 1 [AU] y la velocidad tangencial inicial es 2π [AU/a˜o]. n El paso en el tiempo es τ = 0.02 [a˜os]; y 200 pasos son calculados. Los resultados est´n en n a desacuerdo con la predicci´n te´rica de una ´rbita circular con energ´ total constante. o o o ıa

energ´ llega a ser positiva; el sat´lite alcanza la velocidad de escape. Si bajamos el paso de ıa e tiempo desde τ = 0.02 [a˜os] a τ = 0.005 [a˜os] obtenemos mejores resultados, como los n n mostrados en la figura 9.5. Estos resultados no son del todo perfectos; la ´rbita puede ser o una elipse cerrada, pero todav´ tiene una notable deriva esp´ria. ıa u En este punto usted se podr´ estar preguntando, “¿Por qu´ estamos estudiando este ıa e problema?, si la soluci´n anal´ o ıtica es bien conocida”. Es verdad que hay problemas mec´nicos a celestes m´s interesantes (e.g., el efecto de perturbaciones sobre la ´rbita, problema de tres a o cuerpos). Sin embargo, antes de hacer los casos complicados podr´ ıamos, siempre, chequear los algoritmos de problemas conocidos. Suponga que introducimos una peque˜a fuerza de n arrastre sobre el cometa. Podr´ ıamos pecar de inocentes creyendo que la precisi´n de la figura o 9.5 fue un fen´meno f´ o ısico m´s que un artefacto num´rico. a e Claramente, el m´todo de Euler-Cromer hace un trabajo inaceptable de rastreo de las e o ´rbitas m´s el´ a ıpticas. Los resultados mejoran si achicamos el paso de tiempo, pero entonces s´lo podemos rastrear unas pocas ´rbitas. Suponga que deseamos rastrear cometas para o o posibles impactos con la Tierra. Un gran cometa impactando sobre la Tierra ser´ m´s desıa a tructivo que una guerra nuclear. Muchos cometas tienen ´rbitas extremadamente el´ o ıpticas y per´ ıodos de cientos de a˜os. Esta amenaza desde el espacio exterior motiva nuestro estudio n de m´todos m´s avanzados para resolver ecuaciones diferenciales ordinarias. e a

254
90 o

´ CAP´ ITULO 9. EDO II: METODOS AVANZADOS.

30

Energía [M AU*AU/año*año]

20 Energía Cinética Energía Potencial Energía Total 0

10

180o

0o

−10

−20

−30

−40

−50 1.5 1 0.5 0 0.5 1 1.5 0 0.5 1 1.5 2 2.5 3 3.5 4

Distancia [AU]

270o

Tiempo [años]

Figura 9.3: Gr´fico de la trayectoria y la energ´ desde el programa orbita usando el m´todo a ıa e de Euler-Cromer. Los par´metros son los mismos que en la figura 9.2. Los resultados est´n en a a un acuerdo cualitativo al menos con la predicci´n te´rica de una ´rbita circular con energ´ o o o ıa total constante.

90o Energía [M AU*AU/años*años]

200 100 0 −100 −200 0 1

Energía Cinética Energía Potencial Energía Total

180 o

0o

30

20 10 Distancia [AU]

270 o 0 10

20

30

2
Tiempo [años]

3

4

Figura 9.4: Gr´fico de la trayectoria y la energ´ desde el programa orbita usando el m´todo a ıa e de Euler-Cromer. La distancia radial inicial es 1 [AU] y la velocidad tangencial inicial es π [AU/a˜o]. El paso en el tiempo es τ = 0.02 [a˜os]; y 200 pasos son calculados. Debido al n n error num´rico el cometa alcanza la velocidad de escape, la posici´n final es 35 [AU] y la e o energ´ total es positiva. ıa

´ 9.2. METODOS DE RUNGE-KUTTA.
90 o Energía [M AU*AU/años*años] 300 200 100 0 Energía Cinética Energía Potencial Energía Total

255

180o

0o

−100 −200 −300

270o

1

0.5 Distancia [AU]

0

0.5

1

0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1 Tiempo [años]

Figura 9.5: Gr´fico de la trayectoria y la energ´ desde el programa orbita usando el m´todo a ıa e de Euler-Cromer. Los par´metros son los mismos que en la figura 9.4 excepto que el paso de a tiempo es m´s peque˜o τ = 0.005 [a˜os]. Los resultados son mejores, pero a´n presenta una a n n u precesi´n esp´ria. o u

9.2.
9.2.1.

M´todos de Runge-Kutta. e
Runge-Kutta de segundo orden.

Ahora miremos uno de los m´todos m´s populares para resolver num´ricamente las ecuae a e ciones diferenciales ordinarias: Runge-Kutta. Primero trabajaremos las f´rmulas generales de o Runge-Kutta y luego las aplicaremos espec´ ıficamente a nuestro problema del cometa. De esta manera ser´ f´cil usar el m´todo Runge-Kutta para otros sistemas f´ a a e ısicos. Nuestra ecuaci´n o diferencial ordinaria general toma la forma dx = f (x(t), t) , dt (9.15)

donde el vector de estado x(t) = [x1 (t), x2 (t), . . . xN (t)] es la soluci´n deseada. En el problema o de Kepler tenemos x(t) = [rx (t), ry (t), vx (t), vy (t)] , (9.16) y f (x(t), t) = drx dry dvx dvy , , , , dt dt dt dt = [vx (t), vy (t), Fx (t)/m, Fy (t)/m] ,

(9.17)

donde rx , vx , y Fx son las componentes x de la posici´n, la velocidad y la fuerza respectivao mente (y lo mismo para la componente y). Note que en el problema de Kepler, la funci´n f o no depende expl´ ıcitamente del tiempo sino que s´lo depende de x(t). o

256

´ CAP´ ITULO 9. EDO II: METODOS AVANZADOS.

Nuestro punto de partida es el m´todo simple de Euler; en forma vectorial podr´ ser e ıa escrito como x(t + τ ) = x(t) + τ f (x, t) . (9.18) Consideremos la primera f´rmula de Runge-Kutta: o x(t + τ ) = x(t) + τ f donde 1 x∗ t + τ 2 1 ,t + τ 2 , (9.19)

1 1 x ∗ t + τ ≡ x(t) + τ f (x, t) . (9.20) 2 2 Para ver de d´nde viene esta f´rmula, consideremos por el momento el caso de una o o variable. Sabemos que la expansi´n de Taylor o x(t + τ ) = x(t) + τ dx(ζ) , dt = x(t) + τ f (x(ζ), ζ) , (9.21)

es exacta para alg´n valor de ς entre t y t + τ , como se vio en la ecuaci´n (8.10). La f´rmula u o o de Euler toma ς = t; Euler-Cromer usa ς = t en la ecuaci´n de velocidad y ς = t + τ en la o 1 ecuaci´n de posici´n. Runge-Kutta usa ς = t+ 2 τ , lo cual pareciera ser una mejor estimaci´n. o o o 1 Sin embargo, x t + 2 τ no es conocida, podemos aproximarla de la manera simple: usando 1 o un paso de Euler calculamos x∗ t + 1 τ y usando esta como nuestra estimaci´n de x t + 2 τ . 2 A continuaci´n un ejemplo simple usando la f´rmula Runge-Kutta. Consideremos la ecuao o ci´n o dx = −x , x(t = 0) = 1 . (9.22) dt La soluci´n de la ecuaci´n (9.22) es x(t) = e−t . Usando el m´todo de Euler con un paso de o o e tiempo de τ = 0.1, tenemos x(0.1) = 1 + 0.1(−1) = 0.9 , x(0.2) = 0.9 + (0.1)(−0.9) = 0.81 , x(0.3) = 0.81 + 0.1(−0.81) = 0.729 , x(0.4) = 0.729 + 0.1(−0.729) = 0.6561 . Ahora tratemos con Runge-Kutta. Para hacer una correcta comparaci´n usaremos un paso o de tiempo mayor para Runge-Kutta τ = 0.2 porque hace el doble de evaluaciones de f (x). Por la f´rmula de Runge-Kutta presentada arriba, o x∗ (0.1) = 1 + 0.1(−1) = 0.9 , x(0.2) = 1 + 0.2(−0.9) = 0.82 , x∗ (0.3) = 0.82 + 0.1(−0.82) = 0.738 x(0.4) = 0.82 + 0.2(−0.738) = 0.6724 . Podemos comparar esto con la soluci´n exacta x(0.4) = exp(−0.4) ≈ 0.6703. Claramente, o Runge-Kutta lo hace mucho mejor que Euler; los errores porcentuales absolutos son 0.3 % y 2.1 % respectivamente.

´ 9.2. METODOS DE RUNGE-KUTTA.

257

9.2.2.

F´rmulas generales de Runge-Kutta. o

La f´rmula discutida arriba no es la unica posible para un Runge-Kutta de segundo orden. o ´ Aqu´ hay una alternativa: ı 1 x(t + τ ) = x(t) + τ [f (x(t), t) + f (x ∗ (t + τ ), t + τ )] , 2 donde x ∗ (t + τ ) ≡ x(t) + τ f (x(t), t) . (9.24) (9.23)

Para entender este esquema, consideremos nuevamante el caso en una variable. En nuestra f´rmula original, estimamos que f (x(ς), ς) como 1 [f (x, t) + f (x ∗ (t + τ ), t + τ )]. o 2 Estas expresiones pueden ser deducidas usando la expansi´n de Taylor con dos variables, o

f (x + h, t + τ ) =
n=0

1 n!

∂ ∂ h +τ ∂x ∂t

n

f (x, t) ,

(9.25)

donde todas las derivadas son evaluadas en (x, t). Para una f´rmula general de Runge-Kutta o de segundo orden queremos obtener una expresi´n de la siguiente forma o x(t + τ ) = x(t) + w1 τ f (x(t), t) + w2 τ f (x∗ , t + ατ ) , donde x∗ ≡ x(t) + βτ f (x(t), t) . (9.27) (9.26)

Hay cuatro coeficientes no especificados: α, β, w1 y w2 . Note que cubrimos las ecuaciones (9.19) y (9.20) eligiendo los valores w1 = 0 , w2 = 1 α= 1 , 2 β= 1 , 2 (9.28)

y las ecuaciones (9.23) y (9.24) eligiendo w1 = 1 , 2 w2 = 1 , 2 α=1, β=1. (9.29)

Deseamos seleccionar cuatro coeficientes tal que tengamos una precisi´n de segundo orden; o esto es deseamos calzar la serie de Taylor a trav´s de los t´rminos de la segunda derivada. e e Los detalles del c´lculo se proponen como un ejercicio, pero cualquier grupo de coeficientes a satisfacen las relaciones siguientes w1 + w2 = 1, αw2 = 1/2 y α = β dar´n un esquema a Runge-Kutta de segundo orden. El error de truncamiento local es O(τ 3 ), pero la expresi´n o expl´ ıcita no tiene una forma simple. No est´ claro que un esquema sea superior al otro ya a que el error de truncamiento, siendo una funci´n complicada de f (x, t), variar´ de problema o a a problema.

258

´ CAP´ ITULO 9. EDO II: METODOS AVANZADOS.

9.2.3.

Runge-Kutta de cuarto orden.

Presentamos las f´rmulas de Runge-Kutta de segundo orden porque es f´cil de comprender o a su construcci´n. En la pr´ctica, sin embargo, el m´todo m´s com´nmente usado es la siguiente o a e a u f´rmula de cuarto orden: o 1 x(t + τ ) = x(t) + τ F1 + 2F2 + 2F3 + F4 6 donde F1 = f (x, t) , F2 = f F3 = f 1 x + τ F1 , t + 2 1 x + τ F2 , t + 2 1 τ 2 1 τ 2 , (9.31) , , (9.30)

F4 = f (x + τ F3 , t + τ ) . El siguiente extracto del Numerical Recipes4 resume mejor el estado que las f´rmulas de o arriba tienen en el mundo del an´lisis num´rico: a e Para muchos usuarios cient´ ıficos, el m´todo de Runge-Kutta de cuarto orden no es e s´lo la primera palabra en esquemas de integraci´n para ecuaciones diferenciales o o ordinarias, si no que es la ultima tambi´n. De hecho, usted puede ir bastante lejos ´ e con este viejo caballito de batalla, especialmente si los combina con un algor´ ıtmo de paso adaptativo. . . Bulirsch-Stoer o los m´todos predictor-corrector pueden ser e mucho m´s eficientes para problemas donde se require una alta precisi´n. Estos a o m´todos son los finos caballos de carrera mientras que Runge-Kutta es el fiel e caballo de tiro. Usted se preguntar´, ¿por qu´ f´rmulas de cuarto orden y no de orden superior? Bien, los a e o m´todos de orden superior tienen un error de truncamiento mejor, pero tambi´n requieren e e m´s c´lculo, esto es, m´s evaluaciones de f (x, t). Hay dos opciones, hacer m´s pasos con un τ a a a a peque˜o usando un m´todo de orden inferior o hacer pocos pasos con un τ m´s grande usando n e a un m´todo de orden superior. Ya que los m´todos de Runge-Kutta de ´rdenes superiores son e e o muy complicados, el esquema de cuarto orden dado anteriormente es muy conveniente. Entre par´ntesis, el error de truncamiento local para Runge-Kutta de cuarto orden es O(τ 5 ). e Para implementar m´todos de cuarto orden para nuestro problema de la ´rbita, usaremos e o o la funci´n rk4 (tabla 9.3). Esta funci´n toma como datos: el estado actual del sistema, x(t); el o paso de tiempo para ser usado, τ ; el tiempo actual, t; la funci´n f (x(t), t; λ); donde λ es una o lista de par´metros usados por f . La salida es el nuevo estado del sistema, x(t + τ ), calculado a por el m´todo de Runge-Kutta. Usando Runge-Kutta de cuarto orden da los resultados e mostrados en la figura 9.6, la cual es mucho mejor que las obtenidas usando el m´todo de e Euler-Cromer (figura 9.5).
W. Press, B. Flannery, S. Tukolsky and W. Vetterling, Numerical Recipes in fortran, 2nd ed. (Cambridge: Cambridge University Press 1992).
4

´ 9.2. METODOS DE RUNGE-KUTTA.

259

Entradas: x(t), t, τ , f (x, t; λ), y λ. Salidas: x(t + τ ). Evaluaci´n F1 , F2 , F3 y F4 usando ecuaci´n (9.31). o o C´lculo de x(t + τ ) usando Runge-Kutta de cuarto orden, usando ecuaci´n (9.30). a o

Cuadro 9.3: Bosquejo de la funci´n rk4, la cual eval´a un paso simple usando el m´todo o u e Runge-Kutta de cuarto orden. Entradas: x(t), t (no se usa), GM . Salidas: dx(t)/dt. Eval´a la aceleraci´n a = −(GM r/ | r |3 ). u o Retorno: dx(t)/dt = [vx , vy , ax , ay ].

Cuadro 9.4: Bosquejo de la funci´n gravrk, la cual es usada por la funci´n Runge-Kutta para o o evaluar las ecuaciones de movimiento para el problema de Kepler.

9.2.4.

Pasando funciones a funciones.

La funci´n de Runge-Kutta rk4 es muy simple, pero introduce un elemento de prograo maci´n que no hemos usado antes. La funci´n f (x, t; λ) est´ introducida como un par´metro o o a a de entrada a rk4. Esto nos permite usar rk4 para resolver diferentes problemas cambiando simplemente la definici´n de f (como lo haremos en la ultima secci´n). Para el problema de o ´ o Kepler, la funci´n gravrk (tabla 9.4) define la ecuaci´n de movimiento devolviendo dx/dt, o o ecuaci´n (9.17). o En C++ el puntero a la funci´n f (x, t; λ) es pasado como par´metro a rk4. El programa o a orbita llama a rk4 como rk4( state, nState, time, tau, gravrk, param) ; donde el vector de estado es x = [rx , ry , vx , vy ]. En el inicio del archivo, la funci´n gravrk es o declarada con el prototipo void gravrk( double * x, double t, double param, double * deriv ); La primera l´ ınea de rk4 es void rk4(double * x, int nX, double t, double tau, void (*derivsRK) (double *, double, double, double *) , double param)

260
90 o

´ CAP´ ITULO 9. EDO II: METODOS AVANZADOS.
300

Energía [M AU*AU/años*años]

200

Energía Cinética Energía Potencial Energía Total

100

180o

0o

0

−100

−200

1

0.5

0

Distancia [AU]

270

o

0.5

1

−300

0

0.2

0.4

0.6

0.8

1.0

Tiempo [años]

Figura 9.6: Gr´fico de la trayectoria y la energ´ desde el programa orbita usando el m´todo a ıa e de Runge-Kutta. La distancia radial inicial es 1 [AU] y la velocidad tangencial inicial es π [AU/a˜o]. El paso en el tiempo es τ = 0.005 [a˜os]; y 200 pasos son calculados. Comparemos n n con la figura 9.5.

Cuando es llamado por orbita, esta funci´n recibe un puntero a gravrk en la variable o derivsRK. Dentro de rk4, la sentencia (*derivsRK)( x, t, param, F1 ) ; es equivalente a gravrk( x, t, param, F1 ) ; ya que dervsRK apunta a gravrk.

9.3.
9.3.1.

M´todos adaptativos e
Programas con paso de tiempo adaptativo.

Ya que el m´todo de Runge-Kutta de cuarto orden es m´s preciso (errores de truncamiento e a peque˜os), hace un mejor trabajo dentro de una ´rbita altamemente el´ n o ıptica. A´n para una u distancia inicial al afelio de 1 [AU] y una velocidad inicial en el afelio de π/2 [AU/a˜o] usando n 1 un paso tiempo tan peque˜o como τ = 0.0005 [a˜os] (≈ 4 2 [hrs]), la energ´ total var´ sobre n n ıa ıa el 7 % por ´rbita. Si pensamos la f´ o ısica, llegamos a que realizar una integraci´n con un paso o peque˜o es s´lo necesaria cuando el cometa haga su acercamiento m´s pr´ximo, punto en el n o a o cual su velocidad es m´xima. Cualquier error peque˜o en la trayectoria cuando rodea al Sol a n causa una gran desviaci´n en la energ´ potencial. o ıa La idea ahora es dise˜ar un programa que use un paso de tiempo peque˜o cuando el comen n ta est´ cerca del Sol y pasos de tiempo grande cuando est´ lejos. Tal como est´, normalmente a a a

´ 9.3. METODOS ADAPTATIVOS

261

tenemos s´lo una idea apr´ximada de lo que τ pudiera ser; ahora tenemos que seleccionar un o o τm´ y un τm´x y una manera de intercambiar entre ellos. Si tenemos que hacer esto por prueba ın a y error manual, podr´ ser peor que haci´ndolo por la fuerza bruta calculando con un paso ıa e de tiempo peque˜o toda la trayectoria. Idealmente, deseamos estar completamente liberados n de tener que especificar un paso de tiempo. Deseamos tener una trayectoria calculada de la misma posici´n inicial hasta alg´n tiempo final con la seguridad de que la soluci´n es correcta o u o a una precisi´n especificada o Los programas adaptativos continuamente monitorean la soluci´n y modifican el paso de o tiempo para asegurar que se mantenga la precisi´n especificada por el usuario. Esos programas o pueden hacer algunos c´lculos extras para optimizar la elecci´n de τ , en muchos casos este a o trabajo extra vale la pena. Aqu´ est´ una manera para implementar esta idea: dado el estado ı a actual x(t), el programa calcula x(t + τ ) como siempre, y luego repite el c´lculo haciendolo a τ en dos pasos, cada uno con paso de tiempo 2 . Visualmente, esto es

paso grande

x (t)
paso pequeño

x (t+τ/2)

paso pequeño

x b(t+ τ) x s (t+ τ)

La diferencia entre las dos respuestas, xb (t+τ ) y xs (t+τ ), estima el error de truncamiento local. Si el error es tolerable, el valor calculado es aceptado y un valor mayor de τ es usado en la pr´xima iteraci´n. Por otra parte, si el error es muy grande, la respuesta es rebotada, el o o paso de tiempo es reducido y el procedimiento es repetido hasta que se obtenga una respuesta aceptable. El error de truncamiento estimado para el actual paso de tiempo puede guiarnos en seleccionar en nuevo paso de tiempo para la pr´xima iteraci´n. o o

9.3.2.

Funci´n adaptativa de Runge-Kutta. o

Aqu´ mostramos c´mo una iteraci´n adaptativa puede ser implementada para un esquema ı o o de Runge-Kutta de cuarto orden: llamemos ∆ al error de truncamiento; sabemos que ∆ ∝ τ 5 para un esquema Runge-Kutta de cuarto orden. Supongamos que el paso de tiempo actual τant da un error de ∆c = | xb − xs |; esta es nuestra estimaci´n para el error de truncamiento. o Dado que deseamos que el error sea menor o igual que el error ideal especificado por el usuario, le llamamos ∆i ; luego, el nuevo paso de tiempo estimado es τest ∆i =τ ∆c
1/5

.

(9.32)

Ya que esto es s´lo una estimaci´n, el nuevo paso de tiempo es τnuevo = S1 τest , donde S1 < 1. o o Esto nos hace sobreestimar el cambio cuando disminuimos τ y subestimar el cambio cuando lo aumentamos. Malogramos los esfuerzos computacionales cada vez que rebotamos una respuesta y necesitamos reducir el paso de tiempo, por lo tanto es mejor ajustar τnuevo < τest . Podr´ ıamos poner un segundo factor de seguridad, S2 < 1, para asegurarse que el programa no sea demasiado entusiasta en aumentar o disminuir precipitadamente el paso de tiempo.

262

´ CAP´ ITULO 9. EDO II: METODOS AVANZADOS.

Con ambas precauciones, el nuevo paso de tiempo es  S2 τant si S1 τest > S2 τant  τnuevo = τ /S2 si S1 τest < τant /S2 .   S1 τest en otro caso

(9.33)

Entradas: x(t), t, τ , ∆i , f (x, t; λ), y λ. Salidas: x(t ), t , τnuevo . Fijar las variables iniciales Iterar sobre el n´mero deseado de intentos para satisfacer el error l´ u ımite. • Tomar dos peque˜os pasos de tiempo. n • Tomar un unico paso grande de tiempo. ´ • Calcule el error de truncamiento estimado. • Estime el nuevo valor de τ (incluyendo factores de seguridad). • Si el error es aceptable, regresar los valores calculados. Mostrar un mensaje de error si el error l´ ımite nunca es satisfecho.

Cuadro 9.5: Bosquejo de la funci´n rka, la cual eval´a un unico paso usando un m´todo o u ´ e adaptativo de Runge-Kutta de cuarto orden. Esto obliga a asegurar que nuestro nueva estimaci´n para τ nunca aumente o decrezca o por m´s que un factor S2 . Por supuesto, este nuevo τ podr´ ser insuficientemente peque˜o, a ıa n y tendr´ ıamos que continuar reduciendo el paso de tiempo; pero al menos sabr´ ıamos que no ocurrir´ de un modo incontrolado. a Este procedimiento no es “a prueba de balas”, los errores de redondeo llegan a ser significativos en pasos de tiempos muy peque˜os. Por esta raz´n la iteraci´n adaptativa podr´ n o o ıa fallar para encontrar un paso de tiempo que de la precisi´n deseada. Debemos mantener esta o limitaci´n en mente cuando especifiquemos el error aceptable. Una funci´n de Runge-Kutta o o adaptativa, llamada rka, es esbozada en la tabla 9.5. Note que los datos de entrada en la secuencia de llamada son los mismos que para rk4, excepto por la suma de ∆i , el error ideal especificado. Las salidas del rka son el nuevo estado del sistema, x(t ); el tiempo nuevo, t y el nuevo paso de tiempo, τ nuevo, el cual podr´ ser usado la pr´xima vez que sea llamada ıa o la rka. Usando el m´todo de Runge-Kutta adaptativo, el programa orbita da los resultados en e la figura 9.7 para una ´rbita altamente el´ o ıptica. Notemos que el programa toma muchos m´s a pasos en el perihelio que en el afelio. Podemos comparar con los resultados usando el m´todo e de Runge-Kutta no adaptativo (figura 9.6) en el cual los pasos en el perihelio son ampliamente

´ 9.3. METODOS ADAPTATIVOS
90 o
1500

263

Energía [M AU*AU/años*años]

Energía Cinética Energía Potencial Energía Total

1000

500

180

o

0o

0

−500

−1000

270
1 0.5 0

o 0.5 1

−1500

0

0.05

0.1

0.15

0.2

0.25

Distancia [AU]

Tiempos [años]

Figura 9.7: Gr´fico de la trayectoria y la energ´ desde el programa orbita usando el m´todo a ıa e de Runge-Kutta adaptativo. La distancia radial inicial es 1 [AU] y la velocidad tangencial inicial es π/2 [AU/a˜o]. El paso inicial en el tiempo es τ = 0.1 [a˜os]; y 40 pasos son n n calculados.

0.1

0.01 Tau [aæos]
 

0.001

0.0001 0.01

0.1 Distancia [Au]

1

Figura 9.8: Paso de tiempo como funci´n de la distancia radial desde el programa orbita o usando el m´todo de Runge-Kutta adaptativo. Los param´tros son los mismos de la figura e e 9.7.

espaciados. Una gr´fica de los pasos de tiempo versus la distancia radial (figura 9.8) muestra a que τ var´ casi tres ´rdenes de magnitud.√ ıa o Interesantemente esta gr´fica revela una relaci´n a o 3 . Por supuesto esta dependencia nos recuerda exponencial aproximada de la forma τ ∝ r la tercera ley de Kepler, ecuaci´n (9.10). Esperamos alguna dispersi´n en los puntos, ya que o o nuestra rutina adaptada solamente estima el paso de tiempo ´ptimo. o

264

´ CAP´ ITULO 9. EDO II: METODOS AVANZADOS.

9.4.
9.4.1.

Listados del programa.
orbita.cc

#include "NumMeth.h" const double GM=4.0e0*M_PI*M_PI ; const double masaCometa = 1.0e0 ; const double adaptErr = 1.0e-3; void rk4(double * x, int nX, double t, double tau, void(*derivsRK)(double *, double, double, double *), double param) { double * F1=new double [nX] ; double * F2=new double [nX] ; double * F3=new double [nX] ; double * F4=new double [nX] ; double * xtemp=new double [nX] ; // Evaluemos F1=f(x,t) (*derivsRK) (x, t, param, F1) ; double half_tau = tau/2.0e0; double t_half = t+half_tau ; double t_full = t+tau ; // Evaluamos F2=f(x+tau*F1/2, t+tau/2) for(int i=0; i<nX; i++) xtemp[i]=x[i]+half_tau*F1[i] ; (*derivsRK) (xtemp, t_half, param, F2) ; // Evaluamos F3=f(x+tau*F2/2, t+tau/2) for(int i=0; i<nX; i++) xtemp[i]=x[i]+half_tau*F2[i] ; (*derivsRK) (xtemp, t_half, param, F3) ; // Evaluamos F4=f(x+tau*F3, t+tau) for(int i=0; i<nX; i++) xtemp[i]=x[i]+tau*F3[i] ; (*derivsRK) (xtemp, t_full, param, F4) ; // Retornamos x(t+tau) for(int i=0; i<nX; i++) x[i] += tau*(F1[i]+F4[i]+2.0e0*(F2[i]+F3[i]))/6.0e0 ; delete [] F1; delete [] F2; delete [] F3; delete [] F4; delete [] xtemp ;

9.4. LISTADOS DEL PROGRAMA. } void rka ( double * x, int nX, double & t, double & tau, double erro, void(*derivsRK)(double *, double, double, double *), double param) { double tSave = t ; double safe1 = 0.9, safe2 = 4.0 ; //factores de seguridad double * xSmall = new double[nX] ; double * xBig = new double[nX] ; int maxTray=100 ; for (int iTray=0; iTray<maxTray; iTray++) { // Tomemos dos peque{\~n}os pasos en el tiempo double half_tau = 0.5*tau ; for (int i =0; i < nX; i++) xSmall[i]=x[i] ; rk4( xSmall, nX, tSave, half_tau, derivsRK, param) ; t= tSave + half_tau ; rk4( xSmall, nX, t, half_tau, derivsRK, param) ; // Tomemos un solo tiempo grande for (int i =0; i < nX; i++) xBig[i]=x[i] ; rk4( xBig, nX, tSave, tau, derivsRK, param) ; // Calculemos el error de truncamiento estimado double erroRatio = 0.0e0 ; double eps = 1.0e-16 ; for (int i = 0 ; i < nX; i++) { double scale = erro * (fabs(xSmall[i]) + fabs(xBig[i]))/2.0e0 ; double xDiff = xSmall[i] - xBig[i] ; double ratio = fabs(xDiff)/(scale+eps) ; erroRatio = (erroRatio > ratio ) ? erroRatio:ratio ; } // Estimamos el nuevo valor de tau (incluyendo factores de seguridad) double tau_old= tau ; tau = safe1*tau_old*pow(erroRatio, -0.20) ; tau = (tau > tau_old/safe2) ? tau:tau_old/safe2 ; tau = (tau < safe2*tau_old) ? tau:safe2*tau_old ; // Si el error es aceptable regrese los valores computados if ( erroRatio < 1 ) { for (int i =0 ; i < nX; i++) x[i]=xSmall[i] ; return ; } } cout << "Error: Runge-Kutta adaptativo fallo" << endl ;

265

266 exit(-1) ; }

´ CAP´ ITULO 9. EDO II: METODOS AVANZADOS.

void gravrk( double * x, double t, double param, double * deriv) { double gm=param ; double rX=x[0], rY=x[1]; double vX=x[2], vY=x[3] ; double mod_r= sqrt(rX*rX+rY*rY) ; double aX= -gm*rX/(mod_r*mod_r*mod_r) ; double aY= -gm*rY/(mod_r*mod_r*mod_r) ; // Retorna la derivada deriv[0] deriv[1] deriv[2] deriv[3] } int main() { ofstream salidaO ("Orbita.txt") ; ofstream salidaE ("Energia.txt") ; ofstream salidaT ("Tau.txt") ; double r0 ; cout << "Ingrese la distancia radial inicial [AU]: " ; cin >> r0 ; double vT ; cout << "Ingrese la velocidad tangencial inicial [AU/a{\~n}os]: " ; cin >> vT ; double x0=r0 ; double y0=0.0e0; double vx0=0.0e0 ; double vy0=vT; // // Suponemos angulo inicial nulo // int metodo = 0 ; while( metodo < 1|| metodo > 4 ) { cout << "Ingrese el m{\’e}todo num{\’e}rico a usar :" << endl ; cout << "\t Metodo de Euler \t\t\t[1]" << endl; cout << "\t Metodo de Euler-Cromer \t\t[2]" << endl; = = = = vX; vY; aX; aY;

9.4. LISTADOS DEL PROGRAMA. cout << "\t Metodo de Runge-Kutta 4 orden \t\t[3]" << endl; cout << "\t Metodo de Runge-Kutta adaptativo \t[4]" << endl; cout << "elija: " ; cin >> metodo ; } double tau ; cout << "Ingrese paso en el tiempo: " ; cin >> tau ; int numPasos ; cout << "Ingrese el numero de pasos: " ; cin >> numPasos ; double param=GM ; const int dimX= 4; double * x = new double[dimX] ; double double double double double double xN= x0; yN= y0; vxN=vx0; vyN=vy0; vxNp1, vyNp1, xNp1, yNp1; tiempo = 0.0e0 ;

267

for(int pasos=0; pasos < numPasos; pasos++) { double r =sqrt(xN*xN+yN*yN) ; double v2 =vxN*vxN+vyN*vyN ; double theta= atan2(yN, xN) ; salidaO << theta << " " << r << endl ; double Ep = -GM*masaCometa/r ; double Ek = masaCometa*v2/2.0e0 ; double ET= Ep+Ek ; salidaE<< tiempo << " " << Ek<< " " << Ep<<" " << ET << endl ; double modr3=pow(xN*xN+yN*yN, 3.0e0/2.0e0) ; double axN= -GM*xN/modr3 ; double ayN= -GM*yN/modr3 ; switch( metodo ) { case 1: { // Euler vxNp1=vxN+tau*axN ; vyNp1=vyN+tau*ayN ; xNp1= xN+tau* vxN ; yNp1= yN+tau* vyN ; tiempo += tau ;

268

´ CAP´ ITULO 9. EDO II: METODOS AVANZADOS. } break ; case 2: { // Euler-Cromer vxNp1=vxN+tau*axN ; vyNp1=vyN+tau*ayN ; xNp1= xN+tau* vxNp1 ; yNp1= yN+tau* vyNp1 ; tiempo += tau ; } break ; case 3: { // Runge-Kutta 4to Orden x[0] = xN; x[1] = yN; x[2] = vxN; x[3] = vyN; rk4( x, dimX, tiempo, tau, gravrk, param); xNp1=x[0] ; yNp1=x[1]; vxNp1=x[2]; vyNp1=x[3]; tiempo += tau ; } break ; case 4: { x[0] = xN; x[1] = yN; x[2] = vxN; x[3] = vyN; rka( x, dimX, tiempo, tau, adaptErr, gravrk, param); double distancia = sqrt( x[0]*x[0]+x[1]*x[1]) ; salidaT<< distancia << " " <<tau << endl ; xNp1=x[0] ; yNp1=x[1]; vxNp1=x[2]; vyNp1=x[3]; } } xN=xNp1 ; yN=yNp1 ; vxN=vxNp1 ; vyN=vyNp1 ;

} salidaO.close() ; salidaE.close() ; salidaT.close() ;

9.4. LISTADOS DEL PROGRAMA. delete [] x; return 0; }

269

270

´ CAP´ ITULO 9. EDO II: METODOS AVANZADOS.

Cap´ ıtulo 10 Resolviendo sistemas de ecuaciones.
versi´n final 2.20-0304071 o

En este cap´ ıtulo aprenderemos a c´mo resolver sistemas de ecuaciones de ambos tipos, o lineal y no lineal. Ya conocemos los algoritmos b´sicos para los sistemas lineales: eliminar a variables hasta que tengamos una sola ecuaci´n con una sola inc´gnita. Para sistemas noo o lineales desarrollamos un esquema iterativo que en cada paso resuelve una versi´n linealizada o de estas ecuaciones. Para mantener la continuidad, la discusi´n ser´ motivada por el c´lculo o a a del estado estacionario, un importante tema en ecuaciones diferenciales ordinarias.

10.1.
10.1.1.

Sistemas de ecuaciones lineales.
Estado estacionario de EDO.

En el cap´ ıtulo pasado, nosotros vimos c´mo resolver ecuaciones diferenciales ordinarias o de la forma dx = f (x, t) , (10.1) dt donde x = [x1 , x2 , . . . , xN ]. Dada una condici´n inicial para las N variables xi (t) = 0, nosotros o podemos calcular la serie de tiempo xi (t) por una variedad de m´todos (e.g. Runge-Kutta). e Los ejemplos que hemos estudiado hasta aqu´ han sido aquellos conocidos como sistemas ı aut´nomos donde f (x, t) = f (x), esto es, f no depende expl´ o ıcitamente del tiempo. Para sistemas aut´nomos, a menudo existe una importante clase de condiciones iniciales para las o cuales xi (t) = xi (0) para todo i y t. Estos puntos, en el espacio N -dimensional de nuestras variables, son llamados estado estacionario. Si nosotros partimos de un estado estacionario nos quedamos ah´ para siempre. Localizar los estados estacionarios para ecuaciones diferenciales ı ordinarias es importante, ya que ellos son usados en el an´lisis de bifurcaciones.2 a ∗ ∗ ∗ ∗ Es f´cil ver que x = [x1 , x2 , . . . , xN ] es un estado estacionario si y s´lo si a o f (x ∗ ) = 0 , o fi (x∗ , x∗ , . . . , x∗ ) = 0 , 1 2 N
1

(10.2) para todo i, (10.3)

Este cap´ ıtulo est´ basado en el cuarto cap´ a ıtulo del libro: Numerical Methods for Physics, second edition de Alejandro L. Garcia, editorial Prentice Hall. 2 R. Seydel, From Equilibrium to Chaos, Practical Bifurcation and Stability Analysis (New York: Elsevier, 1988).

271

272

CAP´ ITULO 10. RESOLVIENDO SISTEMAS DE ECUACIONES.

ya que esto implica que dx ∗ /dt = 0. Localizar los estados estacionarios se reduce al problema de resolver N ecuaciones con N inc´gnitas xi ∗ . Este problema es tambi´n llamado “encontrar o e las raices de f (x)”. Como un ejemplo, consideremos el p´ndulo simple; el estado est´ descrito por el ´ngulo e a a θ y la velocidad angular ω. Los estados estacionarios se encuentran al resolver las ecuaciones no lineales g − sen θ∗ = 0 , ω ∗ = 0 . (10.4) L Las raices son θ∗ = 0, ±π, ±2π, . . . y ω ∗ = 0. Por supuesto que no todos los sistemas son tan f´ciles de resolver. a Deber´ ser claro que encontrar raices tiene muchas m´s aplicaciones que calcular los ıa a estados estacionario. En este cap´ ıtulo consideraremos una variedad de maneras para resolver ambos sistemas lineales y sistemas no lineales. En esta secci´n y en la pr´xima consideraremos o o sistemas lineales, dejando los sistemas no lineales para la parte final del cap´ ıtulo.

10.1.2.

Eliminaci´n Gaussiana. o

El problema de resolver fi ({xj }) = 0 se divide en dos importantes clases. En esta secci´n o consideramos el caso f´cil cuando fi ({xj }) es una funci´n lineal. El problema en ese caso se a o reduce a resolver un sistema de N ecuaciones con N inc´gnitas. o a11 x1 + a12 x2 + . . . + a1N xN − b1 = 0 a21 x1 + a22 x2 + . . . + a2N xN − b2 = 0 . . . . . . . . . . . . aN 1 x1 + aN 2 x2 + . . . + aN N xN − bN = 0 , o en forma matricial ˇ Ax − b = 0 , donde   a11 a12 . . .  ˇ  A = a21 a22 . . . , . . .. . . . . .   x1 x2  x=  , . . .   b1 b2  b=  . . . . (10.6)

(10.5)

(10.7)

Sabemos c´mo resolver este conjunto de ecuaciones. Combinando las ecuaciones para o eliminar variables hasta que tengamos una sola ecuaci´n con una sola inc´gnita. Hagamos o o un ejemplo simple para revisar c´mo el procedimiento trabaja. Tomemos las ecuaciones o x1 + x2 + x3 = 6 , −x1 + 2x2 = 3, 2x1 + x3 = 5 . (10.8)

Deseamos eliminar x1 de la segunda y de la tercera ecuaci´n. Para llevar a cabo esto, primero o sumamos la primera y la segunda y despu´s restamos dos veces la primera a la tercera. Esto e nos da x1 + x2 + x3 = 6, 3x2 + x3 = 9, (10.9) −2x2 − x3 = −7 .

10.1. SISTEMAS DE ECUACIONES LINEALES.

273

Ahora, eliminamos x2 de la ultima ecuaci´n multiplicando la segunda ecuaci´n por − 2 y la ´ o o 3 restamos de la tercera, d´ndonos a x1 + x2 + 3x2 + x3 = 6, x3 = 9, 1 − 3 x3 = −1 .

(10.10)

Este procedimiento es llamado eliminaci´n hacia adelante. Si se tienen N ecuaciones, elimio namos x1 de las ecuaciones 2 hasta la N , luego eliminamos x1 y x2 de las ecuaciones 3 hasta la N , y as´ sucesivamente. La ultima ecuaci´n s´lo contendr´ la variable xN . ı ´ o o a Volviendo al ejemplo, es ahora trivial resolver la tercera ecuaci´n resultando x3 = 3. o Podemos ahora sustituir este valor en la segunda ecuaci´n obteniendo 3x2 + 3 = 9, tal que o x2 = 2. Finalmente, introduciendo los valores de x2 y x3 en la primera ecuaci´n obtenemos o x1 = 1. Este segundo procedimiento es llamado sustituci´n hacia atr´s. Deber´ ser claro o a ıa c´mo esto trabaja con sistemas grandes de ecuaciones. Usando la ultima ecuaci´n obtenemos o ´ o xN , ´ste es usado en la pen´ltima ecuaci´n para obtener xN −1 y as´ seguimos. e u o ı Este m´todo de resolver sistemas de ecuaciones lineales por eliminaci´n hacia adelante e o 3 y luego sustituci´n hacia atr´s es llamado eliminaci´n Gaussiana. Esta es una secuencia o a o rutinaria de pasos que es simple para un computador realizar sistem´ticamente. Para N a ecuaciones con N inc´gnitas, el tiempo de computaci´n para eliminaci´n Gaussiana va como o o o N 3 . Afortunadamente, si el sistema es esparcido o ralo4 (la mayor´ de los coeficientes son ıa cero), el tiempo de c´lculo puede ser considerablemente reducido. a

10.1.3.

Pivoteando.

La eliminaci´n Gaussiana es un procedimiento simple, sin embargo, se debe estar conciente o de sus riesgos. Para ilustrar la primera fuente de problemas, consideremos el conjunto de ecuaciones x 1 + x2 + x3 = 5 , x1 + x2 = 3, (10.11) x1 + x3 = 4 . En el l´ ımite → 0 la soluci´n es x1 = 1, x2 = 2, x3 = 3. Para estas ecuaciones, el primer o paso de la eliminaci´n hacia adelante podr´ partir por multiplicar la primera ecuaci´n por o ıa o (1/ ) y sustray´ndola de la segunda y tercera ecuaciones, lo que da e x1 + x2 + x3 = 5, (1 − 1/ )x2 − (1/ )x3 = 3 − 5/ , −(1/ )x2 + (1 − 1/ )x3 = 4 − 5/ .

(10.12)

Por supuesto, si = 0 tenemos grandes problemas, ya que el factor 1/ estalla. A´n si = 0, u pero es peque˜o, vamos a tener serios problemas de redondeo. Supongamos que 1/ es tan n
G.E. Forsythe and C.B. Moler, Computer Solution of Linear Algebraic System (Upper Saddle River, N.J.: Prentice-Hall, 1967). 4 sparse
3

274

CAP´ ITULO 10. RESOLVIENDO SISTEMAS DE ECUACIONES.

grande que (C − 1/ ) → −1/ , donde C es del orden de la unidad. Nuestras ecuaciones, despu´s del redondeo, llegan a ser e x1 + x2 + x3 = 5, −(1/ )x2 − (1/ )x3 = −5/ , −(1/ )x2 − (1/ )x3 = −5/ .

(10.13)

En este punto est´ claro que no podemos proceder ya que la segunda y la tercera ecuaci´n en a o (10.13) son ahora id´nticas; no tenemos m´s que tres ecuaciones independientes. El pr´ximo e a o paso de eliminaci´n ser´ transformar la tercera ecuaci´n en (4.13) en la tautolog´ 0 = 0. o ıa o ıa Afortunadamente, hay una soluci´n simple: intercambiar el orden de las ecuaciones antes o de realizar la eliminaci´n. Cambiando las ecuaciones primera y segunda en (10.11), o x1 + x2 = 3, x 1 + x2 + x3 = 5 , x1 + x3 = 4 . El primer paso de la eliminaci´n hacia adelante nos da las ecuaciones o x1 + x2 = 3, (1 − )x2 + x3 = 5 − 3 , −x2 + x3 = 4 − 3 .

(10.14)

(10.15)

El redondeo elimina los t´rminos proporcionales a , dando e x1 + x2 = 3, x2 + x3 = 5 , −x2 + x3 = 1 .

(10.16)

El segundo paso de eliminaci´n hacia adelante elimina x2 de la tercera ecuaci´n en (10.16) o o usando la segunda ecuaci´n, o x1 + x2 x2 + = 3, x3 = 5 , 2x3 = 6 .

(10.17)

Se puede comprobar f´cilmente que la sustituci´n hacia atr´s da x1 = 1, x2 = 2, y x3 = 3, la a o a cual es la respuesta correcta en el l´ ımite → 0. Los algoritmos que reordenan las ecuaciones cuando ellas sit´an elementos peque˜os en la u n diagonal son llamados pivotes. A menudo si todos los elementos de una matriz son inicialmente de una magnitud comparable, el procedimiento de eliminaci´n hacia adelante podr´ producir o ıa peque˜os elementos sobre la diagonal principal. El precio de pivotear es s´lo un par de l´ n o ıneas extras en el programa, pero es esencial usar pivoteo para todas, no s´lo para las matrices m´s o a peque˜as. A´n con el pivoteo, no podemos garantizar estar a salvo de problemas de redondeo n u si se trata de matrices muy grandes.

10.1. SISTEMAS DE ECUACIONES LINEALES.

275

10.1.4.

Determinantes.

Es f´cil obtener el determinante de una matriz usando la eliminaci´n Gaussiana. Despu´s a o e de completar la eliminaci´n hacia adelante, uno simplemente calcula el producto de los coeo ficientes de los elementos diagonales. Tomamos nuestro ejemplo original, ecuaci´n (10.8). La o matriz es   1 1 1 ˇ (10.18) A = −1 2 0 . 2 0 1 Completada la eliminaci´n hacia adelante, ecuaci´n (10.10), el producto de los coeficientes de o o los elementos diagonales es (1)(3)(− 1 ) = −1, el cual, usted puede comprobar, es el determi3 ˇ nante de A. Este m´todo es sut´ e ılmente m´s complicado cuando se usa el pivoteo. Si el n´mero a u de pivoteos es impar, el determinante es el producto negativo de los coeficientes de los elementos de la diagonal. Ahora deber´ ser obvio que la regla de Cramer es computacionalmente ıa una manera ineficiente para resolver el conjunto de ecuaciones lineales.

10.1.5.

Eliminaci´n Gaussiana en Octave. o

No necesitamos escribir un programa en Octave para realizar la eliminaci´n Gaussiana o con pivoteo. En vez de esto nosotros podemos usar las capacidades de manipulaci´n de o matrices que viene con Octave. En Octave, la eliminaci´n Gaussiana es una rutina primitiva, o tal como las funciones seno o ra´ cuadrada. Como con cualquier rutina “enlatada”, usted ız deber´ entender, en general, como trabaja y reconocer posibles problemas, especialmente los ıa computacionales (e.g., ¿poner sqrt(-1) retorna un n´mero imaginario o un error?). u Octave implementa la eliminaci´n de Gauss usando los operadores slash / y backslash \. o ˇ El sistema de ecuaciones lineales x A = b donde x y b son vectores fila, se resuelve usando ˇ El sistema de ecuaciones lineales A x = b donde x y b son ˇ el operador slash como x = b/A. ˇ vectores columna, se resuelve usando el operador backslash como x = b\A. Como un ejemplo, tomemos la ecuaci´n (10.11) con = 0, escrito en forma matricial o      5 0 1 1 x1 1 1 0 x2  = 3 (10.19) 4 1 0 1 x3 Usando Octave en forma interactiva la soluci´n es ilustrada a continuaci´n: o o octave> octave> octave> octave> 1 2 3 A=[0 1 1; 1 1 0; 1 0 1]; b=[5;3;4]; x=A\b; disp(x);

Claramente, Octave usa pivoteo en este caso. Los operadores slash y backslash pueden ser usados de la misma manera en programas. El comando en Octave para el determinante de una matriz es det(A).

276

CAP´ ITULO 10. RESOLVIENDO SISTEMAS DE ECUACIONES.

10.1.6.

Eliminaci´n Gaussiana con C++ de objetos matriciales. o

El uso de arreglos multidimensionales en C++ no es del todo comodo. Las maneras usuales de declarar un arreglo de M × N de n´meros con punto flotante en doble precisi´n son: u o const int M=3, N=3; double A[M][N] ; para asignaci´n est´tica de memoria y o a int M, N . . . // Se fijan valores a M y N double * * A = new double * [M] ; // asignacion de un vector de punteros for(int i=0;i<M;i++) { A[i] = new double [N] ; // asignacion de memoria para cada fila } para un reserva din´mica (no olvide desasignar cada fila con un delete[]). Una asignaci´n a o est´tica es simple pero r´ a ıgida, ya que las dimensiones son constantes fijas. Cuando el arreglo est´tico es pasado a una funci´n, esta funci´n deber´ declarar alg´n arreglo con el mismo a o o ıa u n´mero de columnas de acuerdo al arreglo a ser indexado apropiadamente. Una asignaci´n u o din´mica es flexible pero es dif´ de manejar, aunque los detalles pueden ser escondidos a ıcil dentro de funciones separadas. Accesar elementos fuera de los contornos del arreglo es un error de programaci´n com´n (bug) el cual es dif´ de rastrear con arreglos din´micos. o u ıcil a C++ nos permite corregir estas deficiencias creando nuestros propios tipos de variables. Estas variables definidas por el usuario son llamadas clases de objetos. De aqu´ en adelante ı usaremos la clase Matrix para declarar arreglos de una o dos dimensiones de n´meros de punto u flotante. Esta clase est´ enteramente declarada dentro del archivo de cabecera Matrix.h e a implementada dentro de Matrix.cc. Algunos ejemplos de declaraci´n de objetos de Matrix o son int M=3, N=2 ; Matrix A(M,N), b(N), x(3) ; Aunque esto se parece a una asignaci´n de arreglo est´tico, note que las dimensiones no son o a constantes fijas. Tanto vectores unidimensionales como matrices bidimensionales pueden ser declarados; las anteriores son tratadas como matrices de una sola columna. Los valores en estas variables pueden ser fijados por la declaraci´n de asignamiento o A(0,0)=0; A(1,0)=1; A(2,0)=1; b(1)=5; A(0,1)=1; A(1,1)=1; A(2,1)=0; b(2)=3; A(0,2)=1; A(1,2)=0; A(2,2)=1; b(3)=4.

El formato para el objeto Matrix es A(i, j) en vez de A[i][j], para distinguirlos de los arreglos C++ convencionales. Un objeto Matrix conoce sus dimensiones, y usted puede obtenerlas usando las funciones miembros nRow() y nCol(). Por ejemplo:

10.1. SISTEMAS DE ECUACIONES LINEALES.

277

ˇ Entradas: A, b. ˇ Salidas: x, det A. Fija el factor de escala, si = maxj (| Ai,j |) para cada fila. Itera sobre las filas k = 1, . . . , (N − 1). • Selecciona la columna a pivotear a partir de maxj (| Ai,j |)/si . • Realiza pivoteos usando la lista de ´ ındice de columnas. • Realiza la eliminaci´n hacia adelante. o ˇ Calcula el determinante det A, como producto de los elementos de la diagonal. Realiza la sustituci´n hacia atr´s. o a

Cuadro 10.1: Bosquejo de la funci´n ge, la cual resuelve un sistema de ecuaciones lineales o ˇ ˇ x = b por eliminaci´n Gaussiana. La funci´n tambi´n devuelve el determinante de A. A o o e int m = A.nRow(), n = A.nCol() ; asigna m y n a las dimensiones de A. La verificaci´n de los contornos se realiza cada vez que o un objeto Matrix es indexado. Las l´ ıneas Matrix newA(3, 7) ; newA(4,5) = 0; // Una matriz no cuadrada de 3 por 7 // Fuera de los limites

produce el mensage de error: Indice de fila fuera de los limites cuando el programa es corrido. Esto significa que al menos uno de los ´ ındices i no satisface la condici´n 0 < i ≤ N . o Los objetos Matrix autom´ticamente liberan la memoria que les fue asignada cuando ellos a exceden su alcance (scope), por lo tanto no es necesario invocar delete. Para asignar todos los elementos de un objeto Matrix a un valor dado usamos la funci´n o miembro set(double x ), por ejemplo A.set(1.0). Una matriz entera puede ser asignada a otra del mismo tama˜o (e.g., Matrix C(3,3); C=A;). Sin embargo, a diferencia de las matrin ces de Octave, operaciones aritm´ticas como 2*A no est´n a´n implementadas. Operaciones e a u de este tipo deber´ ser llevadas a cabo elemento por elemento, t´ ıan ıpicamente usando ciclos for. La rutina de eliminaci´n Gaussiana ge, la cual usa los objetos tipo Matrix, es descrita o en la tabla 10.1. Declarando y asignando la matriz A y los vectores b y x como arriba, un programa puede llamar esta rutina como double determ = ge(A, b, x) ; // Eliminacion Gaussiana cout << x(1) << ", " << x(2) << ", " << x(3) << endl ; cout << "Determinante = " << determ << endl ; ˇ ˇ para resolver el sistema lineal A x = b y calcular el determinante de A.

278

CAP´ ITULO 10. RESOLVIENDO SISTEMAS DE ECUACIONES.

10.2.
10.2.1.

Matriz inversa.
Matriz inversa y eliminaci´n Gaussiana. o

En la secci´n previa hemos revisado c´mo resolver un conjunto de ecuaciones simult´neas o o a por eliminaci´n de Gauss. Sin embargo, si usted est´ familiarizado con el ´lgebra lineal, o a a probablemente podr´ escribir la soluci´n de ıa o ˇ Ax = b , como ˇ x = A−1 b , (10.21) ˇ ˇ donde A−1 es la matriz inversa de A. No nos deber´ sorprender que el c´lculo de la matriz ıa a inversa est´ relacionada al algoritmo para resolver un conjunto de ecuaciones lineales. Usuale mente la inversa de una matriz es calculada por aplicaciones repetidas de eliminaciones de Gauss (o una variante de descomposici´n llamada LU). o La inversa de una matriz est´ definida por la ecuaci´n a o ˇ ˇ ˇ A A−1 = I , ˇ donde I es la matriz identidad  1 0 ˇ  I = 0  . . .  ... . . .  . . . .  .. . (10.22) (10.20)

0 1 0 . . .

0 0 1 . . .

(10.23)

Definiendo los vectores columna   1 0   e1 = 0 , ˆ   . . .

  0 1   e2 = 0 , ˆ   . . .

... ,

  . . .   eN = 0 , ˆ 0 1

(10.24)

podr´ ıamos escribir la matriz identidad como una vector fila de los vectores columna ˇ ˆ ˆ ˆ I = e1 e2 . . . eN Si resolvemos el conjunto de ecuaciones lineales, ˇ A x1 = e1 . ˆ (10.26) . (10.25)

ˇ El vector soluci´n x1 es la primera columna de la inversa A−1 . Si procedemos de esta manera o ˇ con los otros e calcularemos todas las columnas de A−1 . En otras palabras, nuestra ecuaci´n ˆ o −1 ˇˇ ˇ para la matriz inversa AA = I es resuelta escribi´ndola como e ˇ ˆ ˆ ˆ ˆ ˆ ˆ A x1 x2 . . . xN = e1 e2 . . . eN . (10.27)

10.2. MATRIZ INVERSA.

279

ˇ Entradas: A. ˇ ˇ Salidas: A−1 , det A. Matriz ˇ es inicializada a la matriz identidad. b Fija el factor de escala, si = maxj (| Ai,j |) para cada fila. Itera sobre las filas k = 1, . . . , (N − 1). • Selecciona la columna a pivotear a partir de maxj (| Ai,j |)/si . • Realiza pivoteos usando la lista de ´ ındice de columnas. • Realiza la eliminaci´n hacia adelante. o ˇ Calcula el determinante detA, como producto de los elementos de la diagonal. Realiza la sustituci´n hacia atr´s. o a

Cuadro 10.2: Bosquejo de la funci´n inv, la cual calcula el inverso de una matriz y su o determinante. ˇ Despu´s de calcular los x, construimos A−1 como e (x1 )1  (x1 )2  = .  . .  (x2 )1 (x2 )2 . . .  . . . (xN )1 . . . (xN )2   .  .. .  . . . . . (xN )N

ˇ ˆ ˆ ˆ A−1 x1 x2 . . . xN

(10.28)

(x1 )N (x2 )N donde(xi )j es el elemento j de xi .

o La tabla 10.2 muestra la funci´n inv para calcular la inversa de una matriz. En Octave, inv(A) es una funci´n internamente construida que regresa a la matriz inversa de A . Es o posible resolver un sistema de ecuaciones lineales usando la matriz inversa, pero hacer esto es usualmente sobrepasarse. Una excepci´n podr´ ser el caso donde deseamos resolver un o ıa ˇ n´mero de problemas similares en el cual la matriz A es fija pero el vector b toma muchos u valores diferentes. Finalmente, aqu´ hay una f´rmula manual para tener presente: la inversa ı o de una matriz 2 × 2 es ˇ A−1 = 1 a22 −a12 a11 a22 − a12 a21 −a21 a11

.

(10.29)

Para matrices mayores las f´rmulas r´pidamente llegan a ser muy desordenadas. o a

280

CAP´ ITULO 10. RESOLVIENDO SISTEMAS DE ECUACIONES.

10.2.2.

Matrices singulares y patol´gicas. o

Antes que regresemos a la F´ ısica, discutamos otro posible riesgo en resolver sistemas de ecuaciones lineales. Consideremos las ecuaciones x1 + x2 = 1 . 2x1 + 2x2 = 2 (10.30)

Note que realmente no tenemos dos ecuaciones independientes, ya que la segunda es s´lo el o doble de la primera. Estas ecuaciones no tienen una soluci´n unica. Si tratamos de hacer una o ´ eliminaci´n hacia adelante, obtenemos o x1 + x2 = 1 , 0 = 0 y no se puede hacer nada m´s. a Otra manera de mirar este problema es ver que la matriz 1 1 ˇ A= 2 2 (10.32) (10.31)

no tiene inversa. Una matriz sin inversa se dice que es singular. Una matriz singular tambi´n tiene un determinante nulo. Las matrices singulares no siempre son evidentes. ¿Podr´ e ıa adivinar si esta matriz   1 2 3 4 5 6 7 8 9 es singular? Aqu´ est´ lo que pasa en Octave cuando tratamos de resolver (10.30) ı a octave:1> A=[1 1; 2 2]; octave:2> b=[1; 2]; octave:3> x=A\b; warning: matrix singular to machine precision, rcond = 0 Dependiendo de su compilador, la rutina inv de C++ probablemente retorne infinito o arroje un mensage de error. En algunos casos la rutina calcula una inversa para una matriz singular, pero naturalmente la respuesta es espuria. Algunas veces la matriz no es singular pero est´ tan cerca de serlo que los errores de a redondeo podr´ “empujarla al abismo”. Un ejemplo trivial ser´ ıan ıa 1+ 2 1 2 , (10.33)

donde es un n´mero muy peque˜o. A una matriz se le dice patol´gica cuando est´ muy u n o a cerca de ser singular. ˇ Si usted sospecha que est´ tratrando con una matriz patol´gica cuando resuelve Ax = b, a o ˇ entonces calcule el error absoluto, Ax − b / b para comprobar si x es una soluci´n precisa. o

10.2. MATRIZ INVERSA.

281

Formalmente, la condici´n num´rica est´ definida como la “distancia” normalizada entre o e a una matriz y la matriz singular m´s cercana5 . Hay una variedad de maneras para definir a la distancia, dependiendo del tipo de norma usada. La funci´n de Octave cond(A) regresa o la condici´n num´rica de una matriz A. Una matriz con una gran condici´n num´rica es o e o e patol´gica. Un peque˜o determinante puede algunas veces advertirnos que la matriz podr´ o n ıa ser patol´gica, pero la condici´n num´rica es el criterio real.6 o o e

10.2.3.

Osciladores arm´nicos acoplados. o

En el comienzo de este cap´ ıtulo, discutimos el problema de encontrar los estados estacionarios de ecuaciones diferenciales ordinarias. Un ejemplo can´nico de un sistema con o interacciones lineales es el caso de osciladores arm´nicos acoplados. Consideremos el sistema o mostrado en la figura 10.1; las constantes de resorte son k1 , . . . , k4 . La posici´n de los bloo ques, relativas a la pared izquierda, son x1 , x2 y x3 . La distancia entre las paredes es LP , y las longitudes naturales de los resortes son L1 , . . . , L4 . Los bloques son de ancho despreciable.

Lp

x1

x2

Figura 10.1: Sistema de bloques acoplados por resortes anclados entre paredes. La ecuaci´n de movimiento para el bloque i es o dxi dvi 1 = vi , = Fi , (10.34) dt dt mi donde Fi es la fuerza neta sobre el bloque i. En el estado estacionario, las velocidades vi , son nulas y las fuerzas netas, Fi son cero. Esto es justo el caso de equilibrio est´tico. Nuestro a trabajo ahora es encontrar las posiciones en reposo de las masas. Expl´ ıcitamente las fuerzas netas son F1 = −k1 (x1 − L1 ) + k2 (x2 − x1 − L2 ) F2 = −k2 (x2 − x1 − L2 ) + k3 (x3 − x2 − L3 ) (10.35) F3 = −k3 (x3 − x2 − L3 ) + k4 (Lp − x3 − L4 ) o en forma matricial,        F1 −k1 − k2 k2 0 x1 −k1 L1 + k2 L2  . F2  =  k2 −k2 − k3 k3  x2  −  −k2 L2 + k3 L3 0 k3 k3 − k4 x3 −k3 L3 + k4 (L4 − Lp ) F3
5 6

(10.36)

S. Conte and C. de Boor, Elementary Numerical Analysis (New York: McGraw-Hill, 1980). G.H. Golub and C.F. van Loan, Matrix computation 2d ed. (Baltimore Johns Hopkins University Press, 1989).

282

CAP´ ITULO 10. RESOLVIENDO SISTEMAS DE ECUACIONES.

ˇ Por conveniencia, abreviaremos la ecuaci´n de arriba como F = Kx − b. En forma matricial o las simetr´ son claras, y vemos que no ser´ dif´ extender el problema a un sistema m´s ıas ıa ıcil a grande de osciladores acoplados. En el estado de equilibrio est´tico las fuerzas netas son a ˇ iguales a cero, as´ obtenemos el resto de las posiciones de las masas resolviendo Kx − b. ı

10.3.
10.3.1.

Sistemas de ecuaciones no lineales.
M´todo de Newton en una variable. e

Ahora que sabemos c´mo resolver sistemas de ecuaciones lineales, procederemos al caso o m´s general (y m´s desafiante) de resolver sistemas de ecuaciones no lineales. Este problema a a es dif´ tanto que consideraremos primero el caso de una variable. Deseamos resolver para ıcil, x∗ tal que f (x∗ ) = 0 . (10.37) donde f (x∗ ) es ahora una funci´n general. Hay un n´mero de m´todos disponibles para o u e encontrar raices en una variable. Quiz´s usted conozca algunos m´todos como el de bisecci´n a e o o de la secante u otros algoritmos. Tambi´n hay algoritmos especializados para cuando f (x) e es un polinomio (e.g., funci´n de roots en Octave). En vez de utilizar todos estos esquemas, o nos concentraremos en el m´s simple y util de los m´todos para el caso general de N variables. a ´ e 7 a o ız El m´todo de Newton est´ basado en la expansi´n de Taylor de f (x) entorno a la ra´ e x∗ . Supongamos que hacemos una estimaci´n acerca de la localizaci´n de la ra´ llamamos o o ız; a esta estimaci´n x1 . Nuestro error podr´ ser escrito como δx = x1 − x∗ o x∗ = x1 − δx. o ıa Escribiendo la expansi´n de Taylor de f (x∗ ), o f (x∗ ) = f (x1 − δx) = f (x1 ) − δx df (x1 ) + O(δx2 ) . dx (10.38)

Note que si x∗ es una ra´ f (x∗ ) = 0, as´ podemos resolver para δx ız, ı δx = f (x1 ) + O(δx2 ) . f (x1 ) (10.39)

Despreciamos el t´rmino O(δx2 ) (este ser´ nuestro error de truncamiento) y usamos la exe a presi´n resultante de δx para corregir nuestra estimaci´n inicial. La nueva estimaci´n es o o o x2 = x1 − δx = x1 − Este procedimiento podr´ ser iterado como ıa xn+1 = xn − f (xn ) , f (xn ) (10.41) f (x1 ) . f (x1 ) (10.40)

para mejorar nuestra estimaci´n hasta obtener la precisi´n deseada. o o El procedimiento iterativo descrito m´s arriba puede entenderse mejor gr´ficamente (figua a ra 10.2). Note que en cada paso usamos la derivada de f (x) para dibujar la l´ ınea tangente a
7

F.S. Acton, Numerical Methods that Work (New York: Harper&Row, 1970).

10.3. SISTEMAS DE ECUACIONES NO LINEALES.

283

f(x)

x2 x1 x3

x*

x

Figura 10.2: Representaci´n gr´fica del m´todo de Newton. o a e

la funci´n. Donde esta l´ o ınea tangente intersecta el eje x es nuestra siguiente estimaci´n de la o ra´ Efectivamente, estamos linealizando f (x) y resolviendo el problema lineal. Si la funci´n ız. o es bien comportada, pronto ser´ aproximadamente lineal en alguna vecindad cerca de la ra´ a ız ∗ x. Unas pocas notas acerca del m´todo de Newton: primero, cuando converge, encuentra una e ra´ muy r´pidamente; pero, desafortunadamente, algunas veces diverge (e.g., f (xn ) ≈ 0) y ız a falla. Para funciones bien comportadas, este m´todo es garantizado que converger si estamos e suficientemente cerca de la ra´ Por esta raz´n algunas veces est´ combinada con un algoritmo ız. o a m´s lento pero que asegura encontrar la ra´ tal como la bisecci´n. Segundo, si hay varias a ız, o raices, la ra´ a la cual el m´todo converge depende de la estimaci´n inicial (que podr´ no ız e o ıa ser la ra´ deseada). Hay procedimientos (e.g., “deflation”) para encontrar m´ltiples raices ız u usando el m´todo de Newton. Finalmente, el m´todo es m´s lento cuando se encuentran e e a raices tangentes, tales como para f (x) = x2 .

10.3.2.

M´todo de Newton multivariable. e

No es dif´ generalizar el m´todo de Newton a problemas de N variables. Ahora nuestra ıcil e inc´gnita x = [x1 , x2 , . . . , xN ] es un vector fila, y deseamos encontrar los ceros (raices) de o la funci´n vector fila o f (x) = [f1 (x) , f2 (x) , . . . , fN (x)] . (10.42) De nuevo, hacemos una estimaci´n inicial para ubicar la ra´ llamamos a esta estimaci´n x1 . o ız, o ∗ ∗ Nuestro error podr´ ser esrito como δx = x1 − x o x = x1 − δx. Usando la expansi´n de ıa o Taylor de f (x1 ), ˇ f (x ∗ ) = f (x1 − δx) = f (x1 ) − δx D(x1 ) + O(δx 2 ) , ˇ donde D es el Jacobiano, definido como Dij (x) = ∂fj (x) . ∂xi (10.44) (10.43)

284

CAP´ ITULO 10. RESOLVIENDO SISTEMAS DE ECUACIONES.

Ya que x ∗ es la ra´ f (x ∗ ) = 0, como antes podr´ ız, ıamos resolverla para δx. Despreciando el t´rmino de error, podemos escribir la ecuaci´n (10.43) como e o ˇ f (x1 ) = δx D(x1 ) , o ˇ δx = f (x1 ) D−1 (x1 ) . Nuestra nueva estimaci´n es o ˇ x2 = x1 − δx = x1 − f (x1 ) D−1 (x1 ) . (10.47) (10.46) (10.45)

Este procedimiento puede ser iterado para mejorar nuestra estimaci´n hasta que sea obtenida o ˇ la precisi´n deseada. Ya que D cambia en cada iteraci´n, podr´ ser desgastador calcular su o o ıa inversa. En cambio, usamos la eliminaci´n Gaussiana sobre la ecuaci´n (10.45) para resolver o o para δx, y calcular la nueva estimaci´n como x2 = x1 − δx. o

10.3.3.

Programa del m´todo de Newton. e

Para demostrar el m´todo de Newton, lo usaremos para calcular estados estacionarios del e modelo de Lorenz. A principios de la d´cada de 1960 el meteor´logo del MIT, Ed Lorenz, encontr´ que el clima e o o es intr´ ınsecamente impredecible, no por su complejidad, sino por la naturaleza no lineal de las ecuaciones que lo gobiernan. Lorenz formul´ un modelo simple del clima global, reduciendo el o ´ problema a un sistema de ecuaciones diferenciales ordinarias de 12 variables. El observ´ que o este sistema ten´ un comportamiento aperi´dico y que era extremadamente sensible a las ıa o condiciones iniciales. Estudiemos un modelo de Lorenz simplificado a tres variables dx = σ(y − x) , dt dy = rx − y − xz , dt dz = xy − bz , dt

(10.48)

donde σ, r y b son contantes positivas. Estas ecuaciones simples fueron originalmente desarrolladas como un modelo para un fluido con convecci´n. La variable x mide la raz´n o o de convecci´n, y y z miden los gradientes de temperaturas horizontales y verticales. Los o par´metros σ y b dependen de las propiedades del fluido y de la geometr´ del contenedor; a ıa com´nmente, los valores σ = 10 y b = 8/3 son usados. El par´metro r es proporcional al u a gradiente de temperatura aplicado. Un programa que encuentra las raices de este sistema de ecuaciones usando el m´todo e de Newton, al que llamamos newtn, es esbozado en la tabla 10.3. Este programa llama la funci´n fnewt (tabla 10.4), la cual, dado un x = [x , y , z] regresa o     σ(y − x) −σ σ 0 ˇ f = rx − y − xz  , D = r − z −1 −x . (10.49) xy − bz y x −b

10.3. SISTEMAS DE ECUACIONES NO LINEALES.

285

Conjunto inicial de estimaciones x1 y par´metros λk . a Itera sobre el n´mero de pasos deseados. u ˇ • Eval´a la funci´n f (xn ; λk ) y su Jacobiano D. u o • Encuentra δx por la eliminaci´n Gaussiana [ver (10.45)]. o • Actualiza la estimaci´n para la ra´ usando xn+1 = xn − δx. o ız Imprime la estimaci´n final de la ra´ o ız.

Cuadro 10.3: Descripci´n del programa newtn, el cual encuentra una ra´ para un conjunto o ız de ecuaciones. √ √ Para r = 28, σ = 10 y b = 8/3, las tres ra´ ıces son [x, y, z] = [0, 0, 0], [6 2, 6 2, 27] y √ √ [−6 2, −6 2, 27]. Un√ ejemplo de la salida de newtn est´ dada m´s abajo; note que el programa obtiene la a a √ ra´ [6 2, 6 2, 27]. ız octave:1> newtn newtn is the file: ~/cursos/MFM1.apuntes2/programas/newtn.m newtn - Programa para resolver un sistema de ecuaciones no lineales usando el metodo de Newton. Las ecuaciones estan definidas en fnewt Entre la estimacion inicial (vector columna): [50; 50; 50] Entre los parametros a: [28 10 8/3] Despues de 10 iteraciones la raiz es 8.4853 8.4853 27.0000 Otras condiciones iniciales convergen a otras raices. Por ejemplo, comenzando por√ 2, 2], [2, √ convergemos a la ra´ [0, 0, 0]; si comenzamos en [5, 5, 5], converge a [−6 2, −6 2, 27]. ız Comenzando por el punto [4, 4, 15], el m´todo converge a una ra´ s´lo despu´s de hacer e ız o e una excursi´n incre´ o ıblemente distante del origen.

10.3.4.

Continuaci´n. o

La primera dificultad con el m´todo de Newton es la necesidad de dar una buena estimae ci´n inicial para la ra´ A menudo nuestro problema es de la forma o ız. f (x ∗ ; λ) = 0 , (10.50)

donde λ es alg´n par´metro en el problema. Supongamos que conocemos una ra´ x0 para el u a ız ∗ valor λ0 pero necesitamos encontrar una ra´ para un valor diferente de λa . Intuitivamente, ız ∗ ∗ si λa ≈ λ0 , entonces x0 deber´ ser una buena estimaci´n inicial para encontrar xa usando ıa o

286

CAP´ ITULO 10. RESOLVIENDO SISTEMAS DE ECUACIONES.

Entradas: x = [x, y, z], λ = [r, σ, b]. ˇ Salidas: f , D. Eval´a f por el modelo de Lorenz [(10.49)]. u ˇ Eval´a el Jacobiano D para el modelo de Lorenz. u

Cuadro 10.4: Descripci´n de la funci´n fnewt, la cual es usada por newtn para encontrar los o o estados estables de la ecuaci´n de Lorenz. o el m´todo de Newton. Pero si λa ≈ λ0 , ¿hay alguna manera para hacer uso de nuestra ra´ e ız conocida? La respuesta es s´ y la t´cnica es conocida como continuaci´n. La idea es acercarse poco ı e o a poco a λa definiendo la siguiente secuencia de λ : λi = λ0 + (λa − λ0 ) i , N (10.51)

∗ ∗ para i = 1, . . . . . . ., N . Usando el m´todo de Newton, resolvemos f (x1 ; λ1 ) = 0 con x0 e como la estimaci´n inicial. Si N es suficientemente grande, entonces λ1 ≈ λ0 y el m´todo o e ∗ podr´ converger r´pidamente. Luego usamos x1 como una estimaci´n inicial para resolver ıa a o ∗ f (x2 ; λ2 ) = 0; la secuencia contin´a hasta alcanzar nuestro valor deseado en λa . La t´cnica u e de continuaci´n tiene un beneficio adicional que podemos usar cuando estamos interesados o en conocer no s´lo una ra´ simple, sino conocer como x ∗ var´ con λ. o ız ıa

10.4. LISTADOS DEL PROGRAMA.

287

10.4.
10.4.1.

Listados del programa.
Definici´n de la clase Matrix. o

// // Clase de Matrices doubles // #ifndef _Matrix_h #define _Matrix_h #include <iostream> #include <string> class Matrix { private: int nFilP ; int nColP ; int dimP ; double * dataP ; void copy(const Matrix &) ; public: Matrix() ; Matrix( int, int = 1, double = 0.0e0) ; Matrix( const Matrix &) ; ~Matrix() ; Matrix & operator = (const Matrix &) ; double & operator () (int, int =0) ; int nRow () const; int nCol () const ; void set(double) ; double maximoF(int) const ; void pivot(int,int) ; void multi(double, int, int ) ; }; ostream & operator << (ostream &, Matrix ); void error ( int, string="Error") ; Matrix operator * (Matrix, Matrix) ; Matrix operator + (Matrix, Matrix) ; Matrix operator - (Matrix, Matrix) ; #endif

288

CAP´ ITULO 10. RESOLVIENDO SISTEMAS DE ECUACIONES.

10.4.2.

Implementaci´n de la clase Matrix. o

// // Implementacion de la clase Matrix #include "Matrix.h" #include <cassert> #include <cstdlib> // Funcion privada de copia void Matrix::copy(const Matrix & mat) { nFilP=mat.nFilP ; nColP=mat.nColP ; dimP = mat.dimP ; dataP = new double[dimP] ; for(int i =0 ; i< dimP; i++) dataP[i]=mat.dataP[i] ; } // Constructor default Crea una matriz de 1 por 1 fijando su valor a cero Matrix::Matrix() { Matrix(1) ; } // Constructor normal Crea una // y fija sus valores a cero o Matrix::Matrix(int nF, int nC, error(nF>0 && nC >0, "Una de nFilP= nF ; nColP = nC ; dimP = nFilP*nColP ; dataP = new double[dimP] ; assert(dataP != 0) ; for (int i=0; i < dimP; i++) } matriz de N por M a un valor ingresado double v) { las dimensiones no es positiva" ) ;

// Habia memoria para reservar dataP[i]=v ;

// Constructor de copia Matrix::Matrix( const Matrix & mat) { this->copy(mat) ; // this permite acceder a la misma vartiable como un todo // *this representa la variable, y this un puntero a ella // -> nos permite elegir miembros de la clase pero cuando tenemos el puntero // a la variable y no su valor } // Destructor

10.4. LISTADOS DEL PROGRAMA.

289

Matrix::~Matrix() { delete [] dataP ; }

// Libera la memoria

// Operador Asignacion, sobrecarga del = para que funcione con Matrix Matrix & Matrix::operator= (const Matrix & mat) { if( this == &mat ) return *this ; // Si ambos lados son iguales no hace nada delete [] dataP ; // borra la data del lado izquierdo this-> copy(mat) ; return * this ; } // Funciones simples que retornan el numero de filas y de columnas // el const al final indica que no modifican ningun miembro de la clasa int Matrix::nRow() const {return nFilP; } int Matrix::nCol() const {return nColP;} // operador Parentesis // Permite accesar los valores de una matriz via el par (i,j) // Ejemplo a(1,1)=2*b(2,3) // Si no se especifica la columna la toma igual a 0 double & Matrix::operator() (int indF, int indC) { error(indF>-1 && indF< nFilP, "Indice de fila fuera de los limites") ; error(indC>-1 && indC<nColP, "Indice de columna fuera de los limites" ) ; return dataP[indC+nColP*indF] ; } void Matrix::set(double value) { for(int i=0; i<dimP; i++) dataP[i]=value ; } double Matrix::maximoF(int indF) const { error(indF>-1 && indF< nFilP, "Indice de fila fuera en maximoF") ; double max= dataP[nColP*indF]; for(int i=nColP*indF; i<nColP*(indF+1); i++ ) { max = (max > fabs(dataP[i]) ) ? max : fabs(dataP[i]) ; } return max ; } void Matrix::pivot(int indF1, int indF2) { error(indF1>-1 && indF1< nFilP, "Primer indice de fila fuera en Pivot") ; error(indF2>-1 && indF2< nFilP, "Segundo indice de fila fuera en Pivot") ;

290

CAP´ ITULO 10. RESOLVIENDO SISTEMAS DE ECUACIONES.

if(indF1==indF2) return ; double paso ; int ind1, ind2 ; for (int i = 0; i < nColP; i++ ) { ind1 = nColP*indF1+i ; ind2 = nColP*indF2+i ; paso = dataP[ind1] ; dataP[ind1] = dataP[ind2] ; dataP[ind2] = paso ; } } void Matrix::multi(double fact, int indF1, int indF2 ) { int ind1, ind2 ; for (int i = 0; i < nColP; i++ ) { ind1 = nColP*indF1+i ; ind2 = nColP*indF2+i ; dataP[ind2] += fact*dataP[ind1] ; } } // // IOSTREAM << // ostream & operator << (ostream & os, Matrix mat ) { for(int indF=0; indF < mat.nRow(); indF++) { os << "| " ; for(int indC=0; indC<mat.nCol(); indC++) { os << mat(indF,indC) << " "; } os << "|"<<endl ; } return os ; } void error ( int i, string s) { if(i) return ; cout << s<<"\a" <<endl ; exit(-1); } Matrix operator * (Matrix A , Matrix B) { int nColA = A.nCol() ; int nColB = B.nCol() ; int nFilA = A.nRow() ;

10.4. LISTADOS DEL PROGRAMA. int nFilB = B.nRow() ; error(nColA == nFilB, "No se pueden multiplicar por sus dimensiones") ; Matrix R(nFilA , nColB ) ; for (int indF = 0; indF<nFilB; indF++){ for (int indC=0; indC<nColA; indC++){ double sum = 0.0 ; for (int k=0; k < nColA; k++ ) sum += A(indF, k) * B(k, indC) ; R(indF, indC) = sum ; } } return R ; }

291

Matrix operator + (Matrix A , Matrix B) { int nColA = A.nCol() ; int nColB = B.nCol() ; int nFilA = A.nRow() ; int nFilB = B.nRow() ; error(nFilA == nFilB && nColA== nColB, "tienen dimensiones distintas") ; Matrix R(nFilA , nColA ) ; for (int indF = 0; indF<nFilB; indF++){ for (int indC=0; indC<nColA; indC++){ R(indF, indC) = A( indF, indC) + B(indF, indC); } } return R ; } Matrix operator - (Matrix A , Matrix B) { int nColA = A.nCol() ; int nColB = B.nCol() ; int nFilA = A.nRow() ; int nFilB = B.nRow() ; error(nFilA == nFilB && nColA== nColB, "tienen dimensiones distintas") ; Matrix R(nFilA , nColA ) ; for (int indF = 0; indF<nFilB; indF++){ for (int indC=0; indC<nColA; indC++){ R(indF, indC) = A( indF, indC) - B(indF, indC); } } return R ; }

292

CAP´ ITULO 10. RESOLVIENDO SISTEMAS DE ECUACIONES.

10.4.3.

Funci´n de eliminaci´n Gaussiana ge. o o

// // Eliminacion Gaussiana. // #include "NumMeth.h" #include "Matrix.h" double ge( Matrix A, Matrix { int nFil = A.nRow() ; int nCol = A.nCol() ; Matrix si (nFil) ; b, Matrix & x)

for ( int indF= 0; indF < nFil ; indF++) si(indF)= A.maximoF(indF) ; double determinante=1.0e0 ; for (int indC= 0; indC< nCol-1; indC++) { // pivoteo double max = A(indC,indC)/si(indC) ; int indicePivot = indC ; for (int i = indC+1; i < nCol ; i++){ if( A(i, indC)/si(i) > max ) { max = A(i,indC)/si(i) ; indicePivot = i ; } } if(indicePivot != indC) { A.pivot(indC, indicePivot) ; b.pivot(indC, indicePivot) ; determinante *= -1.0e0 ; } double Ad= A(indC,indC) ; for (int indF=indC+1; indF< nFil; indF++ ) { double factor = - A(indF, indC)/Ad ; A.multi(factor, indC, indF); b.multi(factor, indC, indF); } } for (int indF= nFil-1; indF >=0; indF--) { double sum =0.0e0 ; for (int i = indF+1; i < nCol; i++) sum += A(indF, i)*x(i) ; x(indF) = b(indF)/A(indF, indF) - sum /A(indF, indF); } double determ = 1.0e0 ;

10.4. LISTADOS DEL PROGRAMA. for (int i = 0; i < nCol; i++) determ *= A(i,i) ; return determinante*determ } ;

293

10.4.4.

Funci´n para inversi´n de matrices inv. o o

// // Invierte una matriz // #include "NumMeth.h" #include "Matrix.h" double inv( Matrix A, Matrix & invA) { int nFil = A.nRow() ; int nCol = A.nCol() ; error(nFil==nCol, "Matriz no es cuadrada"); Matrix e(nFil) ; Matrix x(nFil) ; double deter = 0.0e0 ; invA.set(0.0e0) ; for(int indC=0; indC < nCol; indC++) { e.set(0.0e0) ; e(indC) = 1.0e0; deter = ge( A, e, x) ; error(fabs(deter)>1.0e-10, " Determinante Singular" ); for (int indF=0; indF< nFil; indF++) invA(indF, indC) = x(indF) ; } return deter ; }

10.4.5.

Programa newtn en Octave.

% newtn - Programa para resolver un sistema de ecuaciones no lineales % usando el metodo de Newton. Las ecuaciones estan definidas en fnewt suppress_verbose_help_message=1; clear all; help newtn; x0=input(’Entre la estimacion inicial (vector columna): ’); x=x0; a=input(’Entre los parametros a: ’); nStep =10;

294 for iStep=1:nStep

CAP´ ITULO 10. RESOLVIENDO SISTEMAS DE ECUACIONES.

[f D] = fnewt(x,a) ; dx=D\f ; x=x-dx; end fprintf(’Despues de %g iteraciones la raiz es \n’, nStep); disp(x’); Funci´n fnewt en Octave. o function [f,D] = fnewt(x,a) f(1)=a(2)*(x(2)-x(1)); f(2)= a(1)*x(1)-x(2)-x(1)*x(3); f(3)=x(1)*x(2)-a(3)*x(3) ; D(1,1)=-a(2); D(2,1)=a(1)-x(3); D(3,1)=x(2); D(1,2)=a(2); D(2,2)=-1; D(3,2)=x(1); D(1,3)=0; D(2,3)=-x(1); D(3,3)=-a(3); return

10.4. LISTADOS DEL PROGRAMA.

295

10.4.6.

Programa newtn en c++.

#include <iostream> #include "NumMeth.h" #include "Matrix.h" void fnewt( Matrix & f, Matrix & D, Matrix xN, Matrix lambda ) { double r= lambda(0) ; double s= lambda(1) ; double b=lambda(2) ; double x=xN(0) ; double y=xN(1) ; double z=xN(2) ; f(0) = s*(y-x) ; f(1) = r*x-y-x*z ; f(2) = x*y-b*z ; D(0,0) = -s ; D(1,0) = r-z ; D(2,0) = y ; D(0,1) = s ; D(1,1)= -1.0e0 ; D(2,1) = x ; D(0,2)=0.0e0 ; D(1,2)= -x ; D(2,2) =-b ; } double ge( Matrix A, Matrix { int nFil = A.nRow() ; int nCol = A.nCol() ; Matrix si (nFil) ; b, Matrix & x)

for ( int indF= 0; indF < nFil ; indF++) si(indF)= A.maximoF(indF) ; double determinante=1.0e0 ; for (int indC= 0; indC< nCol-1; indC++) { // pivoteo double max = A(indC,indC)/si(indC) ; int indicePivot = indC ; for (int i = indC+1; i < nCol ; i++){ if( A(i, indC)/si(i) > max ) { max = A(i,indC)/si(i) ; indicePivot = i ; }

296

CAP´ ITULO 10. RESOLVIENDO SISTEMAS DE ECUACIONES. } if(indicePivot != indC) { A.pivot(indC, indicePivot) ; b.pivot(indC, indicePivot) ; determinante *= -1.0e0 ; } double Ad= A(indC,indC) ; for (int indF=indC+1; indF< nFil; indF++ ) { double factor = - A(indF, indC)/Ad ; A.multi(factor, indC, indF); b.multi(factor, indC, indF); }

} for (int indF= nFil-1; indF >=0; indF--) { double sum =0.0e0 ; for (int i = indF+1; i < nCol; i++) sum += A(indF, i)*x(i) ; x(indF) = b(indF)/A(indF, indF) - sum /A(indF, indF); } double determ = 1.0e0 ; for (int i = 0; i < nCol; i++) determ *= A(i,i) ; return determinante*determ } ;

int main() { Matrix D(3,3) ; Matrix f(3) ; Matrix lambda(3), xN(3), xNp1(3), dx(3) ; cout <<"Ingrese r , Sigma, b : " ; cin >> lambda(0) >> lambda(1) >> lambda(2) ; cout << "Ingrese estimacion inicial : " ; cin>> xN(0) >> xN(1) >> xN(2) ; int iteraciones ; cout << "Ingrese numero de iteraciones : " ; cin >> iteraciones ; for (int itera = 0; itera < iteraciones; itera ++ ) { f.set(0.0e0) ; D.set(0.0e0) ; dx.set(0.0e0) ; fnewt(f, D, xN, lambda ) ;

10.4. LISTADOS DEL PROGRAMA. ge(D, f, dx) ; xNp1=xN-dx ; xN=xNp1 ; cout << xN(0)<< " " << xN(1) << " " << xN(2) << endl ; } cout << xN <<endl ; return 0; }

297

298

CAP´ ITULO 10. RESOLVIENDO SISTEMAS DE ECUACIONES.

Cap´ ıtulo 11 An´lisis de datos. a
versi´n 3.0, 02 de Diciembre 20031 o

A menudo se destaca que los sistemas f´ ısicos simulados sobre un computador son similares al trabajo experimental. La raz´n de esta analog´ es hecha ya que la simulaci´n computacioo ıa o nal produce datos en muchas maneras similares a los experimentos de laboratorio. Sabemos que en el trabajo experimental uno a menudo necesita analizar los resultados y esto es lo mismo que con la simulaci´n num´rica. Este cap´ o e ıtulo cubre parcialmente algunos t´picos en o el an´lisis de datos. a

11.1.
11.1.1.

Ajuste de curvas.
El calentamiento global.

En el presente, parece que predicciones sobre el tiempo de largo alcance y precisas nunca se llevar´n a cabo. La raz´n es a causa de las ecuaciones gobernantes que son altamente a o no lineales y sus soluciones son extremadamente sensibles a las condiciones iniciales (ver el modelo de Lorenz). Por otra parte, las predicciones generales acerca del clima terrestre son ´ posibles. Se pueden predecir si habr´ o no condiciones de sequ´ en Africa en los pr´ximos a ıa o a˜os, aunque no la cantidad de precipitaciones de un d´ en particular. n ıa El calentamiento global es un importante t´pico actualmente debatido en los foros de ino vestigaci´n sobre clima. El calentamiento es culpa de los gases de invernadero, tal como es el o di´xido de carbono en la atm´sfera. Estos gases calientan la Tierra porque son transparentes o o a la radiaci´n de onda corta que llega desde el Sol, pero opacas a la radiaci´n infrarroja desde o o la tierra. Cient´ ıficos y legisladores todav´ est´n debatiendo la amenaza del calentamiento ıa a global. Sin embargo, nadie se pregunta qu´ concentraciones de gases invernadero est´n en e a aumento. Espec´ ıficamente, los niveles de di´xido de carbono han estado firmemente aumeno tados desde la revoluci´n industrial. La figura 11.1 muestra el aumento en la concentraci´n o o de di´xido de carbono durante los a˜os ochenta, medidos en Mauna Loa, Hawai. o n El estudio del calentamiento global ha producido una vasta cantidad de datos, tanto mediciones pr´cticas, como datos de las simulaciones computacionales. En este cap´ a ıtulo estudiaremos algunas t´cnicas b´sicas para analizar y reducir tales conjuntos de datos. Por e a ejemplo, para los datos mostrados en la figura 11.1, ¿cu´l es la raz´n estimada de crecimiento a o
Este cap´ ıtulo est´ basado en el quinto cap´ a ıtulo del libro: Numerical Methods for Physics, second edition de Alejandro L. Garcia, editorial Prentice Hall.
1

299

300

´ CAP´ ITULO 11. ANALISIS DE DATOS.

355

CO2 (ppm)

350

345

340

335

1982

1984 Año

1986

1988

1990

Figura 11.1: Di´xido de carbono (en partes por mill´n) medida en Mauna Loa, Hawai desde o o 1981 a 1990. Barra de error estimada es σ0 = 0.16 [p.p.m.] .

de la concentraci´n de CO2 por a˜o?. Esta es la primera pregunta que motiva nuestro estudio o n de ajustes de curvas.

11.1.2.

Teor´ general. ıa

El tipo m´s simple de an´lisis de datos es ajustar una curva. Suponga que tenemos un a a conjunto de datos de N puntos (xi , yi ). Deseamos ajustar estos datos a una funci´n Y (x; {aj }), o donde {aj } es un conjunto de M par´metros ajustables. Nuestro objetivo es encontrar los a valores de esos par´metros, para los cuales la funci´n ajusta mejor los datos. Intuitivamente, a o esperamos que si nuestro ajuste de la curva es bueno, un gr´fico del conjunto de datos (xi , yi ) a y la funci´n Y (x; {aj }) mostrar´n la curva pasando cerca de los puntos (ver figura 11.2). o a Podemos cuantificar esta sentencia midiendo la distancia entre un punto y la curva. ∆i = Y (xi ; {aj }) − yi . (11.1)

Nuestro criterio de ajuste para la curva ser´ que la suma de los cuadrados de los errores a sea un m´ ınimo; esto es, necesitamos encontrar {aj } que minimice la funci´n o
N N

D({aj }) =
i=1

∆2 i

=
i=1

[Y (xi ; {aj}) − yi ]2 .

(11.2)

11.1. AJUSTE DE CURVAS.

301

yi ∆i

σi

Y(x;{aj })

xi
Figura 11.2: Ajuste de datos a una curva.

Esta t´cnica nos dar´ el ajuste de los cuadrados m´nimos; esta no es la unica manera de e a ı ´ obtener un ajuste de la curva, pero es la m´s com´n. El m´todo de los m´ a u e ınimos cuadrados fue el primero usado por Gauss para determinar las ´rbitas de los cometas a partir de los o datos observados. A menudo, nuestros datos tienen una barra de error estimada (o intervalo de seguridad), el cual escribimos como yi ± σi . En este caso podr´ ıamos modificar nuestro criterio de ajuste tanto como para dar un peso menor a los puntos con m´s error. En este esp´ a ıritu definimos
N

χ ({aj }) =
i=1

2

∆i σi

2

N

=
i=1

[Y (xi ; {aj }) − yi ]2 . 2 σi

(11.3)

La funci´n chi-cuadrado es la funci´n de ajuste m´s com´nmente usada, porque si los errores o o a u son distribuidos gaussianamente, podemos hacer sentencias estad´ ısticas concernientes a la virtud del ajuste. Antes de continuar, debemos destacar que discutiremos brevemente la validaci´n de la o curva de ajuste. Usted puede ajustar cualquier curva para cualquier conjunto de datos, pero esto no significa que los resultados sean significativos. Para establecer un significado tenemos que preguntarnos lo siguiente: ¿cu´l es la probabilidad de que los datos, dado el error a experimental asociado con cada uno de los puntos, sean descritos por la curva?. Desafortunadamente, las hip´tesis de prueba ocupan una porci´n significativa de un curso estad´ o o ıstico y est´n fuera de los objetivos de este libro.2 a

11.1.3.

Regresi´n lineal. o

Primero consideremos ajustar el conjunto de datos con una l´ ınea recta, Y (x; {a1 , a2 }) = a1 + a2 x .
2

(11.4)

W. Mendenhall, R.L. Scheaffer, and D.D. Wackerly, Mathematical Statistics with Applications (Boston: Duxbury Press, 1981).

302

´ CAP´ ITULO 11. ANALISIS DE DATOS.

Este tipo de ajuste de curva es tambi´n conocido como regresi´n lineal. Deseamos determinar e o a1 y a2 tal que N 1 χ2 (a1 , a2 ) = (a1 + a2 xi − yi )2 , (11.5) 2 σi i=1 es minimizada. El m´ ınimo es encontrado diferenciando (11.5) y ajustando la derivada a cero: ∂χ2 =2 ∂a1 ∂χ =2 ∂a2 o a1 S + a2 Σx − Σy = 0 a1 Σx + a2 Σx2 − Σxy = 0 , donde
N 2 N

i=1 N

1 (a1 + a2 xi − yi ) = 0 , 2 σi 1 (a1 + a2 xi − yi ) xi = 0 , 2 σi

(11.6)

(11.7)

i=1

(11.8) (11.9)

S≡
i=1 N

1 , 2 σi

N

Σx ≡
i=1 N

xi , 2 σi

N

Σy ≡
i=1 N

yi , 2 σi

(11.10)

Σx2 ≡
i=1

x2 i , 2 σi

Σy 2 ≡
i=1

2 yi , 2 σi

Σxy ≡
i=1

xi yi . 2 σi

Puesto que las sumas pueden ser calculadas directamente de los datos, ellas son constantes conocidas. De este modo tenemos un conjunto lineal de dos ecuaciones simult´neas en las a inc´gnitas a1 y a2 . Estas ecuaciones son f´ciles de resolver: o a a1 = ΣyΣx2 − ΣxΣxy , SΣx2 − (Σx)2 a2 = SΣxy − ΣxΣy . SΣx2 − (Σx)2 (11.11)

Note que si σi es una constante, esto es, si el error es el mismo para todos los datos, los σ se a cancelan en las ecuaciones (11.11). En este caso, los par´metros, a1 y a2 , son independientes de la barra de error. Es com´n que un conjunto de datos no incluya las barras de error u asociadas. Todav´ podr´ ıa ıamos usar las ecuaciones (11.11) para ajustar los datos si tenemos que los σi son constantes (σi =1 siendo la elecci´n m´s simple). o a Lo siguiente es obtener una barra de error asociado, σaj , para el par´metro aj de la curva a 3 de ajuste. Usando la ley de la propagaci´n de errores, o
N 2 σaj = i=1
3

∂aj ∂yi

2 σi ,

(11.12)

P. Bevington, Data Reduction an Error Analysis for the Physical Sciences 2d ed. (New York: McGrawHill, 1992).

11.1. AJUSTE DE CURVAS. e insertando las ecuaciones (11.11), despu´s de un poco de ´lgebra obtenemos e a Σx2 , SΣx2 − (Σx)2 S . − (Σx)2

303

σa1 =

σa2 =

SΣx2

(11.13)

Note que σaj es independiente de yi . Si las barras de error de los datos son constantes (σi = σ0 ), el error en los par´metros es a σ0 σa1 = √ N donde 1 x = N
N

x2 x2 − x

2

,

σ0 σa2 = √ N

x2

1 − x

2

,

(11.14)

xi ,
i=1

x

2

1 = N

N

x2 . i
i=1

(11.15)

Finalmente, si nuestro conjunto de datos no tiene un conjunto de barras de error asociadas, podr´ ıamos estimar σ0 a partir de la diferencia muestral de los datos,
2 σ0 ≈ s2 =

1 N −2

N

[yi − (a1 + a2 xi )]2 ,
i=1

(11.16)

donde s es la desviaci´n est´ndar de la muestra. Note que esta varianza muestral est´ noro a a malizada por N − 2, puesto que hemos extra´ dos par´metros a1 y a2 , de los datos. ıdo a Muchos problemas de ajuste de curva no lineales, pueden ser transformados en problemas lineales por un simple cambio de variable. Por ejemplo, Z(x; {α, β}) = αeβx , podr´ ser reescrita como las ecuaciones (11.4) usando el cambio de variable ıa ln Z = Y , ln α = a1 , β = a2 . (11.18) (11.17)

Similarmente, para ajustar una potencia de la forma Z(t; {α, β}) = αtβ , usamos el cambio de variable ln Z = Y , ln t = x , ln α = a1 , β = a2 . (11.20) (11.19)

Estas transformaciones deber´ ser familiares debido a que se usan para graficar datos en ıan escala semi logar´ ıtmica o escalas log-log.

304

´ CAP´ ITULO 11. ANALISIS DE DATOS.

11.1.4.

Ajuste general lineal de m´ ınimos cuadrados.

El procedimiento de ajuste de m´ ınimos cuadrados es f´cil de generalizar para funciones a de la forma
M

Y (x; {aj }) = a1 Y1 (x) + a2 Y2 (x) + . . . + aM YM (x) =
j=1

aj Yj (x) .

(11.21)

Para encontrar los ´ptimos par´metros procedemos como antes encontrando el m´ o a ınimo de 2 χ, ∂χ2 ∂ = ∂aj ∂aj o
N N

i=1

1 2 σi

M

2

ak Yk (x) − yi
k=1 M

=0,

(11.22)

i=1

1 Y (xi ) 2 j σi
M

ak Yk (x) − yi
k=1 N

=0,

(11.23)

por lo tanto
N

i=1 k=1

Yj (xi )Yk (xi ) ak = 2 σi

i=1

Yj (xi )yi , 2 σi

(11.24)

para j = 1, . . . , M . Este conjunto de ecuaciones es conocida como las ecuaciones normales del problema de los m´ ınimos cuadrados. Las ecuaciones normales son m´s f´ciles de trabajar en forma matricial. Primero, definaa a ˇ como mos la matriz de dise˜o A, n   Y1 (xi )/σ1 Y2 (xi )/σ1 . . . Yj (xi )  ˇ  A = Y1 (xi )/σ2 Y2 (xi )/σ2 . . . , Aij = . (11.25) σi . . .. . . . . . Note que la matriz de dise˜o no depende de yi , los valores de datos, pero depende de xi , esto n es, sobre el dise˜o del experimento (donde las mediciones son tomadas). Usando la matriz de n dise˜o, podemos escribir (11.24) como n
N M N

Aij Aik ak =
i=1 k=1 i=1

Aij

yi , 2 σi

(11.26)

o en forma matricial, ˇ ˇ ˇ (AT A)a = AT b , (11.27) ˇ donde el vector b est´ definido como bi = yi /σi y AT es la traspuesta de la matriz de dise˜o. a n Esta ecuaci´n es f´cil de resolver para el par´metro vector a, o a a ˇ ˇ ˇ a = (AT A)−1 AT b . (11.28)

Usando este resultado y la ley de propagaci´n de errores, en la ecuaci´n (11.12), encontramos o o que el error estimado en el par´metro aj es a σaj = Cjj (11.29)

11.1. AJUSTE DE CURVAS.

305

ˇ ˇ ˇ donde C = (AT A)−1 . Una aplicaci´n com´n de esta formulaci´n general lineal de ajuste de m´ o u o ınimos cuadrados es el ajuste de los datos polinomiales, Y (x; {aj }) = a1 + a2 x + a3 x2 + . . . + aM xM −1 . (11.30)

La matriz de dise˜o tiene elementos Aij = aj xj−1 /σi , el cual es un tipo de matriz de Vandern I monde. Desafortunadamente estas matrices son notoriamente patol´gicas, por lo tanto sea o cuidadoso para M > 10.

11.1.5.

Bondades del ajuste.

Podemos f´cilmente ajustar cada punto de dato si el n´mero de par´metros, M , es igual a u a al n´mero de puntos de datos, N . En este caso ya sea que hemos construido una teor´ trivial u ıa o no hemos tomado suficientes datos. En vez de eso, supongamos el escenario m´s com´n en a u el cual N M . Porque cada dato de punto tiene un error, no esperemos que la curva pase exactamente a trav´s de los datos. Sin embargo, preguntemos, con las barras de error dadas, e ¿cuan probable es que la curva en efecto describa los datos?. Por supuesto, si no se tienen barras de error no hay nada que se pueda decir acerca de la bondad del ajuste. El sentido com´n sugiere que si el ajuste es bueno, entonces el promedio de la diferencia u deber´ ser aproximadamente igual a la barra de error, ıa | yi − Y (xi ) | ≈ σi . (11.31)

Colocando esto dentro de nuestra definici´n para χ2 , la ecuaci´n (11.3), da χ2 ≈ N . Sin o o embargo, sabemos que entre m´s par´metros usamos, m´s f´cil es ajustar la curva; el ajuste a a a a puede ser perfecto si M = N . Esto sugiere que nuestra regla pr´ctica para que un ajuste sea a bueno es χ2 ≈ N − M . (11.32) Por supuesto, este es s´lo un crudo indicador, pero es mejor que una simple ojeada a la curva. o Un an´lisis completo podr´ usar χ estad´ a ıa ıstico para asignar una probabilidad de que los datos sean ajustados por la curva. Si encontramos que χ2 N − M , entonces una de dos: no hemos usado una funci´n o apropiada, Y (x), para nuestro ajuste de curva o las barras de errores, σI , son demasiado peque˜as. Por otra parte, si χ2 n N − M , el ajuste es tan espectacularmente bueno que podemos esperar que las barras de error sean realmente demasiado grandes. Habitualmente la calidad de un ajuste se mide por el coeficiente de correlaci´n adimeno sional que es un n´mero que var´ entre 0 y 1, correspondiendo a 1 un mejor ajuste. u ıa r2 = S(a1 y − a2 xy) − ( S y 2 − ( y)2 y)2 . (11.33)

306

´ CAP´ ITULO 11. ANALISIS DE DATOS.

Cap´ ıtulo 12 Integraci´n num´rica b´sica o e a
versi´n 4.1, 4 de Diciembre del 2004 o

En este cap´ ıtulo veremos algunos m´todos b´sicos para realizar cuadraturas (evaluar e a integrales num´ricamente). e

12.1.

Definiciones
b

Consideremos la integral I=
a

f (x) dx .

(12.1)

Nuestra estrategia para estimar I es evaluar f (x) en unos cuantos puntos, y ajustar una curva simple a trav´s de estos puntos. Primero, subdividamos el intervalo [a, b] en N subintervalos. e Definamos los puntos xi como x0 = a, xN = b, x0 < x1 < x2 < · · · < xN −1 < xN . La funci´n f (x) s´lo se eval´a en estos puntos, de modo que usamos la notaci´n fi ≡ f (xi ), o o u o ver figura 12.1.

f(x)

x0=a x1

x2

xi

xN=b

Figura 12.1: Subintervalos.

307

308

´ ´ ´ CAP´ ITULO 12. INTEGRACION NUMERICA BASICA

12.2.

Regla trapezoidal

El m´todo m´s simple de cuadratura es la regla trapezoidal. Conectamos los puntos fi e a con l´ ıneas rectas, y la funci´n lineal formada por la sucesi´n de l´ o o ıneas rectas es nuestra curva aproximante. La integral de esta funci´n aproximante es f´cil de calcular, pues es la suma de o a

fi f(x) fi+1 Ti xi xi+1 x

Figura 12.2: Sucesi´n de l´ o ıneas rectas como curva aproximante.

las ´reas de trapezoides. El ´rea de un trapezoide es a a 1 Ti = (xi+1 − xi )(fi+1 + fi ) . 2 La integral es entonces calculada como la suma de las ´reas de los trapezoides: a I IT = T0 + T1 + · · · + TN −1 .

Las expresiones son m´s simples si tomamos puntos equidistantes. En este caso el espaa ciado entre cada par de puntos es b−a h= , N de modo que xi = a + ih. El ´rea de un trapezoide es entonces a 1 Ti = h(fi+1 + fi ) , 2 y la regla trapezoidal para puntos equiespaciados queda 1 1 IT (h) = hf0 + hf1 + hf2 + · · · + hfN −1 + hfN 2 2 N −1 1 = h(f0 + fN ) + h fi 2 i=1

(12.2)

´ 12.3. INTERPOLACION CON DATOS EQUIDISTANTES.

309

12.3.

Interpolaci´n con datos equidistantes. o

Para el caso de puntos xi = a + ih que est´n igualmente espaciados podemos plantear a un formalismo m´s general. Primero que todo, ajustemos un polinomio de grado N a un a conjunto de N + 1 datos xi , fi , no necesariamente equidistantes, de la forma: PN (x) = b0 + b1 (x − x0 ) + · · · + bN (x − x0 )(x − x1 ) · · · (x − xN −1 ) . Determinemos los coeficientes usando los datos: b0 = f0 = f (x0 ) f1 − f0 ≡ f [x1 , x0 ] b1 = x1 − x0 f2 − f1 f1 − f0 f [x2 , x1 ] − f [x1 , x0 ] b2 = − /(x2 − x0 ) = ≡ f [x2 , x1 , x0 ] x2 − x1 x1 − x0 x2 − x0 . . . bN = f [xN , xN −1 , xN −2 , . . . , x1 , x0 ] , donde hemos usado la definici´n recurrente o f [xN , xN −1 , xN −2 , . . . , x1 , x0 ] ≡ f [xN , xN −1 , xN −2 , . . . , x1 ] − f [xN −1 , xN −2 , . . . , x1 , x0 ] . xN − x0 (12.3)

La expresi´n anterior es conocida como la n-´sima diferencia dividida finita. Usando estas o e definiciones podemos escribir el polinomio de interpolaci´n (12.3) de la siguiente manera: o PN (x) = f0 + f [x1 , x0 ](x − x0 ) + f [x2 , x1 , x0 ](x − x1 )(x − x0 ) + · · · +f [xN , xN −1 , xN −2 , . . . , x1 , x0 ](x − x0 )(x − x1 ) · · · (x − xN −1 ) , Este polinomio es conocido como el polinomio de interpolaci´n por diferencias divididas de o Newton. Analicemos estos f [. . .] para el caso equiespaciado, f [x1 , x0 ] = El segundo f2 − f1 f1 − f0 − f (x2 ) − 2f (x1 ) + f (x0 ) ∆2 f0 x − x1 x1 − x0 f [x2 , x1 , x0 ] = 2 = . = x2 − x0 2h2 2!h2 En general tenemos (puede probarse por inducci´n) que o ∆n f0 . n!hn Luego podemos escribir la llamada f´rmula hacia adelante de Newton-Gregory, definiendo o α = (x − x0 )/h de la siguiente manera f [xN , xN −1 , xN −2 , . . . , x1 , x0 ] = fN (x) = f (x0 ) + ∆f (x0 )α + ∆n f (x0 ) ∆2 f (x0 ) α(α − 1) + · · · + α(α − 1) · · · (α − n + 1) + RN , 2! n! (12.4) f1 − f0 ∆f0 = . x1 − x0 1!h

310

´ ´ ´ CAP´ ITULO 12. INTEGRACION NUMERICA BASICA

el error de truncamiento viene dado por RN = para alg´n ξ ∈ [a, b]. u f (n+1) (ξ) n+1 h α(α − 1)(α − 2) · · · (α − n) , (n + 1)!

12.4.

Reglas de cuadratura

La integral (12.1) puede ser evaluada separ´ndola en una suma de integrales sobre pea que˜os intervalos que contengan dos o tres puntos, luego usando el polinomio de interpolaci´n n o adecuado para el n´mero de puntos escogidos podemos evaluar aproximadamente cada inteu gral. Para terminar el proceso debemos sumar todas las integrales parciales. Usemos s´lo dos o puntos, y entre esos dos puntos aproximamos la funci´n por el polinomio de interpolaci´n de o o dos puntos, i.e. por una recta, figura 12.3 (a).
xi+1 xi+1

Ii (h) =
xi

f (x) dx ≈
xi

f (xi ) + ∆f (xi )

x − xi h

dx = f (xi )h +

∆f (xi ) h2 , h 2

usando que ∆f (xi ) = f (xi+1 ) − f (xi ) podemos dar una expresi´n para la integral o Ii (h) ≈ f (xi+1 ) + f (xi ) h. 2 (12.5)

f(x)

(a) f(x)

(b)

xi

xi+1

xi

xi+1

xi+2

Figura 12.3: Aproximaciones, (a) lineal, (b) cuadr´tica. a

Si consideramos intervalos que contengan tres puntos podemos usar la aproximaci´n a o segundo orden, es decir esta vez aproximamos nuestra funci´n por un polinomio de segundo o grado, figura 12.3 (b).
xi+2 xi+2

Ii (h) =
xi

f (x) dx ≈
xi

f (xi ) + ∆f (xi )

(x − xi ) ∆2 f (xi ) (x − xi ) (x − xi − h) + h 2 h h

dx ,

12.4. REGLAS DE CUADRATURA integrando obtenemos Ii (h) ≈ 2hf (xi ) + ∆f (xi ) 4h2 ∆2 f (xi ) + h 2 2h2 8h3 4h3 − 3 2 ,

311

usando la expresi´n para ∆f (xi ) = f (xi+1 )−f (xi ) y para ∆2 f (xi ) = f (xi+2 )−2f (xi+1 )+f (xi ) o tenemos h (12.6) Ii (h) ≈ (f (xi ) + 4f (xi+1 ) + f (xi+2 )) . 3 Se puede continuar encontrando expresiones usando aproximaciones de orden mayor, sin embargo, las f´rmulas (12.5) y (12.6) son, sin duda, las m´s usadas. o a A continuaci´n, para evaluar la integral finita (12.1) debemos sumar las integrales paro ciales para ambos casos. Partamos sumando (12.5)
b N −1 xi+1 N −1

I=
a

f (x) dx =
i=0 xi

f (x) dx ≈
i=0

f (xi+1 ) − f (xi ) h ≡ IT (h) , 2

haciendo la suma tenemos h IT (h) = [f (a) + f (b)] + h 2
N −1

f (xi ) ,
i=1

regla trapezoidal.

(12.7)

Ahora evaluemos la integral finita, (12.1), usando la descomposici´n en integrales de tres o puntos ecuaci´n (12.6) o
b N −2 xi+2 N −2

I=
a

f (x) dx =
i=0 xi

f (x) dx ≈
i=0

h [f (xi ) + 4f (xi+1 ) + f (xi+2 )] ≡ Is (h) , 3

haciendo la suma tenemos Is (h) = 2h f (a) f (b) + 2f (x1 ) + f (x2 ) + 2f (x3 ) + f (x4 ) + 2f (x5 ) + . . . + 3 2 2 . (12.8)

La cual es conocida como la regla de Simpson. Notemos que se necesita un n´mero impar de u puntos equiespaciados para aplicar esta regla. Se puede estimar el error cometido en cada caso integrando el t´rmino (12.3) que correse ponde al error de truncamiento de la expansi´n. Evaluemos el error para el caso trapezoidal o en que cortamos la expansi´n a primer orden, por lo tanto el error corresponde o
xi+1 T (h)

=
xi

d2 f (ξ) h2 (x − xi ) (x − xi − h) dx , dx2 2! h h

haciendo el cambio de variable u = x − xi tenemos
T (h)

=

1 d2 f (ξ) 2 dx2

h

u(u − h) du =
0

h3 h3 − 3 2

1 d2 f (ξ) h3 d2 f (ξ) =− 2 dx2 12 dx2

312

´ ´ ´ CAP´ ITULO 12. INTEGRACION NUMERICA BASICA

este es el error en cada integral entre xi y xi+1 , para obtener el error total en la integral entre a y b tenemos que multiplicar por el n´mero de intervalos (N ), u I − IT (h) = N
T (h) = −N

h3 d2 f (ξ) (b − a)h2 d2 f (ξ) h2 =− = − (f (b) − f (a)) . 12 dx2 12 dx2 12

La expresi´n para el error en el m´todo trapezoidal nos queda o e I − IT (h) = − 1 2 h [f (b) − f (a)] + O(h4 ) . 12 (12.9)

Vemos que el error es proporcional a h2 , y que la regla trapezoidal tendr´ problemas cuando a b√ la derivada diverge en los extremos del intervalo. Por ejemplo, la integral 0 x dx es problem´tica. En el caso de la integral de Simpson se puede probar que el error es proporcional a a h4 . Como ejemplo, consideremos la funci´n error o 2 erf(x) = √ π
x 0

e−y dy .

2

(12.10)

Para x = 1, erf(1) 0.842701. La regla trapezoidal con N = 5 da 0.83837, que es correcto en los dos primeros decimales. La regla de Simpson, con los mismos 5 puntos, da 0.84274, con cuatro decimales correctos . Por supuesto, el integrando en este ejemplo es muy suave y bien comportado lo cual asegura que los m´todos funcionaran bien. e

12.5.

Integraci´n de Romberg o

Una pregunta usual es cu´ntas subdivisiones del intervalo realizar. Un modo de decidir es a repetir el c´lculo con un intervalo m´s peque˜o. Si la respuesta no cambia apreciablemente, a a n la aceptamos como correcta (sin embargo, esto no evita que podamos ser enga˜ados por funn ciones patol´gicas o escenarios inusuales). Con la regla trapezoidal, si el n´mero de paneles es o u una potencia de dos, podemos dividir el tama˜o del intervalo por dos sin tener que recalcular n todos los puntos. Definamos la secuencia de tama˜os de intervalo, n 1 1 h1 = (b − a) , h2 = (b − a) , . . . , hn = n−1 (b − a) . 2 2 Para n = 1 s´lo hay un panel, luego o 1 1 IT (h1 ) = (b − a)[f (a) + f (b)] = h1 [f (a) + f (b)] . 2 2 Para n = 2 se a˜ade un punto interior, luego n 1 IT (h2 ) = h2 [f (a) + f (b)] + h2 f (a + h2 ) 2 1 = IT (h1 ) + h2 f (a + h2 ) . 2 (12.11)

´ 12.5. INTEGRACION DE ROMBERG Hay una f´rmula recursiva para calcular IT (hn ) usando IT (hn−1 ): o 1 IT (hn ) = IT (hn−1 ) + hn 2
2n−2

313

f [a + (2i − 1)hn ] .
i=1

(12.12)

El segundo t´rmino del lado derecho da la contribuci´n de los puntos interiores que se han e o agregado cuando el tama˜o del intervalo es reducido a la mitad. n Usando el m´todo recursivo descrito, podemos agregar paneles hasta que la respuesta e parezca converger. Sin embargo, podemos mejorar notablemente este proceso usando un m´todo llamado integraci´n de Romberg. Primero veamos la mec´nica, y despu´s explicaremos e o a e por qu´ funciona. El m´todo calcula los elementos de una matriz triangular: e e R1,1 – – – R2,1 R2,2 – – R=R – 3,1 R3,2 R3,3 . . . .. . . . . . . . La primera columna es simplemente la regla trapezoidal recursiva: Ri,1 = IT (hi ) . (12.14)

(12.13)

Las sucesivas columnas a la derecha se calculan usando la f´rmula de extrapolaci´n de Rio o chardson: 1 [Ri+1,j − Ri,j ] . (12.15) Ri+1,j+1 = Ri+1,j + j 4 −1 La estimaci´n m´s precisa para la integral es el elemento RN,N . o a El programa romberg.cc calcula la integral erf(1) usando el m´todo de Romberg. Con e N = 3, se obtiene la tabla 0.771743 0 0 0.825263 0.843103 0 0.838368 0.842736 0.842712 R3,3 da el resultado exacto con 4 decimales, usando los mismos 4 paneles que antes usamos con la regla trapezoidal (y que ahora reobtenemos en el elemento R3,1 ). Es util que el programa entregue toda la tabla y no s´lo el ultimo t´rmino, para tener ´ o ´ e una estimaci´n del error. Como en otros contextos, usar una tabla demasiado grande puede o no ser conveniente pues errores de redondeo pueden comenzar a degradar la respuesta. Para entender por qu´ el esquema de Romberg funciona, consideremos el error para la e regla trapezoidal, ET (hn ) = I − IT (hn ). Usando (12.9), ET (hn ) = − Como hn+1 = hn /2, ET (hn+1 ) = − 1 2 hn [f (b) − f (a)] + O(h4 ) . n 48 1 2 h [f (b) − f (a)] + O(h4 ) . n 12 n

314

´ ´ ´ CAP´ ITULO 12. INTEGRACION NUMERICA BASICA

Consideremos ahora la segunda columna de la tabla de Romberg. El error de truncamiento para Rn+1,2 es: 1 I − Rn+1,2 = I − IT (hn+1 ) + [IT (hn+1 ) − IT (hn )] 3 1 = ET (hn+1 ) + [ET (hn+1 ) − ET (hn )] 3 1 1 1 1 =− + − h2 [f (b) − f (a)] + O(h4 ) n n 48 3 48 12 = O(h4 ) n Notemos c´mo el t´rmino h2 se cancela, dejando un error de truncamiento de orden h4 . La o e n n siguiente columna (la tercera) de la tabla de Romberg cancela este t´rmino, y as´ sucesivae ı mente.

12.6.

Cuadratura de Gauss.

Consideremos el problema de cuadratura sin considerar puntos fijos equidistantes, sino que pensamos en hacer una elecci´n adecuada de puntos y pesos para cada punto, tal que o nuestra integral pueda aproximarse como:
b

f (x) dx ≈ w1 f (x1 ) + . . . + wN f (xn ) ,
a

(12.16)

aqu´ los xi son un conjunto de puntos elegidos de manera inteligente tal que disminuyan el ı error y los wi son sus pesos respectivos, no necesariamente iguales unos con otros.

f(x)

(a) f(x)

(b)

Figura 12.4: (a) Ilustraci´n de la regla trapezoidal que une los dos puntos extremos por una o recta. (B) Estimaci´n mejorada al elegir inteligentemente los puntos. o

El nombre que reciben esta clase de t´cnicas es Cuadratura de Gauss, la m´s com´n de e a u ellas es la conocida como de Gauss-Legendre, y es util para un intervalo finito, el cual es ´ mapeado mediante un cambio de variables al intervalo [−1, 1]. Existen otras cuadraturas ∞ como la de Gauss-Laguerre ´ptima para integrales de la forma 0 e−x f (x) dx. o

12.6. CUADRATURA DE GAUSS. ±xi wi ±xi wi

315

N=2 0.57735 02692 1.00000 00000 N=3 0.00000 00000 0.88888 88889 0.77459 66692 0.55555 55556 N=4 0.33998 10436 0.65214 51549 0.86113 63116 0.34785 48451 N=5 0.00000 00000 0.56888 88889 0.53846 93101 0.47862 86705 0.90617 98459 0.23692 68850

N=8 0.18343 46425 0.36268 37834 0.52553 24099 0.31370 66459 0.79666 64774 0.22238 10345 0.96028 98565 0.10122 85363 N=12 0.12523 34085 0.24914 70458 0.36783 14990 0.23349 25365 0.58731 79543 0.20316 74267 0.76990 26742 0.16007 83285 0.90411 72564 0.10693 93260 0.98156 06342 0.04717 53364

Cuadro 12.1: Puntos y pesos para integraci´n de Gauss-Legendre. o

Para evaluar (12.1), debemos mapear el intervalo [a, b] en el intervalo [−1, 1] mediante el 1 cambio de variable x = 1 (b + a) + 2 (b − a)z, qued´ndonos a 2
b a

b−a f (x) dx = 2

1

f (z) dz ,
−1

(12.17)

esta ultima integral puede ser evaluada usando diferentes conjuntos de puntos y pesos, ´
1

f (z) dz ≈ w1 f (x1 ) + . . . + wN f (xn ) .
−1

(12.18)

En la tabla 12.1 presentamos los conjuntos con N = 2, 3, 4, 8 y 12 puntos. Los puntos xi corresponden a los ceros del Polinomio de Legendre PN de grado N y los pesos vienen dados por 2 wi = 1 = 1, 2, . . . , N 2 (1 − xi )[(d/dx)PN (xi )]2 Como ejemplo, consideremos la funci´n error o 2 erf(x) = √ π para x = 1, es decir,
1 x 0

e−y dy ,

2

(12.19)

erf(1) =
0

2 2 √ e−y dy . π
1 2

(12.20) +
z 2

1 Haciendo el cambio de variable sugerido y = 2 (b + a) + 1 (b − a)z = 2 integral queda 1

y dy = dz/2, la

erf(1)

0.842701 =
−1

1 2 √ e−(1+z) /4 dz = π

1

g(z) dz .
−1

(12.21)

316

´ ´ ´ CAP´ ITULO 12. INTEGRACION NUMERICA BASICA

Evaluemos con el conjunto de dos puntos
1

erf(1) =
−1

g(z) dz

g(−0.57735 02692) + g(+0.57735 02692) = 0.84244189252125179 , (12.22)

tres decimales correctos. Ahora con el conjunto de tres puntos,
1

erf(1) =
−1

g(z) dz

0.55555 55556 × g(−0.77459 66692) + 0.88888 88889 × g(0.00000 00000) + 0.55555 55556 × g(+0.77459 66692) = 0.84269001852936587 , (12.23)

tres decimales correctos. Finalmente con el conjunto de cuatro puntos
1

erf(1) =
−1

g(z) dz

0.34785 48451 × g(−0.86113 63116) + 0.65214 51549 × g(−0.33998 10436) + 0.65214 51549 10436 × g(+0.33998 10436) + 0.34785 48451 × g(+0.86113 63116) = 0.84270117131761124 , (12.24)

los seis decimales correctos.

12.7.

Bibliograf´ ıa

Numerical Methods for Physics, second edition de Alejandro L. Garcia, editorial Prentice Hall. M´todos Num´ricos Aplicados en Ingenier´a de Jean-Marie Ledanois, Aura L´pez de e e ı o Ramos, Jos´ Antonio Pimentel M. y Filipo F. Pironti Lubrano, editorial Mc Graw e Hill. M´todos Num´ricos para Ingenieros Steven C. Chapra y Raymond P. Canale, editorial e e Mc Graw Hill.

12.8. LISTADOS DEL PROGRAMA.

317

12.8.
12.8.1.

Listados del programa.
trapecio.cc

#include "NumMeth.h" double integrando(double); int main(){ double a=0, b=1,x; int N; double h; double I, suma=0; cout << "Regla trapezoidal para erf(1)" << endl; cout << "Numero de puntos: " ; cin >> N; h = (b-a)/(N-1); for (int i=2;i<N;i++){ x = a+(i-1)*h; suma+=integrando(x); } I = h*((integrando(a)+integrando(b))/2.0 + suma); cout << "Valor aproximado: erf(1) ~= " << I << endl; cout << "Valor exacto: erf(1) = 0.842701" << endl; } double integrando(double x){ return (2.0/sqrt(M_PI))*exp(-x*x); }

12.8.2.

romberg.cc

#include "NumMeth.h" #include <iomanip.h> double integrando(double); int main(){ double a=0, b=1,x; int N,np; double h; double I, suma=0; cout << "Integracion de Romberg para erf(1)" << endl;

318

´ ´ ´ CAP´ ITULO 12. INTEGRACION NUMERICA BASICA

cout << "Dimension de tabla: " ; cin >> N; double ** R = new double * [N]; for (int i=0;i<N;i++){ R[i] = new double[N]; } for (int i=0;i<N;i++){ for (int j=0;j<N;j++){ R[i][j] = 0 ; } } // // // // // // for (int i=0;i<N;i++){ for (int j=0;j<N;j++){ cout << R[i][j] << " "; } cout << endl; }

h = (b-a); // Ancho del intervalo np = 1; // Numero de paneles for (int i=0;i<N;i++,h/=2,np*=2){ if (i==0){ R[0][0] = h*(integrando(a)+integrando(b))/2.0; } else { suma = 0; for (int j=1;j<=np-1;j+=2){ x = a+j*h; suma += integrando(x); } R[i][0] = R[i-1][0]/2.0 + h*suma; } } int m = 1; for (int j=1;j<N;j++){ m *= 4; for (int i=j;i<N;i++){ R[i][j] = R[i][j-1] + (R[i][j-1]-R[i-1][j-1])/(m-1); } }

12.8. LISTADOS DEL PROGRAMA. cout << "Tabla R" << endl << endl; for (int i=0;i<N;i++){ for (int j=0;j<N;j++){ cout << /*setprecision(6) << */ setw(8) << } cout << endl; }

319

R[i][j] << " ";

cout << endl; cout << "Valor aproximado: erf(1) ~= " << R[N-1][N-1] << endl; cout << "Valor exacto: erf(1) = 0.842701" << endl; for (int i=0;i<N;i++){ delete [] R[i]; } delete [] R; } double integrando(double x){ return (2.0/sqrt(M_PI))*exp(-x*x); }

320

´ ´ ´ CAP´ ITULO 12. INTEGRACION NUMERICA BASICA

Parte III Ap´ndices. e

321

Ap´ndice A e Transferencia a diskettes.
La filosof´ de diferentes unidades (A:, B:,. . . ) difiere de la estructura unica del sistema ıa ´ de archivos que existe en unix. Son varias las alternativas que existen para la transferencia de informaci´n a diskette. o Una posibilidad es disponer de una m´quina win9x con ftp instalado y acceso a red. a Empleando dicha aplicaci´n se pueden intercambiar archivos entre un sistema y el otro. o Existe un conjunto de comandos llamados mtools disponible en multitud plataformas, que permiten el acceso a diskettes en formato win9x de una forma muy eficiente. mdir a: Muestra el contenido de un diskette en a:. mcopy file a: Copia el archivo file del sistema de archivos unix en un diskette en a:. mcopy a:file file Copia el archivo a:file del diskette en el sistema de archivos unix con el nombre file. mdel a:file Borra el archivo a:file del diskette. Con a: nos referimos a la primera diskettera /dev/fd0 y luego al archivo que se encuentra en el diskette. Su nombre se compone de a:filename. Si se desea emplear el caracter comod´ para un conjunto de archivos del diskette, estos deben rodearse de ın dobles comillas para evitar la actuaci´n del shell (p.e. mcopy ‘‘a:*.dat’’). La opci´n o o -t realiza la conversi´n necesaria entre unix y win9x, que se debe realizar s´lo en o o archivos de texto. Una alternativa final es montar el dispositivo /dev/fd0 en alg´n directorio, t´ u ıpicamente /floppy, considerando el tipo especial de sistema de archivos que posee vfat y luego copiar y borrar usando comandos unix. Esta forma suele estar restringida s´lo a root, o el comando: mount -t vfat /dev/fd0 /floppy no puede ser dado por un usuario. Sin embargo, el sistema aceptar´ el comando a mount /floppy de parte del usuario. Una vez terminado el trabajo con el floppy ´ste e debe ser desmontado, antes de sacarlo, mediante el comando: umount /floppy.

323

324

´ APENDICE A. TRANSFERENCIA A DISKETTES.

Ap´ndice B e Las shells csh y tcsh.
Son dos de los Shells interactivos m´s empleados. Una de las principales ventajas de tcsh a es que permite la edici´n de la l´ o ınea de comandos, y el acceso a la historia de ´rdenes usando o las teclas de cursores.1

B.1.

Comandos propios.

Los comandos propios o intr´ ınsecos, Built-In Commands, son aqu´llos que proporciona el e propio shell 2 . alias name def Asigna el nombre name al comando def. history Muestra las ultimas ´rdenes introducidas en el shell. Algunos comandos relacionados con el ´ o Command history son: !! Repite la ultima orden. ´ !n Repite la orden n-´sima. e !string Repite la orden m´s reciente que empiece por la cadena string. a !?string Repite la orden m´s reciente que contenga la cadena string. a str1∧ str2 o !!:s/str1/str2/ (substitute) Repite la ultima orden reemplanzando la primera ocurrencia de la cadena ´ str1 por la cadena str2.
bash tambi´n lo permite. e A diferencia de los comandos que provienen de un ejecutable situado en alguno de los directorios de la variable PATH.
2 1

325

326 !!:gs/str1/str2/

´ APENDICE B. LAS SHELLS CSH Y TCSH.

(global substitute) Repite la ultima orden reemplazando todas las ocurrencias de la ´ cadena str1 por la cadena str2. !$ Es el ultimo argumento de la orden anterior que se haya tecleado. ´ repeat count command Repite count veces el comando command. rehash Rehace la tabla de comandos (hash table). set variable = VALUE Asigna el valor de una variable del shell. set Muestra el valor de todas las variables. setenv VARIABLE VALUE Permite asignar el valor de una variable de entorno. source file Ejecuta las ´rdenes del fichero file en el shell actual. o unset variable Borra la asignaci´n del valor de una variable del shell. o unsetenv VARIABLE VALUE Borra la asignaci´n del valor de una variable de entorno. o umask value Asigna la m´scara para los permisos por omisi´n. a o unalias name Elimina un alias asignado.

B.2.

Variables propias del shell.

Existe un conjunto de variables denominadas shell variables, que permiten modificar el funcionamiento del shell. filec (FILE Completion) Es una variable toggle que permite que el shell complete autom´ticamente el nombre de un a 3 archivo o un directorio . Para ello, si el usuario introduce s´lo unos cuantos caracteres de o un archivo y pulsa el TAB, el shell completa dicho nombre. Si s´lo existe una posibilidad, el o
3

bash permite no s´lo completar ficheros/directorios sino tambi´n comandos. o e

B.2. VARIABLES PROPIAS DEL SHELL.

327

completado es total y el shell deja un espacio tras el nombre. En caso contrario hace sonar un pitido. Pulsando Ctrl-D el shell muestra las formas existentes para completar. prompt Es una variable de cadena que contiene el texto que aparece al principio de la l´ ınea de comandos. savehist Permite definir el n´mero de ´rdenes que se desea almacenar al abandonar el shell. Esto u o permite recordar las ´rdenes que se ejecutaron en la sesi´n anterior. o o

328

´ APENDICE B. LAS SHELLS CSH Y TCSH.

Ap´ndice C e Editores tipo emacs.
Los editores tipo emacs se parecen mucho y en su mayor´ sus comandos son los mismos. ıa Para ejemplificar este tipo de editores nos centraremos en XEmacs, pero los comandos y descripciones se aplican casi por igual a todos ellos. Los editores tipo emacs constan de tres zonas: La zona de edici´n: donde aparece el texto que est´ siendo editado y que ocupa la o a mayor parte de la pantalla. La zona de informaci´n: es una barra que esta situada en la pen´ltima l´ o u ınea de la pantalla. La zona de introducci´n de datos: es la ultima l´ o ´ ınea de la pantalla. Emacs es un editor que permite la edici´n visual de un archivo (en contraste con el modo o de edici´n de vi). El texto se agrega o modifica en la zona de edici´n, usando las teclas o o disponibles en el teclado. Adem´s, existen una serie de comandos disponibles para asistir en esta tarea. a La mayor´ de los comandos de emacs se realizan empleando la tecla de CONTROL o la ıa 1 tecla META . Emplearemos la nomenclatura: C-key para indicar que la tecla key debe de ser pulsada junto con CONTROL y M-key para indicar que la tecla META debe de ser pulsada junto a key. En este ultimo caso NO es necesario pulsar simult´neamente las teclas ESC y ´ a key, pudiendo pulsarse secuencialmente ESC y luego key, sin embargo, si se usa ALT como META deben ser pulsadas simult´neamente. Observemos que en un teclado normal hay unos a 50 caracteres (letras y n´meros). Usando SHIFT se agregan otros 50. As´ usando CONTROL u ı, y META, hay unos 50 · 4 = 200 comandos disponibles. Adem´s, existen comandos especiales a llamados prefijos, que modifican el comando siguiente. Por ejemplo, C-x es un prefijo, y si C-s es un comando (de b´squeda en este caso), C-x C-s es otro (grabar archivo). As´ a trav´s u ı, e de un prefijo, se duplican el n´mero de comandos disponibles s´lo con el teclado, hasta llegar u o a unos 200 · 2 = 400 comandos en total. Aparte de estos comandos accesibles por teclas, algunos de los cuales comentaremos a continuaci´n, existen comandos que es posible ejecutar por nombre, haciendo as´ el n´mero o ı u de comandos disponibles virtualmente infinito.
1

Dado que la mayor´ de los teclados actuales no poseen la tecla META se emplea ya sea ESC o ALT. ıa

329

330

´ APENDICE C. EDITORES TIPO EMACS.

Revisemos los comandos m´s usuales, ordenados por t´pico. a o Abortar y deshacer En cualquier momento, es posible abortar la operaci´n en curso, o deshacer un comando o indeseado:

C-g C-x u

abortar deshacer

Archivos

C-x C-x C-x C-x C-x

C-f i C-s C-w C-c

cargar archivo insertar archivo grabar archivo grabar con nombre salir

Ventanas Emacs permite dividir la pantalla en varias ventanas. En cada ventana se puede editar texto e ingresar comandos independientemente. Esto es util en dos situaciones: a) si necesi´ tamos editar un solo archivo, pero necesitamos ver su contenido en dos posiciones distintas (por ejemplo, el comienzo y el final de archivos muy grandes); y b) si necesitamos editar o ver varios archivos simult´neamente. Naturalmente, aunque son independientes, s´lo es posible a o editar un archivo a la vez. A la ventana en la cual se encuentra el cursor en un momento dado le llamamos la “ventana actual”.

C-x C-x C-x C-x C-x

2 3 1 0 o

dividir ventana actual en 2 partes, con l´ ınea horizontal dividir ventana actual en 2 partes, con l´ ınea vertical s´lo 1 ventana (la ventana actual, eliminando las otras) o elimina s´lo la ventana actual o cambia el cursor a la siguiente ventana

El cambio del cursor a una ventana cualquiera se puede hacer tambi´n r´pidamente a e a trav´s del mouse. e Comandos de movimiento Algunos de estos comandos tienen dos teclas asociadas, como se indica a continuaci´n. o

331

C-b o ← C-p o ↑ C-a o Home M-< o C-Home M-f o M-→ C-v o Page Up M-g (n´mero) u

izquierda un car´cter a arriba una l´ ınea principio de la l´ ınea principio del documento avanza una palabra avanza una p´gina a salta a la l´ ınea (n´mero) u

C-f o → C-n o ↓ C-e o End M-> o C-End M-b o M-← M-v o Page Down C-l

derecha un car´cter a abajo una l´ ınea fin de la l´ ınea fin del documento retrocede una palabra retrocede una p´gina a refresca la pantalla

Comandos de inserci´n y borrado o Al ser un editor en modo visual, las modificaciones se pueden hacer en el texto sin necesidad de entrar en ning´n modo especial. u

C-d o Delete Backspace C-k

borra un car´cter despu´s del cursor a e borra un car´cter antes del cursor a borra desde la posici´n del cursor hasta el fin de l´ o ınea (no incluye el cambio de l´ ınea) M-d borra desde el cursor hacia adelante, hasta que termina una palabra M-Backspace borra desde el cursor hacia atr´s, hasta que comienza una palabra a C-o Inserta una l´ ınea en la posici´n del cursor o

May´ sculas y min´ sculas u u M-u M-l M-c Cambia a may´scula desde la posici´n del cursor hasta el fin de la palabra u o Cambia a min´scula desde la posici´n del cursor hasta el fin de la palabra u o Cambia a may´scula el car´cter en la posici´n del cursor y u a o a min´scula hasta el fin de la palabra u

Por ejemplo, veamos el efecto de cada uno de estos comandos sobre la palabra EmAcS, si el cursor est´ sobre la letra E (¡el efecto es distinto si est´ sobre cualquier otra letra!): a a M-u : EmAcS −→ EMACS M-l : EmAcS −→ emacs M-c : EmAcS −→ Emacs Transposici´n o Los siguientes comandos toman como referencia la posici´n actual del cursor. Por ejemplo, o C-t intercambia el car´cter justo antes del cursor con el car´cter justo despu´s. a a e

C-t M-t C-x C-t

Transpone dos caracteres Transpone dos palabras Transpone dos l´ ıneas

332 B´ squeda y reemplazo u

´ APENDICE C. EDITORES TIPO EMACS.

C-s C-r M- % M-&

B´squeda u B´squeda u B´squeda u B´squeda u

hacia el fin del texto hacia el inicio del texto y sustituci´n (pide confirmaci´n cada vez) o o y sustituci´n (sin confirmaci´n) o o

Definici´n de regiones y reemplazo o Uno de los conceptos importantes en emacs es el de regi´n. Para ello, necesitamos dos o conceptos auxiliares: el punto y la marca. El punto es simplemente el cursor. Espec´ ıficamente, es el punto donde comienza el cursor. As´ si el cursor se encuentra sobre la letra c en emacs, ı, el punto est´ entre la a y la c. La marca, por su parte, es una se˜al que se coloca en alg´n a n u punto del archivo con los comandos apropiados. La regi´n es el espacio comprendido entre el o punto y la marca. Para colocar una marca basta ubicar el cursor en el lugar deseado, y teclear C-Space o C-@. Esto coloca la marca donde est´ el punto (en el ejemplo del p´rrafo anterior, quedar´ a a ıa entre las letras a y c. Una vez colocada la marca, podemos mover el cursor a cualquier otro lugar del archivo (hacia atr´s o hacia adelante respecto a la marca). Esto define una cierta a ubicaci´n para el punto, y, por tanto, queda definida la regi´n autom´ticamente. o o a La regi´n es una porci´n del archivo que se puede manipular como un todo. Una regi´n se o o o puede borrar, copiar, pegar en otro punto del archivo o incluso en otro archivo; una regi´n se o puede imprimir, grabar como un archivo distinto; etc. As´ muchas operaciones importantes ı, se pueden efectuar sobre un bloque del archivo. Por ejemplo, si queremos duplicar una regi´n, basta con definir la regi´n deseada (ponieno o do la marca y el punto donde corresponda) y teclear M-w. Esto copia la regi´n a un buffer o temporal (llamado kill buffer). Luego movemos el cursor al lugar donde queremos insertar el texto duplicado, y hacemos C-y. Este comando toma el contenido del kill buffer y lo inserta en el archivo. El resultado final es que hemos duplicado una cierta porci´n del texto. o Si la intenci´n era mover dicha porci´n, el procedimiento es el mismo, pero con el comando o o C-w en vez de M-w. C-w tambi´n copia la regi´n a un kill buffer, pero borra el texto de la e o pantalla. Resumiendo:

C-Space o C-@ M-w C-w C-y

Comienzo de regi´n o Copia regi´n o Corta regi´n o Pega regi´n o

El concepto de kill buffer es mucho m´s poderoso que lo explicado reci´n. En realidad, a e muchos comandos, no s´lo M-w y C-w, copian texto en un kill buffer. En general, cualquier o comando que borre m´s de un car´cter a la vez, lo hace. Por ejemplo, C-k borra una l´ a a ınea. Lo que hace no es s´lo borrarla, sino adem´s copiarla en un kill buffer. Lo mismo ocurre o a con los comandos que borran palabras completas (M-d, M-Backspace), y muchos otros. Lo

333 interesante es que C-y funciona tambi´n en todos esos casos: C-y lo unico que hace es tomar e ´ el ultimo texto colocado en un kill buffer (resultado de la ultima operaci´n que borr´ m´s de ´ ´ o o a un car´cter a la vez), y lo coloca en el archivo. Por lo tanto, no s´lo podemos copiar o mover a o “regiones”, sino tambi´n palabras o l´ e ıneas. M´s a´n, el kill buffer no es borrado con el C-y, a u as´ que ese mismo texto puede ser duplicado muchas veces. Continuar´ disponible con C-y ı a mientras no se ponga un nuevo texto en el kill buffer. Adem´s, emacs dispone no de uno sino de muchos kill buffers. Esto permite recuperar a texto borrado hace mucho rato. En efecto, cada vez que se borra m´s de un car´cter de una a a vez, se una un nuevo kill buffer. Por ejemplo, consideremos el texto: La primera linea del texto, la segunda linea, y finalmente la tercera. Si en este p´rrafo borramos la primera l´ a ınea (con C-k), despu´s borramos la primera e palabra de la segunda (con M-d, por ejemplo), y luego la segunda palabra de la ultima, ´ entonces habr´ tres kill buffers ocupados: a buffer 1 : La primera linea del texto, buffer 2 : la buffer 3 : finalmente Al colocar el cursor despu´s del punto final, C-y toma el contenido del ultimo kill buffer e ´ y lo coloca en el texto:

segunda linea, y la tercera. finalmente Si se teclea ahora M-y, el ultimo texto recuperado, finalmente, es reemplazado por el ´ pen´ltimo texto borrado, y que est´ en el kill buffer anterior: u a

segunda linea, y la tercera. la Adem´s, la posici´n de los kill buffers se rota: a o buffer 1 : finalmente buffer 2 : La primera linea del texto, buffer 3 : la Sucesivas aplicaciones de M-y despu´s de un C-y rotan sobre todos los kill buffers (que e pueden ser muchos). El editor, as´ conserva un conjunto de las ultimas zonas borradas durante ı, ´ la edici´n, pudiendo recuperarse una antigua a pesar de haber seleccionado una nueva zona, o o borrado una nueva palabra o l´ ınea. Toda la informaci´n en los kill buffers se pierde al salir o de emacs (C-c). Resumimos entonces los comandos para manejo de los kill buffers:

334

´ APENDICE C. EDITORES TIPO EMACS.

C-y Copia el contenido del ultimo kill buffer ocupado ´ M-y Rota los kill buffers ocupados Definici´n de macros o La clave de la configurabilidad de emacs est´ en la posibilidad de definir nuevos comandos a que modifiquen su comportamiento o agreguen nuevas funciones de acuerdo a nuestras necesidades. Un modo de hacerlo es a trav´s del archivo de configuraci´n $HOME/.emacs, para lo e o cual se sugiere leer la documentaci´n disponible en la distribuci´n instalada. Sin embargo, si o o s´lo necesitamos un nuevo comando en la sesi´n de trabajo actual, un modo m´s simple es o o a definir una macro, un conjunto de ´rdenes que son ejecutados como un solo comando. Los o comandos relevantes son: C-x ( C-x ) C-x e Comienza la definici´n de una macro o Termina la definici´n de una macro o Ejecuta una macro definida

Todas las sucesiones de teclas y comandos dados entre C-x ( y C-x ) son recordados por emacs, y despu´s pueden ser ejecutados de una vez con C-x e. e Como ejemplo, consideremos el siguiente texto, con los cinco primeros lugares del r´nking a ATP (sistema de entrada) al 26 de marzo de 2002: 1 2 3 4 5 hewitt, lleyton (Aus) kuerten, gustavo (Bra) ferrero, juan (Esp) kafelnikov, yevgeny (Rus) haas, tommy (Ger)

Supongamos que queremos: (a) poner los nombres y apellidos con may´scula (como deu ber´ ser); (b) poner las siglas de pa´ s´lo en may´sculas. ıa ıses o u Para definir una macro, colocamos el cursor al comienzo de la primera l´ ınea, en el 1, y damos C-x (. Ahora realizamos todos los comandos necesarios para hacer las tres tareas solicitadas para el primer jugador solamente: M-f (avanza una palabra, hasta el espacio antes de hewitt; M-c M-c (cambia a Hewitt, Lleyton); M-u (cambia a AUS); Home (vuelve el cursor al comienzo de la l´ ınea); ↓ (coloca el cursor al comienzo de la l´ ınea siguiente, en el 2). Los dos ultimos pasos son importantes, porque dejan el cursor en la posici´n correcta para ´ o ejecutar el comando nuevamente. Ahora terminamos la definici´n con C-x ). Listo. Si ahora o ejecutamos la macro, con C-x e, veremos que la segunda l´ ınea queda modificada igual que la primera, y as´ podemos continuar hasta el final: ı 1 2 3 4 5 Hewitt, Lleyton (AUS) Kuerten, Gustavo (BRA) Ferrero, Juan (ESP) Kafelnikov, Yevgeny (RUS) Haas, Tommy (GER)

335 Comandos por nombre Aparte de los ya comentados existen muchas otras ´rdenes que no tienen necesariamente o una tecla asociada (bindkey) asociada. Para su ejecuci´n debe de teclearse previamente: o M-x y a continuaci´n en la zona inferior de la pantalla se introduce el comando deseado. Emo pleando el TAB se puede completar dicho comando (igual que en bash). De hecho, esto sirve para cualquier comando, incluso si tiene tecla asociada. Por ejemplo, ya sabemos M-g n va a la l´ ınea n del documento. Pero esto no es sino el comando goto-line, y se puede tambi´n ejecutar tecleando: M-x goto-line n. e Repetici´n o Todos los comandos de emacs, tanto los que tienen una tecla asociada como los que se ejecutan con nombre, se pueden ejecutar m´s de una vez, anteponi´ndoles un argumento a e num´rico con e M-(number) Por ejemplo, si deseamos escribir 20 letras e, basta teclear M-20 e. Esto es particularmente util con las macros definidos por el usuario. En el ejemplo anterior, con el r´nking ATP, ´ a despu´s de definir la macro quedamos en la l´ e ınea 2, y en vez de ejecutar C-x e 4 veces, podemos teclear M-4 C-x e, con el mismo resultado, pero en mucho menos tiempo. Para terminar la discusi´n de este editor, diremos que es conveniente conocer las secuencias o de control b´sico de emacs: a C-a, C-e, C-k, C-y, C-w, C-t, C-d, etc., porque funcionan para editar la l´ ınea de comandos en el shell, como tambi´n en muchos e programas de texto y en ventanas de di´logo de las aplicaciones X Windows. A su vez, los a editores jed, xjed, jove tambi´n usan por defecto estas combinaciones. e

336

´ APENDICE C. EDITORES TIPO EMACS.

Ap´ndice D e Una breve introducci´n a o Octave/Matlab
D.1. Introducci´n o

Octave es un poderoso software para an´lisis num´rico y visualizaci´n. Muchos de sus a e o comandos son compatibles con Matlab. En estos apuntes revisaremos algunas caracter´ ısticas de estos programas. En realidad, el autor de este cap´ ıtulo ha sido usuario durante algunos a˜os n de Matlab, de modo que estos apuntes se han basado en ese conocimiento, considerando los comandos que le son m´s familiares de Matlab. En la mayor´ de las ocasiones he verificado a ıa que los comandos descritos son tambi´n compatibles con Octave, pero ocasionalmente se e puede haber omitido algo. . . . Matlab es una abreviaci´n de Matrix Laboratory. Los elementos b´sicos con los que se o a trabaja con matrices. Todos los otros tipos de variables (vectores, texto, polinomios, etc.), son tratados como matrices. Esto permite escribir rutinas optimizadas para el trabajo con matrices, y extender su uso a todos los otros tipos de variables f´cilmente. a

D.2.

Interfase con el programa

Con Octave/Matlab se puede interactuar de dos modos: un modo interactivo, o a trav´s e de scripts. Al llamar a Octave/Matlab (escribiendo octave en el prompt, por ejemplo), se nos presenta un prompt. Si escribimos a=1, el programa responder´ a=1. Alternativamente, a podemos escribir a=3; (con punto y coma al final), y el programa no responder´ (elimina a el eco), pero almacena el nuevo valor de a. Si a continuaci´n escribimos a, el programa o responder´ a=3. Hasta este punto, hemos usado el modo interactivo. a Alternativamente, podemos introducir las instrucciones anteriores en un archivo, llamado, por ejemplo, prueba.m. En el prompt, al escribir prueba, y si nuestro archivo est´ en el path a de b´squeda del programa, las l´ u ıneas de prueba.m ser´n ejecutadas una a una. Por ejemplo, a si el archivo consta de las siguientes cuatro l´ ıneas: a=3; a 337

338 a=5 a

´ ´ APENDICE D. UNA BREVE INTRODUCCION A OCTAVE/MATLAB

el programa responder´ con a a=3 a=5 a=5 prueba.m corresponde a un script. Todas las instrucciones de Octave/Matlab pueden ejecutarse tanto en modo interactivo como desde un script. En Linux se puede ejecutar un archivo de comandos Octave de modo stand-alone incluyendo en la primera l´ ınea: #!/usr/bin/octave -q.

D.3.
D.3.1.

Tipos de variables
Escalares

A pesar de que ´stos son s´lo un tipo especial de matrices (ver subsecci´n siguiente), e o o conviene mencionar algunas caracter´ ısticas espec´ ıficas. – Un n´mero sin punto decimal es tratado como un entero exacto. Un n´mero con punto u u decimal es tratado como un n´mero en doble precisi´n. Esto puede no ser evidente u o en el output. Por default, 8.4 es escrito en pantalla como 8.4000. Tras la instrucci´n o format long, sin embargo, es escrito como 8.40000000000000. Para volver al formato original, basta la instrucci´n format. o – Octave/Matlab acepta n´meros reales y complejos. La unidad imaginaria es i: 8i y u 8*i definen el mismo n´mero complejo. Como i es una varible habitualmente usada u en iteraciones, tambi´n est´ disponible j como un sin´nimo. Octave/Matlab distinguen e a o entre may´sculas y min´sculas. u u – Octave/Matlab representa de manera especial los infinitos y cantidades que no son n´meros. inf es infinito, y NaN es un no-n´mero (Not-a-Number). Por ejemplo, escribir u u a=1/0 no arroja un error, sino un mensaje de advertencia, y asigna a a el valor inf. An´logamente, a=0/0 asigna a a el valor NaN. a

D.3.2.

Matrices

Este tipo de variable corresponde a escalares, vectores fila o columna, y matrices convencionales. Construcci´n o Las instrucciones: a = [1 2 ; 3 4]

D.3. TIPOS DE VARIABLES o ´ a = [1, 2; 3, 4]

339

1 2 . Las comas (opcionales) separan elementos de columnas distintas, 3 4 y los punto y coma separan elementos de filas distintas. El vector fila (1 2) es definen la matriz b = [1 2] y el vector columna c = [1;2] Un n´mero se define simplemente como d = [3] ´ d = 3. u o Nota importante: Muchas funciones de Octave/Matlab en las p´ginas siguientes acepa tan indistintamente escalares, vectores filas, vectores columnas, o matrices, y su output es un escalar, vector o matriz, respectivamente. Por ejemplo, log(a) es un vector fila si a es un vector fila (donde cada elemento es el logaritmo natural del elemento correspondiente en a), y un vector columna si a es un vector columna. En el resto de este manual no se advertira este hecho, y se pondr´n ejemplos con un solo tipo de variable, en el entendido que el lector a est´ conciente de esta nota. a Acceso y modificaci´n de elementos individuales o Accesamos los elementos de cada matriz usando los ´ ındices de filas y columnas, que parten de uno. Usando la matriz a antes definida, a(1,2) es 2. Para modificar un elemento, basta 1 2 escribir, por ejemplo, a(2,2) = 5. Esto convierte a la matriz en . En el caso especial 3 5 de vectores filas o columnas, basta un ´ ındice. (En los ejemplos anteriores, b(2) = c(2) = 2.) Una caracter´ ıstica muy importante del programa es que toda matriz es redimensionada autom´ticamente cuando se intenta modificar un elemento que sobrepasa las dimensiones a actuales de la matriz, llenando con ceros los lugares necesarios. Por ejemplo, si b = [1 2], y en seguida intentamos la asignaci´n b(5) = 8, b es autom´ticamente convertido al vector o a fila de 5 elementos [1 2 0 0 8]. Concatenaci´n de matrices o Si a = 1 2 ,b= 5 6 ,c= 3 4 7 , entonces 8 1 2 es

d = [a c] 1 2 7 3 4 8 d = [a; b] d=  1 2 d = 3 4  5 6 

340

´ ´ APENDICE D. UNA BREVE INTRODUCCION A OCTAVE/MATLAB

d = [a [0; 0] c] d= 1 2 0 7 3 4 0 8

D.3.3.

Strings

Las cadenas de texto son casos particulares de vectores fila, y se construyen y modifican de modo id´ntico. e Construcci´n o Las instrucciones t t t t = = = = [’un buen texto’] ["un buen texto"] ’un buen texto’ "un buen texto"

definen el mismo string t. Acceso y modificaci´n de elementos individuales o
r = t(4) r = ’b’ t(9) = ’s’ texto = ’un buen sexto’

Concatenaci´n o
t = ’un buen texto’; t1 = [t ’ es necesario’] t1 = ’un buen texto es necesario’

D.3.4.

Estructuras

Las estructuras son extensiones de los tipos de variables anteriores. Una estructura consta de distintos campos, y cada campo puede ser una matriz (es decir, un escalar, un vector o una matriz), o una string. Construcci´n o Las l´ ıneas persona.nombre = ’Eduardo’ persona.edad = 30 persona.matriz_favorita = [2 8;10 15];

´ D.4. OPERADORES BASICOS

341

definen una estructura con tres campos, uno de los cuales es un string, otro un escalar, y otro una matriz: persona = { nombre = ’Eduardo’; edad = 30; matriz_favorita = [2 8; 10 15]; } Acceso y modificaci´n de elementos individuales o
s = persona.nombre s = ’Eduardo’ persona.nombre = ’Claudio’ persona.matriz_favorita(2,1) = 8 persona = { nombre = ’Claudio’; edad = 30; matriz_favorita = [2 8; 8 15]; }

D.4.
D.4.1.

Operadores b´sicos a
Operadores aritm´ticos e

Los operadores +, -, * corresponden a la suma, resta y multiplicaci´n convencional de o matrices. Ambas matrices deben tener la misma dimensi´n, a menos que una sea un escalar. o Un escalar puede ser sumado, restado o multiplicado de una matriz de cualquier dimensi´n. o .* y ./ permiten multiplicar y dividir elemento por elemento. Por ejemplo, si a= entonces
c = a.*b c= 5 12 21 32

1 2 3 4

b=

5 6 7 8

c = a./b c= 0.2 0.3333 0.42857 0.5

342

´ ´ APENDICE D. UNA BREVE INTRODUCCION A OCTAVE/MATLAB

Si b es un escalar, a.*b y a./b equivalen a a*b y a/b. a^b es a elevado a b, si b es un escalar. a.^b eleva cada elemento de a a b. a’ es la matriz a† (traspuesta y conjugada) a.’ es la matriz traspuesta de a.

D.4.2.

Operadores relacionales

Los siguientes operadores est´n disponibles: a < <= > >= == ~= El resultado de estas operaciones es 1 (verdadero) ´ 0 (falso). Si uno de los operandos o es una matriz y el otro un escalar, se compara el escalar con cada elemento de la matriz. Si ambos operandos son matrices, el test se realiza elemento por elemento; en este caso, las matrices deben ser de igual dimensi´n. Por ejemplo, o
a b c d = = = = [1 2 3]; [4 2 1]; (a<3); (a>=b);

c = (1, 1, 0) d = (0, 1, 1)

D.4.3.

Operadores l´gicos o

Los siguientes s´ ımbolos corresponden a los operadores AND, OR y NOT: & | ~ El resultado de estas operaciones es 1 (verdadero) ´ 0 (falso). o

D.4.4.

El operador :

Es uno de los operadores fundamentales. Permite crear vectores y extraer submatrices. : crea vectores de acuerdo a las siguientes reglas: j:k j:i:k es lo mismo que [j,j+1,...,k], si j<=k. es lo mismo que [j,j+i,j+2*i,...,k], si i>0 y j<k, o si i<0 y j>k.

: extrae submatrices de acuerdo a las siguientes reglas: A(:,j) A(i,:) A(:,:) A(:,j:k) A(:) es la j-´sima columna de A. e es la i-´sima fila de A. e es A. es A(:,j), A(:,j+1), . . . , A(:,k). son todos los elementos de A, agrupados en una unica columna. ´

´ D.5. COMANDOS MATRICIALES BASICOS

343

D.4.5.

Operadores de aparici´n preferente en scripts o

Los siguientes operadores es m´s probable que aparezcan durante la escritura de un script a que en modo interactivo. % : Comentario. El resto de la l´ ınea es ignorado. ... : Continuaci´n de l´ o ınea. Si una l´ ınea es muy larga y no cabe en la pantalla, o por alguna otra raz´n se desea dividir una l´ o ınea, se puede usar el operador ... . Por ejemplo, m = [1 2 3 ... 4 5 6]; es equivalente a m = [1 2 3 4 5 6];

D.5.

Comandos matriciales b´sicos a

Antes de revisar una a una diversas familias de comandos disponibles, y puesto que las matrices son el elemento fundamental en Octave/Matlab, en esta secci´n reuniremos algunas o de las funciones m´s frecuentes sobre matrices, y c´mo se realizan en Octave/Matlab. a o Op. aritm´tica e Conjugar Trasponer Trasponer y conjugar Invertir Autovalores, autovectores Determinante Extraer elementos Traza Dimensiones Exponencial +, -, *, .*, ./ conj(a) a.’ a’ inv(a) [v,d]=eig(a) det(a) : trace(a) size(a) exp(a) expm(a) (ver subsecci´n D.4.1) o

(ver subsecci´n D.6.5) o (ver subsecci´n D.4.4) o

(elemento por elemento) (exponencial matricial)

D.6.

Comandos

En esta secci´n revisaremos diversos comandos de uso frecuente en Octave/Matlab. Esta o lista no pretende ser exhaustiva (se puede consultar la documentaci´n para mayores detalles), o y est´ determinada por mi propio uso del programa y lo que yo considero m´s frecuente a a debido a esa experiencia. Insistimos en que ni la lista de comandos es exhaustiva, ni la lista de ejemplos o usos de cada comando lo es. Esto pretende ser s´lo una descripci´n de los o o aspectos que me parecen m´s importantes o de uso m´s recurrente. a a

D.6.1.
clear

Comandos generales
Borra variables y funciones de la memoria

344 clear clear a disp

´ ´ APENDICE D. UNA BREVE INTRODUCCION A OCTAVE/MATLAB Borra todas las variables en memoria Borra la variable a

Presenta matrices o texto

disp(a) presenta en pantalla los contenidos de una matriz, sin imprimir el nombre de la matriz. a puede ser una string.
disp(’ c1 disp([.3 .4]); c2’); c1 c2 0.30000 0.40000

load, save

Carga/Guarda variables desde el disco Guarda las variables a y b en el archivo fname Lee el archivo fname, cargando las definiciones de variables en ´l definidas. e

save fname a b load fname

size,length

Dimensiones de una matriz/largo de un vector

Si a es una matrix de n × m: d = size(a) [m,n] = size(a) d = [m,n] Aloja en m el n´mero de filas, y en n el de columnas u

Si b es un vector de n elementos, length(b) es n. who quit Lista de variables en memoria Termina Octave/Matlab

D.6.2.

Como lenguaje de programaci´n o

Control de flujo for
n=3; for i=1:n a(i)=i^2; end a=[1 4 9]

Para Octave el vector resultante es columna en vez de fila. Observar el uso del operador : para generar el vector [1 2 3]. Cualquier vector se puede utilizar en su lugar: for i=[2 8 9 -3], for i=10:-2:1 (equivalente a [10 8 6 4 2]), etc. son v´lidas. El ciclo for anterior se podr´ haber escrito en una sola l´ a ıa ınea as´ ı: for i=1:n, a(i)=i^2; end

D.6. COMANDOS if, elseif, else Ejemplos: a) if a~=b, disp(a); end b) if a==[3 8 9 10] b = a(1:3); end c) if a>3 clear a; elseif a<0 save a; else disp(’Valor de a no considerado’); end

345

Naturalmente, elseif y else son opcionales. En vez de las expresiones condicionales indicadas en el ejemplo pueden aparecer cualquier funci´n que d´ valores 1 (verdadero) ´ 0 o e o (falso). while while s comandos end Mientras s es 1, se ejecutan los comandos entre while y end. s puede ser cualquier expresi´n que d´ por resultado 1 (verdadero) ´ 0 (falso). o e o break Interrumpe ejecuci´n de ciclos for o while. En loops anidados, break sale del m´s interno o a solamente. Funciones l´gicas o Adem´s de expresiones construidas con los operadores relacionales ==, <=, etc., y los a operadores l´gicos &, | y ~, los comandos de control de flujo anteriores admiten cualquier o funci´n cuyo resultado sea 1 (verdadero) ´ 0 (falso). Particularmente utiles son funciones o o ´ como las siguientes: all(a) any(a) isempty(a) 1 si todos los elementos de a son no nulos, y 0 si alguno es cero 1 si alguno de los elementos de a es no nulo 1 si a es matriz vac´ (a=[]) ıa

346

´ ´ APENDICE D. UNA BREVE INTRODUCCION A OCTAVE/MATLAB

Otras funciones entregan matrices de la misma dimensi´n que el argumento, con unos o o ceros en los lugares en que la condici´n es verdadera o falsa, respectivamente: o finite(a) isinf(a) isnan(a) 1 donde a es finito (no inf ni NaN) 1 donde a es infinito 1 donde a es un NaN

Por ejemplo, luego de ejecutar las l´ ıneas x y a b c = = = = = [-2 -1 0 1 2]; 1./x; finite(y); isinf(y); isnan(y);

se tiene a = [1 1 0 1 1] b = [0 0 1 0 0] c = [0 0 0 0 0] Otra funci´n l´gica muy importante es find: o o find(a) Encuentra los ´ ındices de los elementos no nulos de a.

Por ejemplo, si ejecutamos las l´ ıneas x=[11 0 33 0 55]; z1=find(x); z2=find(x>0 & x<40); obtendremos z1 = [1 3 5] z2 = [1 3] find tambi´n puede dar dos resultados de salida simult´neamente (m´s sobre esta posie a a bilidad en la secci´n D.6.2), en cuyo caso el resultado son los pares de ´ o ındices (´ ındices de fila y columna) para cada elemento no nulo de una matriz y=[1 2 3 4 5;6 7 8 9 10]; [z3,z4]=find(y>8); da como resultado z3 = [2;2]; z4 = [4;5]; z3 contiene los ´ ındice de fila y z4 los de columna para los elementos no nulos de la matriz 2 4 y>8. Esto permite construir, por ejemplo, la matriz z5=[z3 z4] = , en la cual cada 2 5 fila es la posici´n de y tal que la condici´n y>8 es verdadera (en este caso, es verdadera para o o los elementos y(2,4) e y(2,5)).

D.6. COMANDOS Funciones definidas por el usuario

347

Octave/Matlab puede ser f´cilmente extendido por el usuario definiendo nuevas funciones a que le acomoden a sus prop´sitos. Esto se hace a trav´s del comando function. o e Podemos definir (en modo interactivo o dentro de un script), una funci´n en la forma o function nombre (argumentos) comandos endfunction argumentos es una lista de argumentos separados por comas, y comandos es la sucesi´n o de comandos que ser´n ejecutados al llamar a nombre. La lista de argumentos es opcional, a en cuyo caso los par´ntesis redondos se pueden omitir. e A mediano y largo plazo, puede ser mucho m´s conveniente definir las funciones en ara chivos especiales, listos para ser llamados en el futuro desde modo interactivo o desde cualquier script. Esto se hace escribiendo la definici´n de una funci´n en un script con extensi´n o o o .m. Cuando Octave/Matlab debe ejecutar un comando o funci´n que no conoce, por ejemo plo, suma(x,y),busca en los archivos accesibles en su path de b´squeda un archivo llamado u suma.m, lo carga y ejecuta la definici´n contenida en ese archivo. o Por ejemplo, si escribimos en el script suma.m las l´ ıneas function s=suma(x,y) s = x+y; el resultado de suma(2,3) ser´ 5. a Las funciones as´ definidas pueden entregar m´s de un argumento si es necesario (ya hemos ı a visto algunos ejemplos con find y size). Por ejemplo, definimos una funci´n que efect´e un o u an´lisis estad´ a ıstico b´sico en stat.m: a function [mean,stdev] = stat(x) n = length(x); mean = sum(x)/n; stdev = sqrt(sum((x-mean).^2/n)); Al llamarla en la forma [m,s] = stat(x), si x es un vector fila o columna, en m quedar´ el a promedio de los elementos de x, y en s la desviaci´n est´ndard. o a Todas las variables dentro de un script que define una funci´n son locales, a menos que o se indique lo contrario con global. Por ejemplo, si un script x.m llama a una funci´n f, y o dentro de f.m se usa una variable a que queremos sea global, ella se debe declarar en la forma global a tanto en f.m como en el script que la llam´, x.m, y en todo otro script que o pretenda usar esa variable global.

D.6.3.

Matrices y variables elementales

Matrices constantes importantes Las siguientes son matrices que se emplean habitualmente en distintos contextos, y que es util tener muy presente: ´

348 eye(n) ones(m,n) rand(m,n) randn(m,n) zeros(m,n)

´ ´ APENDICE D. UNA BREVE INTRODUCCION A OCTAVE/MATLAB Matriz identidad de n × n Matriz de m × n, con todos los elementos igual a 1. Matriz de m × n de n´meros al azar, distribuidos uniformeu mente. Igual que rand, pero con distribuci´n normal (Gaussiana). o Igual que ones, pero con todos los elementos 0.

Matrices utiles para construir ejes o mallas para graficar ´ Las siguientes son matrices se emplean habitualmente en la construcci’on de gr´ficos: a v = linspace(min,max,n) v = logspace(min,max,n) [X,Y] = meshgrid(x,y) Vector cuyo primer elemento es min, su ultimo elemento ´ es max, y tiene n elementos equiespaciados. An´logo a linspace, pero los n elementos est´n espaa a ciados logar´ ıtmicamente. Construye una malla del plano x-y. Las filas de X son copias del vector x, y las columnas de Y son copias del vector y.

Por ejemplo: x = [1 2 3]; y = [4 5]; [X,Y] = meshgrid(x,y); da X= 1 2 3 1 2 3 , Y = 4 4 4 5 5 5 .

Notemos que al tomar sucesivamente los distintos pares ordenados (X(1,1),Y(1,1)), (X(1,2),Y(1,2)), (X(1,3),Y(1,3)), etc., se obtienen todos los pares ordenados posibles tales que el primer elemento est´ en x y el segundo est´ en y. Esta caracter´ a a ıstica hace particularmente util el ´ comando meshgrid en el contexto de gr´ficos de funciones de dos variables (ver secciones a D.6.7, D.6.7). Constantes especiales Octave/Matlab proporciona algunos n´meros especiales, algunos de los cuales ya menciou namos en la secci´n D.3.1. o √ i, j Unidad imaginaria ( −1 ) inf Infinito NaN Not-A-Number pi El n´mero π (= 3.1415926535897 . . .) u Funciones elementales Desde luego, Octave/Matlab proporciona todas las funciones matem´ticas b´sicas. Por a a ejemplo:

D.6. COMANDOS a) Funciones sobre n´meros reales/complejos u abs angle conj real imag sign sqrt Valor absoluto de n´meros reales, o m´dulo de n´meros imaginarios u o u ´ Angulo de fase de un n´mero imaginario u Complejo conjugado Parte real Parte imaginaria Signo Ra´ cuadrada ız

349

b) Exponencial y funciones asociadas cos, sin, etc. cosh, sinh, etc. exp log c) Redondeo ceil fix floor round Redondear Redondear Redondear Redondear hacia hacia hacia hacia +∞ cero −∞ el entero m´s cercano a Funciones trigonom´tricas e Funciones hiperb´licas o Exponencial Logaritmo

Funciones especiales Adem´s, Octave/Matlab proporciona diversas funciones matem´ticas especiales. Algunos a a ejemplos: bessel besselh beta ellipke erf gamma Funci´n o Funci´n o Funci´n o Funci´n o Funci´n o Funci´n o de Bessel de Hankel beta el´ ıptica error gamma

As´ por ejemplo, bessel(alpha,X) eval´a la funci´n de Bessel de orden alpha, Jα (x), ı, u o para cada elemento de la matriz X.

D.6.4.

Polinomios
p = cn xn + · · · + c1 x + c0

Octave/Matlab representa los polinomios como vectores fila. El polinomio

es representado en Octave/Matlab en la forma p = [c_n, ..., c1, c0]

350

´ ´ APENDICE D. UNA BREVE INTRODUCCION A OCTAVE/MATLAB

Podemos efectuar una serie de operaciones con los polinomios as´ representados. ı poly(x) polyval(p,x) roots(p) Polinomio cuyas ra´ son los elementos de x. ıces Eval´a el polinomio p en x (en los elementos de x si ´ste es u e un vector) Ra´ del polinomio p ıces

D.6.5.
det rank trace inv eig poly

´ Algebra lineal (matrices cuadradas)
Determinante N´mero de filas o columnas linealmente independientes u Traza Matriz inversa Autovalores y autovectores Polinomio caracter´ ıstico

Unos pocos ejemplos, entre los comandos de uso m´s habitual: a

Notar que poly es la misma funci´n de la secci´n D.6.4 que construye un polinomio de o o ra´ ıces dadas. En el fondo, construir el polinomio caracter´ ıstico de una matriz es lo mismo, y por tanto tiene sentido asignarles la misma funci´n. Y no hay confusi´n, pues una opera o o sobre vectores y la otra sobre matrices cuadradas. El uso de todos estos comandos son autoexplicativos, salvo eig, que se puede emplear de dos modos: d = eig(a) [V,D] = eig(a) La primera forma deja en d un vector con los autovalores de a. La segunda, deja en D una matriz diagonal con los autovalores, y en V una matiz cuyas columnas son los autovalores, de modo que A*V = V*D. Por ejemplo, si a =[1 2; 3 4], entonces d= y D= 5.37228 . . . 0 0 −0.37228 . . . , V = 0.41597 . . . −0.82456 . . . 0.90938 . . . 0.56577 . . . . 5.37228 −0.37228

La primera columna de V es el autovector de a asociado al primer autovalor, 5.37228 . . ..

D.6.6.

An´lisis de datos y transformada de Fourier a

En Octave/Matlab est´n disponibles diversas herramientas para el an´lisis de series de a a datos (estad´ ıstica, correlaciones, convoluci´n, etc.). Algunas de las operaciones b´sicas son: o a a) M´ximos y m´ a ınimos Si a es un vector, max(a) es el mayor elemento de a. Si es una matriz, max(a) es un vector fila, que contiene el m´ximo elemento para cada columna. a

D.6. COMANDOS
a = [1 6 7; 2 8 3; 0 4 1] b = max(a)

351

b = (2

8

7)

Se sigue que el mayor elemento de la matriz se obtiene con max(max(a)). min opera de modo an´logo, entregando los m´ a ınimos. b) Estad´ ıstica b´sica a Las siguientes funciones, como min y max, operan sobre vectores del modo usual, y sobre matrices entregando vectores fila, con cada elemento representando a cada columna de la matriz. mean median std prod sum Valor promedio Mediana Desviaci´n standard o Producto de los elementos Suma de los elementos

c) Orden sort(a) ordena los elementos de a en orden ascendente si a es un vector. Si es una matriz, ordena cada columna.
b = sort([1 3 9; 8 2 1; 4 -3 0]);  1 −3 0 b = 4 2 1  8 3 9 

d) Transformada de Fourier Por ultimo, es posible efectuar transformadas de Fourier directas e inversas, en una o dos ´ dimensiones. Por ejemplo, fft y ifft dan la transformada de Fourier y la transformada inversa de x, usando un algoritmo de fast Fourier transform (FFT). Espec´ ıficamente, si X=fft(x) y x=ifft(X), y los vectores son de largo N:
N

X(k) =
j=1

x(j)ωN
N

(j−1)(k−1)

,

1 x(j) = N donde ωN = e−2πi/N .

X(k)ωN
k=1

−(j−1)(k−1)

,

D.6.7.

Gr´ficos a

Una de las caracter´ ısticas m´s importantes de Matlab son sus amplias posibilidades gr´fia a cas. Algunas de esas caracter´ ısticas se encuentran tambi´n en Octave. En esta secci´n revie o saremos el caso de gr´ficos en dos dimensiones, en la siguiente el caso de tres dimensiones, y a luego examinaremos algunas posibilidades de manipulaci´n de gr´ficos. o a

352

´ ´ APENDICE D. UNA BREVE INTRODUCCION A OCTAVE/MATLAB

Gr´ficos bidimensionales a Para graficar en dos dimensiones se usa el comando plot. plot(x,y) grafica la ordenada y versus la abscisa x. plot(y) asume abscisa [1,2,...n], donde n es la longitud de y. Ejemplo: Si x=[2 8 9], y=[6 3 2], entonces plot(x,y)

Figura D.1: Gr´fico simple. a

Por default, Octave utiliza gnuplot para los gr´ficos. Por default, los puntos se conectan a con una l´ ınea roja en este caso. El aspecto de la l´ ınea o de los puntos puede ser modificado. Por ejemplo, plot(x,y,’ob’) hace que los puntos sean indicados con c´ ırculos (’o’) azules (’b’, blue). Otros modificadores posibles son: . @ + * o x l´ ınea (default) puntos otro estilo de puntos signo m´s a asteriscos c´ ırculos cruces r g b m c w red green blue magenta cyan white

Dos o m´s gr´ficos se pueden incluir en el mismo output agregando m´s argumentos a a a a plot. Por ejemplo: plot(x1,y1,’x’,x2,y2,’og’,x3,y3,’.c’). Los mapas de contorno son un tipo especial de gr´fico. Dada una funci´n z = f (x, y), a o nos interesa graficar los puntos (x, y) tales que f = c, con c alguna constante. Por ejemplo, consideremos 2 2 z = xe−x −y , x ∈ [−2, 2], y ∈ [−2, 3] . Para obtener el gr´fico de contorno de z, mostrando los niveles z = −.3, z = −.1, z = 0, a z = .1 y z = .3, podemos usar las instrucciones: x = -2:.2:2; y = -2:.2:3; [X,Y] = meshgrid(x,y);

D.6. COMANDOS Z = X.*exp(-X.^2-Y.^2); contour(Z.’,[-.3 -.1 0 .1 .3],x,y); # Octave por default (gnuplot) contour(x, y, Z.’,[-.3 -.1 0 .1 .3]); # Octave con plplot y Matlab

353

Figura D.2: Curvas de contorno.

Las dos primeras l´ ıneas definen los puntos sobre los ejes x e y en los cuales la funci´n o ser´ evaluada. En este caso, escojimos una grilla en que puntos contiguos est´n separados por a a .2. Para un mapa de contorno, necesitamos evaluar la funci´n en todos los pares ordenados o (x, y) posibles al escoger x en x e y en y. Para eso usamos meshgrid (introducida sin mayores o explicaciones en la secci´n D.6.3). Luego evaluamos la funci´n [Z es una matriz, donde cada o elemento es el valor de la funci´n en un par ordenado (x, y)], y finalmente construimos el o mapa de contorno para los niveles deseados. Gr´ficos tridimensionales a Tambi´n es posible realizar gr´ficos tridimensionales. Por ejemplo, la misma doble gause a siana de la secci´n anterior se puede graficar en tres dimensiones, para mostrarla como una o superficie z(x, y). Basta reemplazar la ultima instrucci´n, que llama a contour, por la si´ o guiente: mesh(X,Y,Z) Observar que, mientras contour acepta argumentos dos de los cuales son vectores, y el tercero una matriz, en mesh los tres argumentos son matrices de la misma dimensi´n (usamos o X, Y, en vez de x, y). Nota importante: Otro modo de hacer gr´ficos bi y tridimensionales es con gplot a y gsplot (instrucciones asociadas realmente no a Octave sino a gnuplot, y por tanto no equivalentes a instrucciones en Matlab). Se recomienda consultar la documentaci´n de Octave o para los detalles.

354

´ ´ APENDICE D. UNA BREVE INTRODUCCION A OCTAVE/MATLAB

Figura D.3: Curvas de contorno.

Manipulaci´n de gr´ficos o a Los siguientes comandos est´n disponibles para modificar gr´ficos construidos con Octaa a ve/Matlab: a) Ejes axis([x1 y1 x2 y2]) b) T´ ıtulos title(s) xlabel(s) ylabel(s) zlabel(s) c) Grillas grid Incluye o borra una grilla de referencia en un gr´fico bidimena sional. grid ‘‘on’’ coloca la grilla y grid ‘‘off’’ la saca. grid equivale a grid ‘‘on’’. T´ ıtulo (s es un string) T´ ıtulo del eje x, y, z. Cambia el eje x al rango (x1, x2), y el eje y al rango (y1, y2).

Al usar gnuplot, el gr´fico mostrado en pantalla no es actualizado autom´ticamente. a a Para actualizarlo y ver las modificaciones efectuadas, hay que dar la instrucci´n replot. o Los siguientes comandos permiten manipular las ventanas gr´ficas: a

D.6. COMANDOS hold Permite “congelar” la figura actual, de modo que sucesivos comandos gr´ficos se superponen sobre dicha figura (nora malmente la figura anterior es reemplazada por la nueva). hold on activa este “congelamiento”, y hold off lo desactiva. hold cambia alternativamente entre el estado on y off. Cierra la ventana actual.

355

closeplot

Finalmente, si se desea guardar un gr´fico en un archivo, se puede proceder del siguiente a modo si Octave est´ generando los gr´ficos con gnuplot y se trabaja en un terminal con a a XWindows. Si se desea guardar un gr´fico de la funci´n y = x3 , por ejemplo: a o x = linspace(1,10,30); y = x.^3; plot(x,y); gset term postscript color gset output ‘‘xcubo.ps’’ replot gset term x11 Las tres primeras l´ ıneas son los comandos de Octave/Matlab convencionales para graficar. Luego se resetea el terminal a un terminal postscript en colores (gset term postscript si no deseamos los colores), para que el output sucesivo vaya en formato postscript y no a la pantalla. La siguiente l´ ınea indica que la salida es al archivo xcubo.ps. Finalmente, se redibuja el gr´fico (con lo cual el archivo xcubo.ps es realmente generado), y se vuelve al a terminal XWindows para continuar trabajando con salida a la pantalla. Debemos hacer notar que no necesariamente el gr´fico exportado a Postscript se ver´ igual a a al resultado que gnuplot muestra en pantalla. Durante la preparaci´n de este manual, nos o dimos cuenta de ello al intentar cambiar los estilos de l´ ınea de plot. Queda entonces advertido el lector.

D.6.8.
lower upper

Strings
Convierte a min´sculas u Convierte a may´sculas u

Para manipular una cadena de texto, disponemos de los siguientes comandos:

As´ lower(’Texto’) da ’texto’, y upper(’Texto’) da ’TEXTO’. ı, Para comparar dos matrices entre s´ usamos strcmp: ı, strcmp(a,b) 1 si a y b son id´nticas, 0 en caso contrario e

Podemos convertir n´meros enteros o reales en strings, y strings en n´meros, con los u u comandos: int2str num2str str2num Convierte entero en string Convierte n´mero en string u Convierte string en n´mero u

356

´ ´ APENDICE D. UNA BREVE INTRODUCCION A OCTAVE/MATLAB

Por ejemplo, podemos usar esto para construir un t´ ıtulo para un gr´fico: a s = [’Intensidad transmitida vs. frecuencia, n = ’, num2str(1.5)]; title(s); Esto pondr´ un t´ a ıtulo en el gr´fico con el texto: a Intensidad transmitida vs. frecuencia, n = 1.5.

D.6.9.

Manejo de archivos

Ocasionalmente nos interesar´ grabar el resultado de nuestros c´lculos en archivos, o a a utilizar datos de archivos para nuevos c´lculos. El primer paso es abrir un archivo: a archivo = fopen(’archivo.dat’,’w’); Esto abre el archivo archivo.dat para escritura (’w’), y le asigna a este archivo un n´mero u que queda alojado en la variable archivo para futura referencia. Los modos de apertura posibles son: r w a r+ w+ a+ Abre para lectura Abre para escritura, descartando contenidos anteriores si los hay Abre o crea archivo para escritura, agregando datos al final del archivo si ya existe Abre para lectura y escritura Crea archivo para lectura y escritura Abre o crea archivo para lectura y escritura, agregando datos al final del archivo si ya existe

En un archivo se puede escribir en modo binario: fread fwrite o en modo texto fgetl fgets fprintf fscanf Lee una l´ ınea del archivo, descarta cambio de l´ ınea Lee una l´ ınea del archivo, preserva cambio de l´ ınea Escribe datos siguiendo un formato Lee datos siguiendo un formato Lee datos binarios Escribe datos binarios

Referimos al lector a la ayuda que proporciona Octave/Matlab para interiorizarse del uso de estos comandos. S´lo expondremos el uso de fprintf, pues el formato es algo que o habitualmente se necesita tanto para escribir en archivos como en pantalla, y fprintf se puede usar en ambos casos. La instrucci´n o fprintf(archivo,’formato’,A,B,...)

D.6. COMANDOS

357

imprime en el archivo asociado con el identificador archivo (asociado al mismo al usar fopen, ver m´s arriba), las variables A, B, etc., usando el formato ’formato’. archivo=1 corresponde a a la pantalla; si archivo se omite, el default es 1, es decir, fprintf imprime en pantalla si archivo=1 o si se omite el primer argumento. ’formato’ es una string, que puede contener caracters normales, caracteres de escape o especificadores de conversi´n. Los caracteres de escape son: o \n \t \b \r \f \\ \’ New line Horizontal tab Backspace Carriage return Form feed Backslash Single quote

Por ejemplo, la l´ ınea fprintf(’Una tabulacion\t y un \’\’original\’\’ cambio de linea\n aqui\n’) da como resultado Una tabulacion aqui y un ’’original’’ cambio de linea

Es importante notar que por default, el cambio de l´ ınea al final de un fprintf no existe, de modo que, si queremos evitar salidas a pantalla o a archivo poco est´ticas, siempre hay e que terminar con un \n. Los especificadores de conversi´n permiten dar formato adecuado a las variables num´ricas o e A, B, etc. que se desean imprimir. Constan del caracter %, seguido de indicadores de ancho (opcionales), y caracteres de conversi´n. Por ejemplo, si deseamos imprimir el n´mero π con o u 5 decimales, la instrucci´n es: o fprintf(’Numero pi = %.5f\n’,pi) El resultado: Numero pi = 3.14159 Los caracteres de conversi´n pueden ser o %e %f %g Notaci´n exponencial (Ej.: 2.4e-5) o Notaci´n con punto decimal fijo (Ej.: 0.000024) o %e o %f, dependiendo de cu´l sea m´s corto (los ceros no a a significativos no se imprimen)

Entre % y e, f, o g seg´n corresponda, se pueden agregar uno o m´s de los siguientes u a caracteres, en este orden: Un signo menos (-), para especificar alineamiento a la izquierda (a la derecha es el default).

358

´ ´ APENDICE D. UNA BREVE INTRODUCCION A OCTAVE/MATLAB Un n´mero entero para especificar un ancho m´ u ınimo del campo. Un punto para separar el n´mero anterior del siguiente n´mero. u u Un n´mero indicando la precisi´n (n´mero de d´ u o u ıgitos a la derecha del punto decimal).

En el siguiente ejemplo veremos distintos casos posibles. El output fue generado con las siguientes instrucciones, contenidas en un script: a = .04395; fprintf(’123456789012345\n’); fprintf(’a = %.3f.\n’,a); fprintf(’a = %10.2f.\n’,a); fprintf(’a = %-10.2f.\n’,a); fprintf(’a = %4f.\n’,a); fprintf(’a = %5.3e.\n’,a); fprintf(’a = %f.\n’,a); fprintf(’a = %e.\n’,a); fprintf(’a = %g.\n’,a); El resultado: 12345678901234567890 a = 0.044. a = 0.04. a = 0.04 . a = 0.043950. a = 4.395e-02. a = 0.043950. a = 4.395000e-02. a = 0.04395. En la primera l´ ınea, se imprimen tres decimales. En la segunda, dos, pero el ancho m´ ınimo es 10 caracteres, de modo que se al´ ınea a la derecha el output y se completa con blancos. En la tercera l´ ınea es lo mismo, pero alineado a la izquierda. En la cuarta l´ ınea se ha especificado un ancho m´ ınimo de 4 caracteres; como el tama˜o del n´mero es mayor, esto no tiene efecto n u y se imprime el n´mero completo. En la quinta l´ u ınea se usa notaci´n exponencial, con tres o decimal (nuevamente, el ancho m´ ınimo especificado, 5, es menor que el ancho del output, luego no tiene efecto). Las ultimas tres l´ ´ ıneas comparan el output de %f, %e y %g, sin otras especificaciones. Si se desean imprimir m´s de un n´mero, basta agregar las conversiones adecuadas y los a u argumentos en fprintf. As´ la l´ ı, ınea fprintf(’Dos numeros arbitrarios: %g y %g.\n’,pi,exp(4)); da por resultado Dos numeros arbitrarios: 3.14159 y 54.5982.

D.6. COMANDOS

359

Si los argumentos num´ricos de fprintf son matrices, el formato es aplicado a cada e columna hasta terminar la matriz. Por ejemplo, el script x = 1:5; y1 = exp(x); y2 = log(x); a = [x; y1; y2]; fprintf = (’%g %8g %8.3f\n’,a); da el output 1 2 3 4 5 2.71828 7.38906 20.0855 54.5982 148.413 0.000 0.693 1.099 1.386 1.609

360

´ ´ APENDICE D. UNA BREVE INTRODUCCION A OCTAVE/MATLAB

Ap´ndice E e Asignaci´n din´mica. o a
La reserva de memoria para la matriz podemos hacerla en forma din´mica ocupando el a operador new que pedir´ al sistema la memoria necesaria, si est´ disponible el sistema se a a la asignar´. Como con cualquier puntero, una vez desocupado el arreglo debemos liberar la a memoria con el comando delete. #include <iostream> using namespace std; int main() { cout<<"Ingrese la dimension deseada :" ; int dim ; cin >> dim ; double * matriz = new double[dim] ; // Reserva la memoria for(int i=0; i < dim; i++) { cout << "Ingrese elemento "<< i <<" : "; cin >> matriz[i] ; } for (int i=0;i<dim;i++){ cout << matriz[i] << ", "; } cout << endl; delete [] matriz; return 0; } Este ejemplo permite apreciar una gran ventaja del uso de punteros, al permitirnos liberarnos de definir la dimensi´n de una matriz como una constante. Aqu´ dim es simplemente un int. o ı, La asignaci´n din´mica permite definir matrices cuya dimensi´n se determina reci´n durante o a o e la ejecuci´n. o Observemos finalmente que la liberaci´n de memoria, en el caso de arreglos, se hace con o el operador delete [], no delete como en los punteros usuales. 361 // Libera la memoria reservada

362

´ ´ ´ APENDICE E. ASIGNACION DINAMICA.

E.1.

Arreglos din´micos bidimensionales. a

Tambi´n es posible definir arreglos bidimensionales din´micamente. En el siguiente ejeme a plo, se define una matriz de 200 filas y 400 columnas, inicializ´ndose sus elementos a cero, y a finalmente se borra: int main() { int width; int height; width = 200; height = 400;

double ** matriz = new double * [width]; for (int i=0;i<width;i++){ matriz[i] = new double[height]; } for (int i=0;i<width;i++){ for (int j=0;j<height;j++){ matriz[i][j] = 0; } } for (int i=0;i<width;i++){ delete [] matriz[i]; } delete [] matriz; return 0; } Primero se crea, con new, un puntero (matriz) de dimensi´n 200, que representar´ las o a filas. Cada uno de sus elementos (matriz[i]), a su vez, ser´ un nuevo puntero, de dimensi´n a o 400, representando cada columna. Por tanto, matriz debe ser un puntero a puntero (de dobles, en este caso), y as´ es definido inicialmente (double ** ...). Esto puede parecer ı extra˜o a primera vista, pero recordemos que los punteros pueden ser punteros a cualquier n objeto, en particular a otro puntero. Luego se crean los punteros de cada columna (primer ciclo for). A continuaci´n se llenan los elementos con ceros (segundo ciclo for). Finalmente, o se libera la memoria, en orden inverso a como fue asignada: primero se libera la memoria de cada columna de la matriz (delete [] matriz[i], tercer ciclo for), y por ultimo se libera ´ la memoria del puntero a estos punteros (delete [] matriz).

Ap´ndice F e make & Makefile.
Frecuentemente los programas est´n compuestos por diferentes subprogramas que se haa yan contenidos en diferentes archivos. La orden de compilaci´n necesaria puede ser muy o engorrosa, y a menudo no es necesario volver a compilar todos los archivos, sino s´lo aqueo llos que hayan sido modificados. unix dispone de una orden denominada make que evita los problemas antes mencionados y permite el mantenimiento de una biblioteca personal de programas. Este comando analiza qu´ archivos fuentes han sido modificados despu´s de la e e ultima compilaci´n y evita recompilaciones innecesarias. ´ o En su uso m´s simple s´lo es necesario suministrar una lista de dependencias y/o instruca o ciones a la orden make en un archivo denominado Makefile. Una dependencia es la relaci´n o entre dos archivos de forma que un archivo se considera actualizado siempre que el otro tenga una fecha de modificaci´n inferior a ´ste. Por ejemplo, si el archivo file.cc incluye el o e archivo file.h, no se puede considerar actualizado el archivo file.o si el archivo file.cc o el archivo file.h ha sido modificado despu´s de la ultima compilaci´n. Se dice que el e ´ o archivo file.o depende de file.cc y el archivo file.cc depende del archivo file.h. El Makefile se puede crear con un editor de texto y tiene el siguiente aspecto para establecer una dependencia: # Esto es un ejemplo de Makefile. # Se pueden poner comentarios tras un caracter hash (#). FILE1: DEP1 DEP2 comandos para generar FILE1 ETIQUETA1: FILE2 FILE2: DEP3 DEP4 comandos para generar FILE2 ETIQUETA2: comandos Se comienza con un destino, seguido de dos puntos (:) y los prerrequisitos o dependencias necesarios. Tambi´n puede ponerse una etiqueta y como dependencia un destino, o bien una e etiqueta y uno o m´s comandos. Si existen muchos prerrequisitos, se puede finalizar la l´ a ınea con un backslash (\) y continuar en la siguiente l´ ınea. En la(s) l´ ınea(s) siguiente(s) se escriben uno o m´s comandos. Cada l´ a ınea se considera como un comando independiente. Si se desea utilizar m´ltiples l´ u ıneas para un comando, 363

364

´ APENDICE F. MAKE & MAKEFILE.

se deber´ poner un backslash (\) al final de cada l´ ıa ınea del comando. El comando make conectar´ las l´ a ıneas como si hubieran sido escritas en una unica l´ ´ ınea. En esta situaci´n, se o deben separar los comandos con un punto y coma (;) para prevenir errores en la ejecuci´n de o el shell. Los comandos deben ser indentados con un tabulador, no con 8 espacios Make lee el Makefile y determina para cada archivo destino (empezando por el primero) si los comandos deben ser ejecutados. Cada destino, junto con los prerrequisitos o dependencias, es denominado una regla. Si make se ejecuta sin argumentos, s´lo se ejecutar´ el primer destino. Veamos un ejemplo: o a file.o: file.cc file.h g++ -c file.cc En este caso se comprueban las fechas de las ultima modificaciones de los archivos file.cc y ´ file.h; si esta fecha es m´s reciente que las del archivo file.o se procede a la compilaci´n. a o El comando make se puede suministrar con un argumento, que indica la etiqueta situada a la izquierda de los dos puntos. As´ en el ejemplo anterior podr´ invocarse make file.o.. ı ıa Gracias a las variables, un Makefile se puede simplificar significativamente. Las variables se definen de la siguiente manera: VARIABLE1=valor1 VARIABLE2=valor2 Una variable puede ser utilizada en el resto del Makefile refiri´ndonos a ella con la expresi´n e o $(VARIABLE). Por defecto, make sabe las ´rdenes y dependencias (reglas impl´ o ıcitas) para compilar un archivo *.cc y producir un archivo *.o, entonces basta especificar solamente las dependencias que make no puede deducir a partir de los nombres de los archivos, por ejemplo: OUTPUTFILE = prog OBJS = prog.o misc.o aux.o INCLUDESMISC = misc.h aux.h INCLUDESFILE = foo.h $(INCLUDESMISC) LIBS = -lmylib -lg++ -lm prog.o: $(INCLUDESFILE) misc.o: $(INCLUDESMISC) aux.o: aux.h $(OUTPUTFILE): $(OBJS) gcc $(OBJS) -o $(OUTPUTFILE) $(LIBS) Las reglas patrones son reglas en las cuales se especifican m´ltiples destinos y construye u el nombre de las dependencias para cada blanco basada en el nombre del blanco. La sintaxis de una regla patr´n: o destinos ... : destino patron:dependencias patrones comandos La lista de destinos especifica aquellos sobre los que se aplicar´ la regla. El destino patr´n y a o las dependencias patrones dicen c´mo calcular las dependencias para cada destino. Veamos o un ejemplo:

365 objects = foo.o \ bar.o all: $(objects) $(objects): %.o: %.cc $(CXX) -c $(CFLAGS) $< -o $@ Cada uno de los destinos (foo.o bar.o) es comparado con el destino patr´n %.o para extraer o parte de su nombre. La parte que se extrae es conocida como el tronco o stem, foo y bar en este caso. A partir del tronco y la regla patr´n de las dependencias %.cc make construye los o nombres completos de ellas (foo.cc bar.cc). Adem´s, en el comando del ejemplo anterior a aparecen un tipo de variables especiales conocidas como autom´ticas. La variable $< mana tiene el nombre de la dependencia actual y la variable $@ mantiene el nombre del destino actual. Finalmente un ejemplo completo:

# # Makefile para el programa eapp #_________________________________________________________ CXX = g++ CXXFLAGS = -Wall -O3 -mcpu=i686 -march=i686 #CXXFLAGS = -Wall -g LIBS = -lm BIN = eapp OBJECTS = eapp.o md.o atoms.o vectores.o metalesEA.o Monte_Carlo.o\ string_fns.o nlista.o rij2.o velver2.o cbc2.o nforce.o \ temperature.o controles.o inparamfile.o \ azar.o velver3.o funciones.o observables.o $(BIN): $(OBJECTS) $(CXX) $(OBJECTS) -o $(BIN) $(LIBS) $(OBJECTS): %.o:%.cc $(CXX) -c $(CXXFLAGS) $< -o $@ clean: rm -fr $(OBJECTS) $(BIN) #End

366

´ APENDICE F. MAKE & MAKEFILE.

Ap´ndice G e Herramientas b´sicas en el uso de a L.A.M.P.
L.A.M.P. es la sigla popular para referirse al uso conjunto: Linux+Apache+Mysql+PHP (tambi´n ´sta ultima se reemplaza por Python o Perl) . e e

G.1.

Objetivo.

Se espera que tras leer este ap´ndice el lector interesado sea capaz de: e Elaborar sus propias paginas web utilizando PHP, a partir de las cuales se pueda intercambiar informaci´n de manera segura mediante el sistema gestor de base de datos o MySql.

G.2.

Prerequisitos

Conocimiento b´sico sobre qu´ es un navegador, es decir, tener cierto tiempo utiliz´ndoa e a lo. Tener instalados y operando conjuntamente los siguientes programas: • Apache 1.3 o superior. • MySql 4 o superior. • PHP 4 o superior.

G.3.

Breve referencia sobre paginas web.

Un navegador es un software que mediante la conexi´n a Internet interpreta scripts preo sentes en el servidor web, desplegando el resultado en pantalla. Dichos scripts normalmente se encuentran escritos en lenguaje html. La gran ventaja que ofrecen las p´ginas web son los llamados hiperv´nculos o links: objetos a ı que permiten saltar entre diferentes p´ginas web de manera f´cil. Gracias a los links existen a a 367

368

´ ´ APENDICE G. HERRAMIENTAS BASICAS EN EL USO DE L.A.M.P.

los “´rboles de p´ginas”: diferentes scripts interconectados mediante links correspondientes a a a un mismo dominio1 . Una p´gina como la anteriormente descrita es capaz de desplegar a informaci´n en un navegador o recibirla a trav´s de formularios. Este tipo de p´ginas reciben o e a el nombre de p´ginas est´ticas, es decir, si se quiere cambiar la informaci´n desplegada, se a a o est´ obligado a modificar el script en html. a En contraste, existen p´ginas que cambian su informaci´n dependiendo de cu´ndo o c´mo a o a o son ejecutadas, recibiendo el nombre de p´ginas din´micas. Para lograr el dinamismo, el a a servidor, tras leer una serie de archivos, genera un nuevo c´digo en html a tiempo de ejecuci´n. o o Ejemplos de dichas p´ginas son aquellas visitadas a diario por cualquier persona: buscadores, a bancos en l´ ınea, correos electr´nicos revisados desde un navegador, etc. Para generar este o tipo de p´ginas existen muchos lenguajes de programaci´n, sin embargo, el m´s utilizado y a o a sobre la que se introducir´ aqu´ es el lenguaje PHP. a ı

G.3.1.

Ejemplos

P´gina Est´tica en html. a a • Archivo hola.html <html> <title> :::::El Clasico Hola mundo::: </title> <body> Hola mundo! </body> </html> El ejemplo anterior corresponde a lo m´s simple en una p´gina web en html ; notar que el a a script est´ estructurado mediante el uso de etiquetas del tipo: <algo> .... </algo>. a P´gina Din´mica en PHP a a • Archivo hola.php <html> <?php $h="Hola mundo!"; ?> <title> :::::El Clasico <?php echo $h; ?>::: </title> <body> <?php echo $h; ?> </body> </html> Si se procede a ejecutar ambos scripts probablemente no se aprecie ninguna diferencia; sin embargo, el proceso que se ha llevado a cabo por el servidor establece fuertes diferencias entre ambos c´digos. Notar que el c´digo en PHP se encuentra inserto por completo en el o o c´digo html. Por lo anterior, es necesario tener, al menos, un conocimiento b´sico de html o a para comenzar a programar en PHP.
1

Nombre del sitio Internet.

G.4. ADMINISTRADOR DE BASES DE DATOS.

369

G.4.

Administrador de Bases de datos.

Una base de datos es una manera ordenada de guardar cualquier tipo de informaci´n o para, de este modo, facilitar su b´squeda posterior. El encargado de buscar la informaci´n u o de manera efectiva es el administrador de la base de datos; en nuestro caso, el administrador corresponder´ al software MySql. La informaci´n de la base de datos se almacena en matrices a o llamadas tablas, conformadas por columnas definidas. Las diferentes filas de una tabla se van constituyendo conforme se agregan nuevos registros; la informaci´n contenida en los registros o corresponde a un conjunto de strings o n´meros. u

G.5.

Servidor Web.

Un servidor Web es un software que opera en la m´quina remota. El servidor posee la a informaci´n contenida en la p´gina y su funci´n es proporcionar al internauta el contenido de o a o ´sta. Para efectos de este ap´ndice, esto se reduce a interpretar el c´digo en PHP y generar e e o en tiempo de ejecuci´n el nuevo script en html. o

Creando scripts.
En las secciones posteriores se listar´n los comandos que permiten generar scripts, el a modo de chequearlos y, de esta forma, aprender mediante ensayo y error es: crear la carpeta ~/public_html. Escribir un script en el directorio antes citado utilizando alg´n editor2 . u abrir el navegador e ir a la URL http://nombredelhost/~nombredelusuario/pathdelscript. Luego de seguir estos pasos, el navegador desplegar´ en la pantalla la ejecuci´n del script. a o Es importante se˜alar que el navegador no acusa errores de manera tan implacable como n compiladores u otros int´rpretes (p.ej. Python), por lo cual se recomienda ser especialmente e riguroso.

G.6.

P´ginas B´sicas en html. a a

Pr´cticamente todo el c´digo en html corresponde a aspectos est´ticos de la p´gina, sobre a o e a lo cual no se profundizar´. Entre los objetivos que se buscan alcanzar en este ap´ndice, presena e tan especial relevancia los formularios, pues permiten introducir informaci´n proporcionada o por un internauta a la base de datos.
2

Existen varios editores especializados en lenguajes web sobre los cuales conviene averiguar un poco.

370

´ ´ APENDICE G. HERRAMIENTAS BASICAS EN EL USO DE L.A.M.P.

G.6.1.

Estructura de una p´gina en html. a

Si bien el navegador es capaz de interpretar correctamente c´digo en html escrito sin o seguir las reglas, es importante al menos saber algunas. Todo el dise˜o de la p´gina se encuentra entre etiquetas del tipo <algo> .... </algo>. n a Las m´s relevantes y que le dan estructura son: a <html>: Esta etiqueta delimita en qu´ parte del script comienza y termina el c´digo en e o html. <title>: Lo que se escriba dentro de esta etiqueta conformar´ el t´ a ıtulo de la p´gina, a es decir, el nombre que aparecer´ en el t´ a ıtulo de la ventana del navegador. <head>: Contiene etiquetas y contenidos del encabezado. Principalmente datos que no aparecen en la p´gina, pero que son relevantes. a <body>: Contiene la informaci´n que ser´ desplegada en la pantalla, ya sea texto im´geo a a nes, sonido, etc. Cabe destacar que ninguna de las etiquetas mencionadas es obligatoria; puede precindirse de ellas si tan s´lo se quiere escribir texto sin ninguna estructura. o

G.6.2.

Algo de estilo.

Las etiquetas utilizadas para dar estilo al texto dentro del cuerpo de la p´gina (i.e. a etiqueta <body>) son: Propiedades del texto. <p>: Delimita un p´rrafo que finalizar´ al cerrarse la etiqueta. Esta etiqueta admite a a opciones especiales de alineaci´n tales como: <p align="center">, la cual centra el o p´rrafo. Las variantes obvias de las otras alineaciones son dejadas al lector. a <h1>:Delimita un t´ ıtulo de porte variable en dependencia del n´mero que se ponga u acompa˜ando a la letra h, dicho n´mero debe estar entre 1 y 6. n u <br>: Introduce un salto de l´ ınea. A diferencia de las etiquetas anteriores, ´sta no tiene e una etiqueta de cerrado. <hr>:Introduce una l´ ınea horizontal. Al igual que en la etiqueta anterior, ´sta es dese apareada. <b>: Todo lo escrito dentro de esta etiqueta quedar´ en negritas. a <em>: Convierte en it´lica todo el texto dentro de esta etiqueta. a <u>: Subraya el texto dentro de la etiqueta. <sub>: Convierte en sub´ ındice los caracteres dentro de esta etiqueta.

´ ´ G.6. PAGINAS BASICAS EN HTML. <sup>: Convierte en super´ ındice los caracteres delimitados por la etiqueta.

371

<font>: Etiqueta que permite definir atributos sobre el texto, tales como el porte o el color. Por ejemplo, si se requiere texto en rojo: <font color="red">. Propiedades globales de la P´gina. a Con las etiquetas anteriormente explicadas es posible crear una p´gina con informaci´n a o de manera relativamente ordenada, mas no est´tica. Un primer paso en esta ultima direcci´n e ´ o es lo que se tratar´ a continuaci´n. a o Todos los atributos globales corresponden a opciones de la etiqueta <body>. Lo que se har´ es definir los colores de: el texto, los links, links ya usados y el fondo. En html los colores a se especifican mediante un c´digo (para conocer el c´digo correspondiente a cada color puede o o consultarse la tabla de colores (G.2) al final de este ap´ndice3 ).Lo anterior puede apreciarse e en el siguiente ejemplo: <body bgcolor="#000000" text="#ffffff" link="#ffff33" alink="#ffffcc"> El campo bgcolor corresponde al color de fondo; text al color del texto; link y alink, a los colores de los links por visitar y visitados respectivamente. Alternativamente, es posible poner una foto de fondo de p´gina, simplemente hay que a suplir bgcolor por: <body background="fondo.jpg"> Se recomienda poner fotos peque˜as que sean visualmente agradables como mosaicos, de n lo contrario, puede variar el c´mo se vean dependiendo del navegador, adem´s de hacer m´s o a a pesada la p´gina. El siguiente ejemplo utiliza las herramientas desarrolladas. a Ejemplo • Archivo ejemplo2.html

<html> <title> :::Herramientas de estilo::: </title> <body bgcolor="#336699" text="#000033" link="#660000" alink="#33ff00"> <h1 align="center" > <font color="red"> Sobre lo que se hablar´ en esta p´gina est´tica a a a </font> </h1> <p align="right"> <em> ...Aqu´ por ejemplo una cita para comenzar</em> ı </p> <br> <p algin="center"> Escribiendo la parte medular de la p´gina.....<br> a Es posible escribir una formula sin caracteres especiales como la siguiente: <p align="center">(a<sub>11</sub>+a<sub>22</sub>+....)<sup>2</sup>=(traza)<sup>2</sup></p
3

La cual por razones obvias debe ser vista a color.

372

´ ´ APENDICE G. HERRAMIENTAS BASICAS EN EL USO DE L.A.M.P.

<p align="left"> Finalmente, se espera un manejo <b> b´sico </b> de <em> html </em> si se ha logrado comprender a <u> este ejemplo por completo </u></p> </body> </html> Otros recursos. Como se se˜al´ en la introducci´n, la caracter´ n o o ıstica m´s relevante de una p´gina web es a a su capacidad de interconexi´n con otras mediante links. Asimismo, existen otros recursos o ampliamente usados que mejoran el aspecto y orden de una p´gina en html. a Insertando una imagen e Para insertar una imagen existe una etiqueta desapareada4 , en ´sta debe darse el path relativo del archivo gr´fico de la siguiente forma: a <img src="path"> Tambi´n se pueden especificar atributos adicionales, tales como: la alineaci´n, el espacio e o vertical y horizontal utilizado por la foto: <img src="path" align="left" hspace="20" vspace="30"> En la orden anterior, la imagen (dentro del espacio que puede utilizar) se encuentra alineada a la izquierda y tiene un marco de "20" horizontal por "30" vertical. Links. El enlace, es decir, el espacio de la p´gina donde el cursor del mouse cambia y permite a acceder a la p´gina siguiente, puede corresponder tanto a texto como a una imagen: a Enlace en el texto: Para esto existe la etiqueta: <a href="path_a_la_p´gina_en_cuestion">texto clickeable del link</a> a a Los path pueden ser relativos5 si se trata de material presente en la misma m´quina; de tratarse de un enlace externo a la p´gina, debe especificarse la URL completa. a Enlace sobre una imagen: Opera exactamente de la misma manera que un enlace de texto y solo cambia el argumento dentro de la etiqueta. <a href="path_a_la_p´gina_en_cuestion"><img src="path"></a> a
4 5

No tiene otra etiqueta de cierre Respecto al c´digo que se est´ ejecutando o a

´ ´ G.6. PAGINAS BASICAS EN HTML. Tablas.

373

Una tabla permite administrar el espacio en una p´gina de manera eficiente y es especiala mente util cuando se quiere una p´gina ordenada y sin muchas caracter´ ´ a ısticas gr´ficas. La a tabla es delimitada por la etiqueta <table>, dentro de ´sta, las filas quedan delimitadas por e la etiqueta <tr>. A su vez, el elemento de cada columna queda atrapado en la etiqueta <td>. Dentro de los elementos de la tabla es posible utilizar pr´cticamente cualquier etiqueta. A a continuaci´n, un esquema sobre c´mo se programa una tabla: o o
<table> <tr> <td> "a11"</td> <td>"a12"</td> <td>"a13"</td> <td>"a14"</td> </tr>

<tr> <td> "a21"</td>

<td> "a22"</td>

<td> "a23"</td>

<td> "a24"</td>

</tr>

<tr>

<td> "a31"</td>

<td> "a32"</td>

<td> "a33"</td>

<td> "a34"</td>

</tr>

<tr>

<td> "a41"</td>

<td> "a42"</td>

<td> "a43"</td>

<td> "a44"</td> </table>

</tr>

Figura G.1: Esquema de una tabla en html, utilizando los elementos de una matriz.

G.6.3.

Formularios.

Toda la preparaci´n previa que se ha llevado a cabo tiene como fin el proveer de interfaz o gr´fica a la p´gina din´mica. El instrumento que permitir´ recibir informaci´n desde el visia a a a o tante son los formularios, el qu´ se hace con dicha informaci´n escapa de las posibilidades de e o html. Para procesar la informaci´n debe recurrirse a otros lenguajes. o Manejo de la informaci´n utilizando el formulario. o Todo formulario se encuentra definido dentro de la etiqueta <form>, la cual contiene algunos atributos que especifican qu´ hacer con la informaci´n. Sin entrar en complicaciones, e o s´lo se se˜alar´ que para poder recuperar la informaci´n contenida en un formulario deben o n a o definirse los siguientes atributos: <form method="post" action="path_del_archivo_que_recupera_las_variables.php"> El atributo method="post" determina de qu´ forma es almacenada la informaci´n; el e o atributo action="archivo.php", indica el nombre del archivo al cual es exportada dicha informaci´n. o Dise˜ o de formularios. n Existen una serie de formularios que deben escogerse seg´n lo requiera la clase de p´gina u a que se ´ste programando. A continuaci´n se listan las etiquetas para implementar los de e o

374

´ ´ APENDICE G. HERRAMIENTAS BASICAS EN EL USO DE L.A.M.P.

mayor uso, recu´rdese que se est´ dentro de un formulario y por lo tanto dentro de una e a etiqueta <form>. Cajas de texto: Para crear una dentro del formulario basta escribir: <input type="text" name="Nombre_de_la_informaci´n"> o Si bien son v´lidas otras etiquetas adicionales, cabe destacar que el atributo type tama bi´n admite otras alternativas de rellenado tales como password, el cual oculta el texto e introducido. Usualmente, la informaci´n recaudada en los formularios es procesada de o manera algor´ ıtmica, por lo que conviene dar menos libertad sobre qu´ informaci´n es e o ingresada por el usuario. Para ello se le hace optar, como se muestra en los 3 siguientes dise˜os de formularios. n Listado de opciones: La sintaxis es la siguiente: <select name="escoga"> <option value="op1">nombrealt1</option> <option value="op2">nombrealt2</option> <option value="op3">nombrealt3</option> <option value="op4">nombrealt4</option> </select> Recordar que el listado de opciones debe estar dentro de la etiqueta de formulario, de lo contrario, la informaci´n obtenida de ´ste no ir´ a ning´n lado. El atributo value o e a u corresponde al nombre que se ha asignado a esa alternativa al procesar la informaci´n, o es decir, si por ejemplo la nombrealt1 es escogida, se registrar´ op1 como valor de la a variable escoja cuando se procese el formulario. Botones de radio: La gran ventaja de ´ste sistema es que se obliga al internauta a e optar, la sintaxis es: <input type="radio" name="escoja" value="op1">nombrealt1 <br> <input type="radio" name="escoja" value="op2">nombrealt2 Sobra decir que un formulario puede tambi´n ser mixto, es decir, contener listados de e opciones cajas de textos y/o botones de radio. Envi´ de la informaci´n. o o Una vez que se ha finalizado la definici´n del formulario, debe agregarse un bot´n que o o env´ la informaci´n, el cual corresponde a otro input type. Adicionalmente, si el formulario ıe o es muy largo es posible agregar un bot´n que ponga el formulario en blanco. Las sintaxis son o las siguientes: Bot´n de envi´ de la informaci´n: <input type="submit" value="boton_de_envio"> o o o Bot´n de reseteo: <input type="reset" value="resetear"> o

´ ´ G.6. PAGINAS BASICAS EN HTML. Ejemplos

375

Con las nuevas herramientas es posible construir p´ginas como las expuestas en los sia guientes ejemplos: usando el primer ejemplo de esta secci´n como un archivo de nombre o ejemplo2.html, se puede construir un peque˜o ´rbol de p´ginas con los siguientes 2 scripts. n a a El primer script requiere una foto llamada inicio.jpg en el directorio local. • Archivo ejemplo3.html <html> <title> :::Utilizando los nuevos recursos::: </title> <body bgcolor="#666666" text="#660000" link="#66FF00" alink="#660066"> <hr> <table align="center"><tr><td><a href="ejemplo2.html"> ejemplo<br> anterior </a></td><td> <a href="ejemplo4.html"> <img src="inicio.jpg" align="center" hspace="30" vspace="20"></a> </td> <td> <a href="http://www.uchile.cl">enlace externo</a> </td> </tr></table> <hr> </body> </html> • Archivo ejemplo4.html <html> <title>.::Ejemplo del uso de formularios tipo caja de texto::.</title> <body bgcolor="#000000" text="#FFFFFF" link="#66FF00" alink="#00FF99"> <br> <h2 align="center"> Complete con sus datos y gane!<h2> <form " method="post" action="procesa.php"> <table align="center"> <tr><td> Nombre:</td><td><input type="text" name="Nombre"></td></tr> <tr> <td>e-mail:</td><td> <input type="text" name="email"></td></tr> <tr><td>Telefono:</td><td> <input type="number" name="fono"></td></tr> <tr><td>Direcci´n:</td><td> <input type="text" name="direc"></td></tr> o <tr><td></td><td><input type="submit" value="enviar"></td></tr> </form> </table> </body> </html> Ejemplo de formularios, tipo listado de alternativas: • Archivo ejemplo4b.html <html><title>::Listado de opciones:::</title> <body bgcolor="#000000" text="#FFFFFF" link="#66FF99" alink="#660033"> <h1 algin="left"><u>Particulas subatomicas</u></h1>

376

´ ´ APENDICE G. HERRAMIENTAS BASICAS EN EL USO DE L.A.M.P.

<form method="post" action="psa.php"> <table><tr><td>Particula subatomica:</td> <td><select name="psa"><option value="proton">prot´n</option> o <option value="neutron">neutr´n</option><option value="electron">electr´n</option> o o </td></tr><tr><td></td><td><input type="submit" value="ver"></td></table></form></body></ht A partir de estas herramientas b´sicas en la programaci´n de p´ginas html, es posible a o a comenzar a introducir elementos que cambien dentro de la p´gina a tiempo de ejecuci´n. Esto a o es, la programaci´n en PHP. Sin embargo, primero debe explorarse brevemente el lenguaje o que permite comunicarse con la base de datos.

G.7.
G.7.1.

MySql.
Iniciando sesi´n. o

MySql es un administrador de base de datos que tiene una estructura de usuarios similar a la de UNIX: existe un superusuario llamado root y los usuarios ordinarios, cada uno con su propia cuenta. Se supondr´ en los siguientes ejemplos la posesi´n de una cuenta cuyo nombre a o de usuario es lamp y de palabra clave bd. Para comenzar a interactuar con el administrador de bases de datos, hay que iniciar una sesi´n en ´ste desde la consola del siguiente modo: o e usa@host:$mysql -u lamp -p Enter password: Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 6 to server version: 4.0.24_Debian-10sarge2-log Type ’help;’ or ’\h’ for help. Type ’\c’ to clear the buffer. mysql> La orden que se da desde la consola es: usa@host:$mysql -u lamp -p, que quiere decir: “comienza una sesi´n de MySql con el nombre de usuario lamp (-u lamp) y pide el password o (-p)”. La ultima l´ ´ ınea corresponde al prompt de MySql.

G.7.2.

Creando una base de datos.

A partir de aqu´ puede interactuarse con MySql ; para hacerlo debe conocerse el lenguaje ı de interacci´n llamado Sql, del cual tan s´lo se ense˜ar´n las ordenes b´sicas. Cabe destacar o o n a a que todo lo que se escriba en la consola de MySql debe finalizar con “;”. El primer paso es crear una base de datos, de nombre base, para ello debe introducirse la orden: mysql> create database base; Una vez creada la base de datos se puede comenzar a trabajar. Un usuario de MySql puede tener varias bases de datos dentro de su cuenta, es por ello que cada vez que ´ste se e conecte a MySql ( i.e. se loguee) debe escoger la base de datos que utilizar´; desde la consola a esto se hace escribiendo: mysql> connect base;

G.7. MYSQL.

377

G.7.3.

Creando tablas.

La base de datos ser´ completamente in´til si no se han creado tablas. Probablemente a u esto constituye el paso m´s complicado en el abordaje de un problema a solucionar con una a base de datos, pues es en la estructura de las tablas que quedar´ plasmado el esquema bajo a el cual operar´ lo que se programe. Por ello se recomienda fuertemente pensar este punto a antes que cualquier otro. Para crear una tabla debe especificarse (Al menos): el nombre de la tabla, el nombre de cada campo y el tipo de cada campo. Sup´ngase el caso simple de o una tabla con tel´fonos llamada “agenda”, esta tabla debe contener al menos dos campos: e nombres, que contenga texto, y tel´fono, que contenga n´meros. Para crear tal tabla debe e u introducirse: mysql> create table agenda(nombre text, telefono int); O en general:

mysql> create table nombretabla(campo1 tipo, campo2 tipo,.......,campo_i tipo); Podr´ juzgarse el ejemplo demasiado simple, pues no queda claro de cu´ntos tipos pueden ıa a ser los campos en una tabla; como la intenci´n no es extenderse, se recomienda instalar el o script en PHP llamado phpmyadmin 6 , el cual permite una administraci´n de la base de o datos desde el navegador de una forma bastante m´s intuitiva y did´ctica que simplemente a a interactuando con la consola. No se debe abusar del uso de esta interfase, pues es fundamental conocer la sintaxis para interactuar con la base de datos ya que justamente son ´stas ´rdenes e o las que se incluyen en los scripts.

G.7.4.

Interactuando con la Tabla.

Teniendo la capacidad para crear bases de datos y, dentro de ´stas, crear tablas, lo que e resta es aprender a: insertar, buscar y remover registros de una tabla. Para ilustrar estas acciones se continuar´ con el ejemplo de la agenda telef´nica. a o Escribiendo nuevos registros en la tabla: sentencia7 INSERT. Sup´ngase que se quiere ingresar un nuevo usuario llamado “Pedro” de n´mero telef´nio u o co “5437896”. Para ello debe escribirse en la consola: mysql> insert into agenda(nombre,telefono) values ("Pedro",5437896); o en general:

mysql> insert into nombre_tabla(campo1,campo2,.....,campoj,..) values (valcampo1, valcampo2,....,valcampoj,...);
6 7

Disponible para la distribuci´n Debian GNU/Linux. o Tanto MySql como html no son sensibles a las may´sculas al escribir scripts. u

378

´ ´ APENDICE G. HERRAMIENTAS BASICAS EN EL USO DE L.A.M.P. Notar que los string deben ir entre comillas dobles o simples, no as´ los n´meros. Si se ı u escribe dos veces el mismo registro, la base de datos guardar´ dos registros diferentes a con exactamente la misma informaci´n y los diferenciar´ por su fecha de ingreso. o a Removiendo registros: sentencia DELETE. Sup´ngase que se quiere borrar exclusivamente a Pedro; para ello debe escribirse: o mysql> delete from agenda where nombre=’Pedro’; Notar la aparici´n de la condici´n WHERE, la cual especifica a qui´n borrar; de truncar o o e la sentencia antes de esta condici´n, MySql borrar´ todos los registros de la tabla. o a Como es de esperarse, se podria haber identificado a qui´n se quer´ eliminar mediante e ıa cualquier otro campo. El administrador se podr´ preguntar c´mo borrar la cantidad ıa o de usuarios que quiera de manera efectiva haciendo algo similar a lo que permite bash, esto es posible y f´cilmente deducible de la sentencia select. a Buscando registros en la base de datos: sentencia SELECT. La sintaxis de la sentencia SELECT es la siguiente: mysql> select nomcampo from nomtabla where condiciones; Un par de ejemplos para ilustrar lo anterior: • Seleccionar todos los elementos: mysql> select * from agenda; Listar´ todos los elementos de la agenda. a • Seleccionar todos los nombres de la agenda: mysql> select nombre from agenda; Listar´ todos los nombres de la agenda (´ a ıdem con los tel´fonos). e • Seleccionar el par (tel´fono, nombre) del usuario “Andrea”: e mysql> select telefono,nombre from agenda where nombre=’Andrea’; • Operadores l´gicos: tambi´n es posible ser m´s espec´ o e a ıfico mediante operadores l´gicos como OR o AND, los cuales funcionan como se esperar´ Esto sirve para, o ıa. por ejemplo, corroborar la existencia de un registro. Sup´ngase que se conoce el o tel´fono “5534126” y se tiene la sospecha de que pertenece a “Andrea”. Para ello e puede digitarse: mysql> select * from agenda where nombre=’Andrea’ and telefono= 5534126; Si no retorna ning´n registro quiere decir que Andrea no tiene ese n´mero. Alteru u nativamente, para obtener m´s informaci´n se puede escribir: a o mysql> select * from agenda where nombre=’Andrea’ or telefono= 5534126; Listar´ todos los registros que cumplan alguna o ambas condiciones. a • Mostrar registros que contengan informaci´n diferente: o

G.7. MYSQL. mysql> select ncampos DISTINCT FROM ntabla where condiciones

379

• Orden: La mayor´ de las veces es necesario saber parcialmente de qu´ forma vendr´n ıa e a los datos listados, para ello es necesario introducir un orden y una tolerancia, de esta forma es posible controlar exactamente qu´ hacer aparecer en el resultado de e la b´squeda. Sup´ngase que se quieren mostrar todos los elementos de la agenda u o ordenados alfab´ticamente por nombre, para esto hay que escribir: e mysql> select * from agenda order by nombre; Queda claro que hace la condici´n ORDER BY. Sup´ngase que se desea invertir el o o orden y poner los ultimos 3 registros, para ello debe escribirse: ´ mysql> select * from agenda order by nombre desc limit 3; La condici´n DESC exige un orden descendente, mientras que LIMIT, acompa˜ado o n de un entero, da la cantidad m´xima de registros que pueden aparecer como resula tado de la b´squeda. Resulta especialmente importante hacer ´rdenes con n´meu o u ros, pues permiten utilizar comparadores aritm´ticos. Sup´ngase que se tiene una e o tabla llamada usuarios que contiene los campos edad y nombre de personas. Para encontrar los mayores de edad deber´ escribirse: ıa mysql> select * from usuarios where edad >= 18;

Actualizaci´n de datos, sentencia: UPDATE. o Esta sentencia permite la actualizaci´n de los datos, es decir, toma un registro viejo o y le modifica alg´n campo. Sup´ngase que en el ejemplo de la agenda telef´nica se u o o quiere cambiar el tel´fono a un usuario llamado “Juan”, quien tiene un nuevo tel´fono e e “8571646”. Para hacerlo debe introducirse la orden: mysql> update agenda set telefono=8571646 where nombre=’Juan’; Es evidente la funci´n de SET en la sintaxis; de no especificarse WHERE y truncarse la o frase, se cambiar´ el tel´fono de todos los registros por el nuevo n´mero. ıa e u Funciones sobre los campos. Existen, adem´s, funciones que pueden aplicarse sobre los campos, las cuales pueden a investigarse utilizando phpmyadmin. Se ver´ un ejemplo simple: en presencia de una tabla a con informaci´n importante como contrase˜as, ser´ necesario alg´n sistema de seguridad o n ıa u sobre ellas. Para esto existe la funci´n PASSWORD, la cual encripta el argumento. La tabla o se llama registrados y contiene 2 campos: Nombre tipo texto y clave tipo VARCHAR. Se sabe como crear una tabla e insertar registros. La siguiente sintaxis muestra la diferencia hecha por la funci´n PASSWORD: o

380

´ ´ APENDICE G. HERRAMIENTAS BASICAS EN EL USO DE L.A.M.P.

mysql> create table registrados (nombre text, clave VARCHAR(20)); mysql> insert into registrados (nombre, clave) values (’andres’,’te45’); mysql> select * from registrados; +--------+-------+ | nombre | clave | +--------+-------+ | andres | te45 | +--------+-------+ 1 row in set (0.00 sec) Se procede a encriptar la clave. mysql> update registrados set clave=PASSWORD(’te45’) where nombre=’andres’; mysql> select * from registrados; +--------+------------------+ | nombre | clave | +--------+------------------+ | andres | 37d3b95821add054 | +--------+------------------+ Se ha expuesto lo m´s b´sico para poder interactuar con la base de datos. El conocimiento a a de esta sintaxis volver´ m´s r´pidos, seguros y eficientes lo programado; sin embargo, el a a a alcance del ap´ndice utilizar´ tan s´lo las herramientas aqu´ expuestas. e a o ı

G.8.

Programaci´n en PHP. o

Los 2 lenguajes antes vistos no tienen relaci´n entre s´ y, de hecho, no podr´n funcionar o ı a en conjunto de no ser por el lenguaje PHP. Este lenguaje es interpretado por un m´dulo del o servidor web, por ello, el c´digo en PHP nunca abandona el servidor, es decir, el internauta o no puede ver la fuente en PHP visitando la p´gina. a Para el estudiante de este ap´ndice se espera un aprendizaje muy r´pido de PHP por su e a similitud con bash y C++. En lo sucesivo, todo el trabajo de PHP ser´ comunicarse con la a base de datos y manipular los recursos de html de manera din´mica. a

G.8.1.

Lenguaje PHP.

Como ya fue se˜alado en la introducci´n, el lenguaje en PHP se encuentra inserto dentro n o del html. Esto significa que el script est´ escrito principalmente en html con trozos en PHP. a Todo el c´digo en PHP queda delimitado por las etiquetas <?php... aqui todo el codigo en php .... ?>. o Al igual que en bash, las variables van antecedidas por un s´ ımbolo $, por otra parte, al igual que en C++ cada l´ ınea de c´digo debe ir finalizada por un “;”. o Si se regresa con esta nueva visi´n sobre el primer ejemplo de p´gina din´mica expuesto o a a en este ap´ndice, se tendr´: e a

´ G.8. PROGRAMACION EN PHP. P´gina Din´mica en PHP a a • Archivo hola.php <html> <?php $h="Hola mundo!";?> <title> :::::El Clasico <?php echo $h; ?>::: </title> <body> <?php echo $h; ?> </body> </html>

381

Lo que ocurre al escribir esta p´gina en el navegador es lo siguiente: el servidor web a procesa el script interpretando el c´digo delimitado en PHP, generando a tiempo de ejecuci´n o o el siguiente nuevo script en html, el que es interpretado por el navegador. <html> <title> :::::El clasico Hola Mundo!:::</title> <body> Hola Mundo! </body> </html> Debe quedar completamente claro que el c´digo en PHP jam´s abandona el servidor web, o a por lo tanto, el c´digo en PHP se encuentra inserto dentro del html y no viceversa. Dentro o de un script en html es posible, las veces que sea necesario y donde sea necesario, escribir c´digo en PHP. o

G.8.2.

Variables.

Las variables en PHP pueden ser string, n´meros o arreglos. Para desplegar en pantalla u una variable se utiliza la instrucci´n echo. El ejemplo anterior constituye un caso simple de o esto.

G.8.3.

Recuperando variables desde un formulario.

En el formulario del ejemplo 4, ´ste enviaba v´ post las variables al archivo procesa.php. e ıa Ahora se proceder´ a crear dicho archivo operando sobre las variables. a Ejemplo • Archivo procesa.php <html><title> recuperando las variables </title> <body bgcolor="#000000" text="#FFFFFF" link="#66FF00" alink="#00FF99"> <h2 align="center"> La informaci´n tirada a pantalla<h2> o <p align="center"> Tu nombre es <b><?php echo $_POST[’Nombre’];?></b> ,vives en <b> <?php echo $_POST[’direc’]; ?> </b>. Tu e-mail es <b> <?php echo $_POST[’correo’]; ?> </b> , adem´s tu tel´fono es <?php echo $_POST[’fono’];?></p></body> </html> a e

382

´ ´ APENDICE G. HERRAMIENTAS BASICAS EN EL USO DE L.A.M.P.

Este archivo simplemente toma las variables y las despliega en pantalla. Se debe notar que la informaci´n contenida en un formulario queda contenida en el grupo de variables o $_POST[’nombredelavariable’]. Con este conocimiento es posible rehacer todo ejercicio propuesto en el cap´ ıtulo de C++ donde se pidan variables y opere con ellas en PHP. Cabe destacar todo lo que es posible mezclar html y PHP.

G.8.4.

Control de flujo.

Las sintaxis de los controles de flujo m´s usuales en PHP son exactamente iguales a los ya a conocidos de C++. A continuaci´n se dan ejemplos de los bucles while y if respectivamente. o Cabe destacar que el uso de “.” pega los string. ejemplo while <?php $i=1; $j="Ejemplo de un bucle haciendo iteraciones, iteracion no :";?> <html><body bgcolor="#336699" text="000033" link="660000" alink="#33ff00"> <h2 align=’center’> LOOP <em> while </em>. </h2> <p align="right"> <?php while($i<10)//comentario en php {echo $j . $i; $i++; ?> <br> <?php } ?> </p></body></html> ejemplo if El condicional if logra que el script haga diferentes cosas seg´n el valor de alguna variable. u A fin de economizar c´digo, a continuaci´n se ejemplificar´ el uso del control de flujo if o o a procesando la informaci´n introducida en el formulario del ejemplo4b.html. La idea es tener o la informaci´n contenida en variables diferentes y que ´sta sea desplegada en la pantalla o e seg´n se elija. La sintaxis del if es exactamente igual que en C++. • Archivo psa.php u <?php $opcion=$_POST[’psa’]; //proton $pmasa="1,672 * 10^27 kg"; $pcarga="1,60217653(14)*10^(-19)C"; $ps="-"; //neutron $nmasa="1,672 * 10^27 kg"; $ncarga="0"; $ns="no tiene carga"; //electron $emasa="9,10 * 10^(-31) kg"; $ecarga="1,60217653(14)*10^(-19)C"; $es="-"; //general

´ G.8. PROGRAMACION EN PHP. $masa; $carga; $signo;

383

if ($opcion=="proton") {$masa=$pmasa; $carga=$pcarga; $signo=$ps;} else if ($opcion=="electron") {$masa=$emasa; $carga=$ecarga; $signo=$es;} else {$masa=$nmasa; $carga=$ncarga; $signo=$ns;} ?> <html><title> informacion</title> <body bgcolor="#000000" text="#FFFFFF" link="#66FF99" alink="#660033"> <table><tr><td>La particula: </td><td> <?php echo $opcion; ?> </td></tr> <tr><td>tiene una masa de :</td><td> <?php echo $masa; ?> </td></tr> <tr><td>tiene una carga de signo :</td><td> <?php echo $signo; ?> </td></tr> <tr><td>tiene una cantidad de carga :</td><td> <?php echo $carga; ?> </td></tr> </table></html>

G.8.5.

Funci´n require. o

Al igual que en todos los dem´s lenguajes estudiados en este curso, PHP posee funciones a intr´ ınsecas a ´l o que pueden crearse. En este ap´ndice tan s´lo se har´ uso de funciones que e e o a vienen ya incluidas en el lenguaje, pues son las primeras que deben conocerse. La funci´n o require pide como argumento alg´n archivo cuando se ejecuta el c´digo. La funci´n se encarga u o o de incluir el archivo y evaluarlo dentro del c´digo. Si el archivo en cuesti´n resulta ser m´s o o a c´digo, ´ste ser´ ejecutado. Usualmente, esto es utilizado para pedir formularios; el uso de o e a esta funci´n se ejemplifica ampliamente en el ejemplo final. o

G.8.6.

Sesi´n. o

PHP tiene la capacidad de definir variables globales sobre un conjunto de p´ginas a a ´ elecci´n; para ello debe realizarse una sesion. Estas son usualmente utilizadas cuando se posee o una estructura de usuarios. Para poder crear una sesi´n debe contarse con: un ´rbol de p´ginas o a a ya armado, una p´gina donde se inicie la sesi´n, y una p´gina donde se termine la sesi´n. Para a o a o ilustrar el uso de las sesiones se considerar´n 4 p´ginas: el formulario del ejemplo4.html; el a a ejemplo anterior procesa.php(con un par de modificaciones) como p´gina de inicio de sesi´n; a o una nueva p´gina ejemplo5.php, que gracias a la sesi´n es capaz de recuperar las variables; a o y una p´gina de cierre de sesi´n salir.php, la cual vuelve al ejemplo4.html. Es importante a o

384

´ ´ APENDICE G. HERRAMIENTAS BASICAS EN EL USO DE L.A.M.P.

adquirir el h´bito de generar ´rboles de p´ginas lo m´s intuitivos posible, pues ´stas suelen a a a a e ser usadas por personas con poco o nulo conocimiento de su construcci´n y gran parte de su o ´xito radicar´ en su simpleza. Sin m´s pre´mbulos, los ejemplos son los siguientes: e a a a Ejemplos. • Nuevo archivo procesa.php <?php session_start();//inicio de la sesi´n o header("Cache-control: private"); //esta l´nea se escribe para no borrar los formularios como lo hace i.e. ı ?> <html><title> recuperando las variables </title> <body bgcolor="#000000" text="#FFFFFF" link="#66FF00" alink="#00FF99"> <h2 align="center"> La informaci´n tirada a pantalla<h2> o <p align="center"> Tu nombre es <b><?php echo $_POST[’Nombre’];?> </b>, vives en <b> <?php echo $_POST[’direc’]; ?> </b>. Tu e-mail es <b> <?php echo $_POST[’correo’]; ?> </b>, adem´s tu tel´fono es <?php echo $_POST[’fono’];?> </p> a e <h1 align="center"> <a href="ejemplo5.php"> <font color="red"> Aqui para seguir </font></a></h1> </body> </html> <?php $_SESSION[’nombre’]= $_POST[’Nombre’]; $_SESSION[’mail’]= $_POST[’correo’]; //Definiendo las variables globales de session.?> • Archivo ejemplo5.php <?php session_start(); ?> <html> <body bgcolor="#000000" text="#FFFFFF" link="66FF00" alink="00FF99"> <table align="center"><tr><td> <b> Las variables aun se recuperan y son: </b></td></tr> <tr><td> <b> El nombre era: <em> <?php echo $_SESSION[’nombre’]; ?> </em> </b></td> </tr> <tr><td> <b> El correo era: <em> <?php echo $_SESSION[’mail’]; ?> </em> </b></td></tr> <h1 align="center"><a href="salir.php"><font color="red">finalizar sesi´n.</font></a></h1> o </table> </body> </html> • archivo salir.php <?php

´ G.8. PROGRAMACION EN PHP. session_start(); session_unset(); header("Location:ejemplo4.html"); echo"<html></html>"; exit; ?>

385

Un par de comentarios sobre los ejemplos: la funci´n session_start() debe ser lo primero o que aparezca en el script, es decir, lo primero registrado por el servidor. Para definir una variable de sesi´n basta asignarla como $_SESSION[’nombre’] la cual existe como variable o global para todas las p´ginas que integren la sesi´n a partir desde donde fue definida la a o variable. Para salir se utiliza la funci´n session_uset(), la cual destruye todas las variables o de la sesi´n. En el ejemplo salir.php se ha utilizado un m´todo que permite redireccionar o e la p´gina de manera autom´tica sobre el cual no se profundizar´. Usualmente, por razones a a a de seguridad, se requiere un ´rbol de p´ginas que sea cerrado, para ello simplemente basta a a definir una variable de sesi´n en la p´gina de entrada y luego, en cada nueva p´gina que o a a integre la sesi´n, anteponer un condicional if que chequee que esa variable exista, es decir, o chequea que se haya pasado por la primera de las p´ginas. Por ejemplo, si se define la variable a de sesi´n $_SESSION[’estado’]="conectado"; en la primera p´gina, una forma de definir o a el condicional es: if ( $_SESSION[’estado’]!= ’conectado’ ) {die( "Ud no esta logueado!.Click aqui para <a href=’ejemplo4.html’>volver</a>");} Esto quiere decir que si la variable de sesi´n ’estado’ es diferente de conectado, niegue la o entrada a la p´gina y despliegue este mensaje. De lo contrario, se continuar´ procesando el a a c´digo. o

G.8.7.

PHP interactuando con MySql.

Si se ha seguido el ap´ndice hasta aqu´ con ´xito, el camino est´ casi completo. Para lograr e ı e a el objetivo final tan s´lo deben introducirse un par de funciones de PHP que permitir´n la o a conexi´n a MySql. Para esto se esquematizar´n los pasos que todo script que se conecta a la o a base de datos debe seguir: 1. Conectarse a MySql. 2. Escoger la base. 3. Determinar si se escribe o se lee desde la base de datos. 4. Escribir la petici´n como variable en un string. o 5. Enviarla (si hab´ que escribir en la base de datos, con esto es suficiente). ıa 6. Si se est´ leyendo desde la base de datos, convertir el resultado en un arreglo y operar a sobre la parte de ´l que se necesite. e

386

´ ´ APENDICE G. HERRAMIENTAS BASICAS EN EL USO DE L.A.M.P.

Siguiendo la numeraci´n respectiva, utilizando el nombre de usuario y contrase˜a de MySql o n antes citado, las funciones son: 1. $conexion=mysql_connect(’localhost’,’lamp’, ’bd’)or die(’No es posible conectar’.mysql_error()); Se conecta al servidor de MySql local bajo el usuario “lamp”. Podr´ parecer en principio ıa un poco inseguro que aparezca la clave del usuario expl´ ıcitamente en el script; sin embargo, recu´rdese que esta parte del script est´ escrita en lenguaje PHP y por lo e a tanto jam´s abandona la m´quina donde se encuentra el script. a a 2. mysql_select_db(’nombredelabase’)or die (’Base no encontrada’); Notar que, a diferencia del ´ ıtem anterior, aqu´ la selecci´n de base no se almacena como ı o variable. 3. Para leer o escribir en la base de datos, basta crear una variable de string con la sintaxis de lo requerido en lenguaje sql. Por ejemplo, sup´ngase que se quiere escribir en o la agenda un nombre guardado en la variable $nombre y un tel´fono almacenado en la e variable $telefono; la sintaxis es: $p="insert into agenda(nombre, telefono) values (’$nombre’,’$telefono’)"; 4. Por otra parte, si quiere escogerse un registro particular, por ejemplo el n´mero teu lef´nico del usuario $usuario , la sintaxis es: o $u="select nombre,telefono from agenda where nombre=’$usuario’"; 5. Independiente de si se quiera leer o escribir, si la petici´n est´ en una variable $p, esta o a se ejecuta en MySql mediante la orden: $pedido=mysql_query($p) or die (’no se pudo’); 6. Sup´ngase que se pidi´ un registro, lo que se obtendr´ de vuelta en la variable $pedido o o a no es un n´mero ni un arreglo. Para poder operar con la informaci´n, primero debe u o convertirse en un arreglo. Dos maneras diferentes de hacerlo son: $fila=mysql_fetch_row($pedido); $arreglo=mysql_fetch_array($pedido); En ambos casos, el arreglo se recorre de la misma manera que en C++. Por ejemplo, en el primer caso, si quiere obtenerse el primer elemento, ´ste corresponder´ a la vae a riable $fila[0].En contraste, el segundo caso, permite seleccionar los elementos del arreglo por su nombre dentro de la tabla de MySql. Por ejemplo, si tenemos una tabla con los campos nombre, direcci´n, entonces los elementos del arreglo corresponden o a $arreglo[’nombre’] y $arreglo[’direcci´n’] respectivamente. En la pr´ctica es o a mucho m´s utilizada esta representaci´n que la de row, pues es m´s f´cil identificar a o a a los elementos. Finalmente, cabe se˜alar que en ambos casos, los arreglos respectivos, n contienen un s´lo registro, pese a que el query, contenga m´s de uno. Para obtener o a todos los registros arrojados por el query, basta recorrerlo con un while, de la siguiente forma.

G.9. EJEMPLO FINAL.

387

//suponiendo conectado a la base, y con la sentencia sql escrita en un string. $pedido=mysql_query($sentencia_mysql); //supong´se que el query de arriba devuelve m´s de un registro, a a // para obtener cada uno basta hacer while($miarreglo=mysql_fetch_array($pedido){echo $miarreglo[’campo’];} ?> Lo anterior desplegar´ en pantalla el contenido de los sucesivos registros en el campo a campo. Lo anterior, tambi´n funciona para mysql_fetch_row. e Con esta secci´n se da por finalizado el ap´ndice; sin embargo, se ha escrito un o e ejemplo final para ver puestas en pr´ctica las herramientas aqu´ expuestas. Se invita al a ı lector a tomarlo como una prueba final de si logr´ un aprendizaje real. o

G.9.

Ejemplo Final.

Se espera haber recorrido con ´xito todos los t´picos de una manera superficial. A fin de e o aclarar cualquier concepto que para el lector haya quedado poco claro, se llevar´ a cabo un a ejemplo simple, el cual debe cumplir el siguiente objetivo: un sistema en l´ ınea donde estudiantes que cursen un ramo puedan averiguar sus notas y promedio de manera personalizada mediante una clave. Se hubiera esperado un ejemplo m´s cient´ a ıfico, sin embargo, todas las herramientas de este ap´ndice apuntan a tareas administrativas m´s que a otra cosa. e a

G.9.1.

Paso I: Estructura de las tablas.

Para todo el ejemplo se tiene el mismo nombre y clave de usuario en MySql que en los ejemplos anteriores. El sistema debe contener una base de datos llamada “ramo” y dentro de ´sta, por lo menos, dos tablas: una con los nombres y contrase˜as de los diferentes alumnos, e n es decir, dos campos y otra con el nombre de cada estudiante y las notas de las respectivas evaluaciones. Para poner una cota superior se crear´n 8 campos de evaluaci´n. Adicionala o mente, se crear´ una tabla que contenga tanto el nombre como la clave del administrador de a este sistema. La creaci´n de la base de datos y las respectivas tablas en la consola de MySql o son por lo tanto:

mysql>create database ramo; mysql>connect ramo; mysql>create table alumnos(Nombre text,clave varchar(20)); mysql>create table notas(Nombre text ,nota1 float, nota2 float, nota3 float, nota4 float, nota5 float, nota6 float, nota7 float, nota8 float); mysql> create table administrador(Nombre text, clave varchar(20)); mysql> insert into administrador(Nombre,clave) values ("administrador", password("admin") ´ Esta es toda la sintaxis que es necesario hacer desde la consola de MySql. Ahora toca “pensar el ´rbol de p´ginas” y la comunicaci´n que tendr´n ´stas con la base de datos. a a o a e

388

´ ´ APENDICE G. HERRAMIENTAS BASICAS EN EL USO DE L.A.M.P.

G.9.2.

Paso II: ´rbol de p´ginas. a a

El ´rbol de p´ginas debe surgir de manera natural a partir de los objetivos que debe a a ´ cumplir lo que se est´ programando. Este se reducir´ a formularios que permitan introducir a a informaci´n, la cual ser´ procesada por otro script en PHP. Si bien existen 2 clases de o a usuarios (el administrador y los usuarios corrientes), todos deben pasar por una p´gina que a les permita “entrar” en el sistema, es decir, ’loguearse’. El archivo expuesto a continuaci´n o es simplemente un formulario que env´ la informaci´n a logueo.php para ser procesada. ıa o • Archivo log.html <html><title> Bienvenido </title><body bgcolor="#66FFFF" text="#660000"> <h1 align="left"> Proceda a identificarse </h1><br><br><br><hr> <form method="post" action="logueo.php"> <table align="left"> <tr><td><b>Nombre de Usuario:</b></td><td> <input type="text" name="nombre"></td></tr> <tr><td><b>Contrase~a:</b></td><td><input type="password" name="clave"></td></tr> n <tr><td><b>tipo de usuario:</b></td> <td><select name="usrcls"><option value="1">usuario</option> <option value="2">administrador</option></td></tr> <tr><td><input type="submit" value="iniciar sesion"></td></tr> </table></form><br><br><br><br><br><hr></body></html> El formulario reci´n expuesto pide 3 datos: el nombre, la contrase˜a y el tipo de usuario e n que est´ intentando ’loguearse’. El script que procesa esta informaci´n debe crear una sesi´n, a o o pues recu´rdese que esto debe ser lo primero que aparezca en el script. Luego debe chequear e que la clave ingresada corresponda a un usuario existente, sin embargo, tambi´n debe realizar e diferentes acciones si se trata de un usuario com´n o del administrador, por lo anterior, este u script funcionar´ en base al condicional if. No debe sorprender la cantidad de c´digo, pues, a o la idea es una sola, cambiando los nombres de las variables: • Archivo logueo.php

<?php session_start(); $nombre=$_POST[’nombre’]; $clave=$_POST[’clave’]; $tipo=$_POST[’usrcls’]; $conexion=mysql_connect(’localhost’,’lamp’, ’bd’)or die(’No es posible conectar’.mysql_error()); mysql_select_db(’ramo’)or die (’error al conectar a la base’); if($tipo==1) {$p="select Nombre,clave from alumnos where Nombre=’$nombre’ and clave=PASSWORD(’$clave’)"; $q=mysql_query($p) or die(’no se pudo hacer el pedido’); $b=mysql_fetch_row($q); if($b==false) {echo "usted no es reconocido por el sistema"; ?> <a href="log.html"><font color="red"> Volver</font></a> <?php}

G.9. EJEMPLO FINAL. else {$_SESSION[’estado’]="conectado"; require(’notas.php’);}} else if($tipo==2) {$p="select Nombre,clave from administrador where Nombre=’$nombre’ and clave=PASSWORD(’$clave’)"; $q=mysql_query($p) or die(’no se pudo hacer el pedido’); $b=mysql_fetch_row($q); if($b==false) {echo "usted no es reconocido por el sistema"; ?> <a href="log.html"><font color="red"> Volver</font></a><?php} else{$_SESSION[’estado’]="conectado"; require(’acciones.php’);}} else{require("log.html");}?>

389

La funci´n del script es la siguiente: primero recupera las variables introducidas en el o formulario y se conecta a la base de datos ramo; despu´s, en funci´n del valor de la variable e o ’usrcls’, decide d´nde buscar la informaci´n del nombre de usuario y claves respectivas. Fio o nalmente, la ultima l´ ´ ınea contempla la posibilidad de que se haya intentado acceder a esta p´gina sin haber pasado por el formulario, requiri´ndol´. A partir de este script, el ´rbol de a e o a p´ginas se bifurca en 2 : la “rama del usuario” y la “rama del administrador”. Los noma bres de las p´ginas ya fueron nombrados en el ultimo script. Se lista a continuaci´n el script a ´ o acciones.php, el cual permite al administrador ingresar informaci´n de manera intuitiva. o Archivo • acciones.php <?php session_start();if ( $_SESSION[’estado’] != ’conectado’ ) {die( "Ud no esta logueado!.Click aqui para <a href=’log.html’>volver</a>");}?> <html><title> Administrando las notas</title> <body bgcolor="#000000" text="#66FF00" link="#CC0033" alink="#66FF66"> <font color="red"><u><a href="salir.php"><h4 align="right"> Cerrar sesi´n.</h4> o <h1 align="center"><font color="blue"> acciones.</h1> <table><tr><td><?php require(’nuser.php’);?></td><td><?php require(’nnota.php’);?> </td></tr></table></body></html> Las primeras l´ ıneas chequean que el usuario se haya “logueado” y especifica el estilo de la p´gina. Luego, se utiliza la funci´n require para solicitar los 2 formularios que corresponden a a o las acciones que pueden ser realizadas por el administrador: crear nuevos usuarios y agregar notas a cada usuario. Ambos formularios son del tipo caja de texto y la informaci´n de ´stos o e es enviada a un archivo del mismo nombre con una “p” final (de procesar). Los archivos que procesan la informaci´n solo escriben directamente en la base de datos la informaci´n o o obtenida de los formularios. Finalmente, cabe destacar el link “cerrar sesi´n”, el cual conduce o a un script que cual destruye todas las variables de sesi´n y devuelve a la p´gina de “logueo” o a log.html, lo que se presenta a continuaci´n: o Archivo • salir.php <?php session_start();if ( $_SESSION[’estado’] != ’conectado’ ) {die( "Ud no esta logueado!.Click aqui para <a href=’log.html’>volver</a>");} session_unset();header("Location:log.html");echo"<html></html>";exit;?>

390

´ ´ APENDICE G. HERRAMIENTAS BASICAS EN EL USO DE L.A.M.P.

A continuaci´n se presentan los scripts que permiten poner notas, crear nuevos usuarios o y sus respectivos archivos de proceso: Archivo • nnota.php. <?php session_start();if ( $_SESSION[’estado’] != ’conectado’ ) {die( "Ud no esta logueado!.Click aqui para <a href=’log.html’>volver</a>");}?> <html><body bgcolor="#000000" text="#66FF00" link="#CC0033" alink="#66FF66"> <br><br><form method="post" action="nnotap.php"><table align="center"> <tr><td><h2>Nueva nota</h2></td></tr> <tr><td>Nombre:</td><td><input type="text" name="nombre"></td></tr> <tr><td>Nota No :</td><td><input type="text" name="nnota"></td></tr> <tr><td>La Nota es:</td><td><input type="text" name="nota"></td></tr> <tr><td></td><td><input type="submit" value="ingresar nota"></table></form></body></html> El archivo que procesa las variables: • nnotap.php <?php session_start();if ( $_SESSION[’estado’] != ’conectado’ ) {die( "Ud no esta logueado!.Click aqui para <a href=’log.html’>volver</a>");} $alumno=$_POST[’nombre’]; $nnota=$_POST[’nnota’];$nota=$_POST[’nota’]; if($nnota>8){echo "el sistema aguanta m´ximo 8 evaluaciones"; require("acciones.php");} a else{$conexion=mysql_connect(’localhost’,’lamp’,’bd’) or die (’No conecta’.mysql_error()); mysql_select_db(’ramo’); $escribe="update notas set nota$nnota=’$nota’ where nombre=’$alumno’"; $haz=mysql_query($escribe); echo "<b>".$alumno. " saco un ".$nota." en la evaluacion no ".$nnota."</b>"; require("acciones.php");}?> Debiera quedar completamente claro lo que ejecuta este script: recupera las variables y revisa que no se haya sobrepasado la cota m´xima de las 8 notas por alumno. De ser as´ procede a ı, a escribir la nueva informaci´n en la base de datos. Cabe notar que la informaci´n no esta o o escrita con la sentencia INSERT, sino UPDATE, por lo cual las notas pueden ser cambiadas. La segunda acci´n habilitada por el administrador es la de agregar nuevos usuarios, lo cual se o hace de una manera totalmente an´loga a los scripts anteriores: a Archivo • nuser.php <?php session_start();if ( $_SESSION[’estado’] != ’conectado’ ) {die( "Ud no esta logueado!.Click aqui para <a href=’log.html’>volver</a>");}?> <html><body bgcolor="#000000" text="#66FF00" link="#CC0033" alink="#66FF66"><br><br> <form method="post" action="nuserp.php"><table align="left"> <tr><td align="center"> <h2>Nuevo registro</h2><br></td></tr> <tr><td>Nombre:</td><td><input type="text" name="nombre"></td></tr> <tr><td>Contrase~a:</td><td><input type="password" name="clave"></td></tr> n <tr><td></td><td><input type="submit" value="ingresar usuario"></td></tr> </table></form></body></html> El archivo que procesa las variables. Archivo • nuserp.php

G.9. EJEMPLO FINAL.

391

<?php session_start();if ( $_SESSION[’estado’] != ’conectado’ ) {die( "Ud no esta logueado!.Click aqui para <a href=’log.html’>volver</a>");} $conexion=mysql_connect(’localhost’,’lamp’,’bd’) or die (’No conecta’.mysql_error()); mysql_select_db(’ramo’); $alumno=$_POST[’nombre’]; $clave=$_POST[’clave’]; $nusuario="insert into alumnos(Nombre,clave) values (’$alumno’,PASSWORD(’$clave’))"; $nusuariob="insert into notas (nombre) values (’$alumno’)"; $escribe=mysql_query($nusuario)or die(’no se pudo escribir’); $escribeb=mysql_query($nusuariob) or die(’no se pudo escribir’); echo "<b> alumno ".$alumno. " ingresado con exito</b>"; require("acciones.php");?> Con esto se da por finalizado el proceso de introducir informaci´n al sistema. Ahora solo o resta generar un script que muestre la informaci´n correspondiente a cada usuario. o Archivo • notas.php

<?php session_start(); $nombre=$_POST[’nombre’]; $clave=$_POST[’clave’]; $conexion=mysql_connect(’localhost’,’lamp’, ’bd’)or die(’No es posible conectar’.mysql_er mysql_select_db(’ramo’)or die (’error al contactar base’); $pedir="select nota1, nota2, nota3, nota4, nota5, nota6, nota7, nota8 from notas where no $pedido=mysql_query($pedir); $notas=mysql_fetch_row($pedido); ?> <html> <title> Notas: </title> <body bgcolor="#333300" text="#3300FF" link="33FF33" alink="#669900"> <h2 align="right"> <a href="salir.php" ><font color="red" <u> Cerrar sesion.</u> </a> </h <h3 align="left"> <font color="green"> Alumno <?php echo $nombre;?></h3> <table align="left"><tr><td><b> Sus notas son</b></td></tr> <tr><td>Eval.No :</td><td>Nota</td><tr> <?php $i=1; $g=0; $cont=0; while($i<=8) { $k=$i-1; echo "<tr><td>". $i . "</td><td>" .$notas[$k]. "</td></tr>"; $i++; if($notas[$k]>=1){$cont++;} $g=$g+$notas[$k]; } if($g==0){echo "usted no tiene notas";} else{$t=$g/$cont;}?> <br><br> <tr><td>Su promedio final es:</td><td><b><?php echo $t; ?> </b> </td></tr> </table>

392 </body></html>

´ ´ APENDICE G. HERRAMIENTAS BASICAS EN EL USO DE L.A.M.P.

Sobre el ultimo ejemplo cabe destacar: se piden todas las notas del alumno en cuesti´n; la ´ o base de datos devuelve para esto la informaci´n que es convertida en fila (mysql_fetch_row()); o luego la fila comienza a ser recorrida utilizando un control de flujo while, el cual va generando a tiempo de ejecuci´n una tabla en html ; las variables auxiliares $i, $g y $cont son utilizadas o para calcular el promedio del n´mero de notas que existan. u

G.10.

Conclusiones.

El ejemplo ha sido chequeado siguiendo los pasos dados en este ap´ndice y funciona de e manera b´sica (pudiendo ser mejorado),pues su fin no es ser operativo, sino explicativo. a Podr´ parecer que se trata de una gran cantidad de c´digo, sin embargo, la mayor parte ıa o del tiempo se est´ repitiendo lo mismo con variaciones obvias. Esperando haber logrado a una comprensi´n aceptable por parte del lector, A partir de las herramientas entregadas, es o posible realizar proyectos bastante m´s ambiciosos tales como: a Sistema de votaciones en l´ ınea. Comunicaci´n mediante mensajes entre usuarios (un rudimentario chat). o Sistema de encuestas en l´ ınea. En general, cualquier problema de administraci´n que involucre diferentes usuarios a o distancia se torna en algo solucionable mediante las herramientas aqu´ desarrolladas. Por ı ultimo, se deja como ejercicio al lector un par de puntos que restan por mejorar del ejemplo ´ final.

G.10.1.

Mejoras al Ejemplo final.

Falt´ lograr: o No se repitan usuarios. Solo existan notas entre 1 y 7. Comunique al administrador cuando ´ste intente ingresar notas a un usuario inexistente. e Sobra decir para el lector con algo de experiencia en programaci´n que todas estos proo blemas ser´n f´cilmente solucionables utilizando el condicional if, de manera de cubrir todas a a las posibilidades. Esto no se ha hecho, pues volv´ el ejemplo demasiado redundante y por lo ıa tanto se ha priorizado su funcionalidad.

G.11. TABLA DE COLORES EN HTML.

393

G.11.

Tabla de Colores en html.

Figura G.2: Los 256 colores posibles de desplegar en una p´gina en html, con su respectivo a c´digo. o

You're Reading a Free Preview

Download
scribd
/*********** DO NOT ALTER ANYTHING BELOW THIS LINE ! ************/ var s_code=s.t();if(s_code)document.write(s_code)//-->