Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica,...

178
Curso de Computación Científica Publicación 2016-09-15 Jorge A Pérez Prieto Teodoro Roca Cortés César Esteban López septiembre 16, 2016

Transcript of Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica,...

Page 1: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación CientíficaPublicación 2016-09-15

Jorge A Pérez Prieto Teodoro Roca CortésCésar Esteban López

septiembre 16, 2016

Page 2: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de
Page 3: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Índice general

1. La Computación Científica y sus herramientas 31.1. ¿En qué consiste? Modelos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31.2. ¿Cómo procedemos? Algoritmos . . . . . . . . . . . . . . . . . . . . . . . . . . 41.3. Aproximaciones en Computación Científica . . . . . . . . . . . . . . . . . . . . . 51.4. Error Absoluto y Error Relativo. Precisión y Exactitud . . . . . . . . . . . . . . . 61.5. Aritmética computacional . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71.6. Ejercicios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8

2. Introducción a la programación con Python 92.1. Empezando con Python . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 102.2. Tipos básicos de datos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 112.3. Operadores aritméticos y lógicos . . . . . . . . . . . . . . . . . . . . . . . . . . 142.4. Cadenas de texto . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 152.5. Impresión de texto y de números . . . . . . . . . . . . . . . . . . . . . . . . . . . 182.6. Estructuras de datos: listas, tuplas y diccionarios . . . . . . . . . . . . . . . . . . 192.7. Módulos y paquetes de Python . . . . . . . . . . . . . . . . . . . . . . . . . . . . 242.8. Información y ayuda sobre funciones y módulos . . . . . . . . . . . . . . . . . . 252.9. Ejercicios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26

3. Análisis de errores 293.1. Tipos de errores . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 293.2. Propagación de errores . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 313.3. Sensibilidad y Acondicionamiento de un problema . . . . . . . . . . . . . . . . . 323.4. Estabilidad y Exactitud de un algoritmo . . . . . . . . . . . . . . . . . . . . . . . 323.5. Ejercicios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33

4. Programas ejecutables 354.1. Reutilizando el código . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 354.2. Definiendo funciones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 374.3. Entrada de datos por pantalla . . . . . . . . . . . . . . . . . . . . . . . . . . . . 404.4. Definiendo un módulo personal . . . . . . . . . . . . . . . . . . . . . . . . . . . 42

I

Page 4: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

4.5. Estructura de un programa o script y normas de escritura . . . . . . . . . . . . . . 434.6. Ejercicios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45

5. Control de flujo 475.1. El bucle for . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 475.2. El bucle while . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 505.3. Sentencias condicionadas if-else . . . . . . . . . . . . . . . . . . . . . . . . . . . 545.4. Declaraciones break y continue y sentencia else en bucles . . . . . . . . . . . . . 565.5. Atrapando los errores. Sentencia try-except . . . . . . . . . . . . . . . . . . . . . 575.6. Una aplicación interesante: Raíces de ecuaciones algebraicas cualquiera . . . . . . 595.7. Ejercicios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59

6. Probabilidad y números aleatorios 636.1. Algunas distribuciones de probabilidad: la Distibución Binomial . . . . . . . . . . 656.2. Ejercicios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68

7. Cálculo numérico con Numpy 697.1. Listas y arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 697.2. Creando arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 707.3. Indexado de arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 717.4. Algunas propiedades de los arrays . . . . . . . . . . . . . . . . . . . . . . . . . . 727.5. Operaciones con arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 737.6. Arrays multidimensionales . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 767.7. Ejercicios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78

8. Análisis estadístico de datos experimentales 798.1. Estadística y parámetros estadísticos . . . . . . . . . . . . . . . . . . . . . . . . . 798.2. La distribución de datos subyacente . . . . . . . . . . . . . . . . . . . . . . . . . 798.3. Sesgo y robustez . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 838.4. Ejercicios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83

9. Lectura y escritura de ficheros 859.1. Creando un fichero sencillo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 859.2. Lectura de ficheros . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 879.3. Lectura y escritura de ficheros de datos con numpy . . . . . . . . . . . . . . . . . 889.4. Ejercicios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89

10. Representación gráfica de funciones y datos 9110.1. Trabajando con texto dentro del gráfico . . . . . . . . . . . . . . . . . . . . . . . 9710.2. Representación gráfica de funciones . . . . . . . . . . . . . . . . . . . . . . . . . 9910.3. Histogramas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10110.4. Figuras diferentes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10210.5. Varios gráficos en una misma figura . . . . . . . . . . . . . . . . . . . . . . . . . 10310.6. Representando datos experimentales . . . . . . . . . . . . . . . . . . . . . . . . . 10410.7. Datos experimentales con barras de error . . . . . . . . . . . . . . . . . . . . . . 10510.8. Representación de datos bidimensionales . . . . . . . . . . . . . . . . . . . . . . 107

II

Page 5: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

10.9. Guardando las figuras creadas . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10910.10.Ejercicios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 110

11. Ajuste de datos experimentales: el método de mínimos cuadrados 11311.1. Formulación general . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11311.2. Aplicación al ajuste de funciones a datos experimentales . . . . . . . . . . . . . . 11411.3. Ajuste a polinomios con Python . . . . . . . . . . . . . . . . . . . . . . . . . . . 11611.4. Ajuste de funciones no lineales . . . . . . . . . . . . . . . . . . . . . . . . . . . 11911.5. Ejercicios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 122

12. Otras aplicaciones de Cálculo Numérico 12512.1. La integración o cuadratura numérica . . . . . . . . . . . . . . . . . . . . . . . . 12612.2. Álgebra matricial . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13112.3. Operaciones básicas con matrices . . . . . . . . . . . . . . . . . . . . . . . . . . 13312.4. Resolución de sistemas de ecuaciones lineales . . . . . . . . . . . . . . . . . . . 13412.5. Ejercicios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 135

13. Apéndice A: Recursos informáticos para el curso 13713.1. El sistema operativo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13713.2. El lenguaje de programación . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13713.3. Python y módulos científicos para Python . . . . . . . . . . . . . . . . . . . . . . 13813.4. Editores de texto . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13913.5. Más documentación y bibliografía . . . . . . . . . . . . . . . . . . . . . . . . . . 140

14. Apéndice B: El sistema operativo GNU/Linux 14314.1. Empezando con Linux: el escritorio de trabajo . . . . . . . . . . . . . . . . . . . 14314.2. Trabajando con la consola de Linux. Directorios y Ficheros. . . . . . . . . . . . . 14414.3. Copiando, moviendo y renombrando ficheros . . . . . . . . . . . . . . . . . . . . 14714.4. Caracteres comodín . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14814.5. Trabajando con ficheros de texto . . . . . . . . . . . . . . . . . . . . . . . . . . . 14814.6. El sistema de usuarios y permisos de Linux . . . . . . . . . . . . . . . . . . . . . 14914.7. Empaquetando y comprimiendo ficheros . . . . . . . . . . . . . . . . . . . . . . 15114.8. Ejercicios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 152

15. Apéndice C: La distribución Gaussiana 15515.1. Propiedades, media y varianza . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15515.2. Población, Muestra y Error estándar de la media . . . . . . . . . . . . . . . . . . 15615.3. La media pesada y su error estándar . . . . . . . . . . . . . . . . . . . . . . . . . 15615.4. Consistencia interna y externa de un conjunto de medidas . . . . . . . . . . . . . 15715.5. Bibliografía . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15815.6. Ejercicios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 158

16. Apéndice D: Cálculo Simbólico 16116.1. Introducción a Sympy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16116.2. Operaciones algebraicas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16316.3. Cálculo de límites . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 164

III

Page 6: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

16.4. Cálculo de derivadas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16416.5. Expansión de series . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16516.6. Integración . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16516.7. Ecuaciones algebraicas y álgebra lineal . . . . . . . . . . . . . . . . . . . . . . . 16616.8. Ejercicios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 169

17. Historial de cambios 17117.1. Revisión 3.2 - Septiembre 2016 . . . . . . . . . . . . . . . . . . . . . . . . . . . 17117.2. Revisión 3.1 - Septiembre 2015 . . . . . . . . . . . . . . . . . . . . . . . . . . . 17117.3. Versión 3.0 - Septiembre 2014 . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17117.4. Versión 2.5 - Noviembre 2013 . . . . . . . . . . . . . . . . . . . . . . . . . . . . 172

IV

Page 7: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

Curso de Computación del 1º del Grado de Física. Universidad de La Laguna.

Edición 3.2

Fecha septiembre 15, 2016

Documentos PDF - ePUB (experimental)

Contenido

Índice general 1

Page 8: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

2 Índice general

Page 9: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

CAPÍTULO 1

La Computación Científica y sus herramientas

1.1 ¿En qué consiste? Modelos

En pocas palabras, consiste en el diseño y análisis de algoritmos para resolver problemas matemá-ticos en muchos campos, especialmente en Ciencia e Ingeniería. Los algoritmos son la traduccióny síntesis, en operaciones algebraicas sencillas, de la solución a problemas de cálculo de diversacomplejidad.

La Física como Ciencia Experimental y Observacional. El objetivo de la física es entender losprocesos de la naturaleza. Esta comprensión se alcanza a partir de una modelización matemáticade las observaciones y/o medidas experimentales. El físico reúne información sobre una serie demagnitudes relevantes en un fenómeno natural, bajo la forma de una o varias medidas u observa-ciones, expresadas como cantidades de una cierta unidad, acompañadas de sus correspondientesincertidumbres e intenta producir un modelo que reproduzca el fenómeno natural.

El modelo matemático. Es un símil matemático que pretende reflejar cierta parte del universo y/osu evolución en el tiempo. Para ser válido, o mejor para ser útil, debe tener dos valores funda-mentales: el de la representación y el de la predicción. El físico debe ser capaz de condensar lainformación obtenida a partir de numerosas observaciones de algún evento en el universo (datos)en una forma reducida (modelo) y ser capaz de evaluar, a partir de él, los posibles resultados futurosde otras observaciones a la vez que entender y explicar resultados obtenidos con anterioridad. Lamayor parte de los modelos implican funciones continuas: longitud, tiempo, temperatura, presión,corriente eléctrica, energía, etc... que no pueden evaluarse matemáticamente de forma exacta.

Los cálculos en los modelos NO pueden resolverse exactamente. Por lo tanto debemos buscar:

1. Un resultado aproximadamente correcto o suficientemente cercano al valor correcto, es de-cir, encontrar algoritmos que converjan rápidamente hacia la solución verdadera (en el lími-te).

2. La forma de evaluar la aproximación de los resultados es decir, estimar la exactitud y/oprecisión de las soluciones aproximadas.

La simulación numérica o computacional. La simulación numérica es la representación y emu-

3

Page 10: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

lación de un sistema o proceso físico utilizando un computador. A los productos obtenidos en lasimulación numérica se les ha venido llamando prototipos virtuales.

1.2 ¿Cómo procedemos? Algoritmos

1.2.1 El proceso de resolver problemas en simulaciones y/o cálculosnuméricos

Generalmente el procedimiento que se sigue para la resolución de problemas incluye los siguientespasos:

1. Desarrollar un modelo matemático del problema.

2. Desarrollar un algoritmo para resolver las ecuaciones de dicho modelo.

3. Implementar el algoritmo en un lenguaje de computación creando un programa o script.

4. Hacer funcionar el programa en un computador.

5. Representar los resultados de la computación.

6. Interpretar y evaluar los resultados y sus errores.

En este curso de introducción a la Computación Científica vamos a aprender a desarrollar estospuntos e insistir especialmente en el 3, 4, 5 y 6.

Desarrollar el primer paso consiste en realizar una modelización matemática. Un problema mate-mático se dice que está bien planteado si:

la solución existe,

es única y,

depende de forma continua de los datos del problema; es decir, que una pequeña variaciónen los datos iniciales no causa grandes cambios en el resultado.

Pero, no siempre es posible obtener problemas bien planteados y entonces se habla de problemaspobremente (o mal) planteados (” ill-conditioned problems”). Aún en problemas bien planteadospueden aparecer problemas de perturbaciones en la computación que deben evitarse con algoritmosestables.

1.2.2 Estrategia general para resolver un problema de computación

Veremos a lo largo del curso que una estrategia básica en la solución de cualquier problema enFísica, en general en Ciencia o en Ingeniería, que requiera de computación es:

Reemplazar un problema difícil o complejo por otro más fácil o simple que tenga la misma solucióno, al menos, una solución ‘muy cercana’ a la del problema original.

4 Capítulo 1. La Computación Científica y sus herramientas

Page 11: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

En general, lo podemos conseguir, por ejemplo, reemplazando según sea el problema que se tengaplanteado:

Funciones complicadas por otras más simples (polinomios, series de Taylor, etc...).

Matrices complejas en general, por otras más simples (diagonales, trangulares, etc...).

Problemas no lineales por otros lineales aunque sean más largos y tediosos.

Ecuaciones diferenciales por sistemas de muchas ecuaciones algebraicas (de diferencias fi-nitas).

Sistemas de orden alto por otros de orden bajo.

Procesos infinitos por otros finitos (integrales por sumatorios, derivadas por diferencias fini-tas, etc...).

Por lo tanto, normalmente debemos: Encontrar un problema alternativo al problema planteado, ouna serie de ellos, que sea más sencillo de solucionar, y que la transformación de uno en otro seatal que preserve la solución del problema original, en algún sentido.

Idealmente, la solución al problema alternativo aproximado no siempre coincide con la del ori-ginal, pero generalmente podremos aproximarla tanto como queramos pagando el precio de másalmacenamiento de datos y/o más trabajo de cálculo. Por lo tanto, debemos estar siempre atentos ala hora de estimar la exactitud y precisión de la solución aproximada y establecer la convergenciahacia la solución verdadera del problema original en el límite apropiado.

1.3 Aproximaciones en Computación Científica

Hay muchas fuentes de aproximación que se suelen utilizar en la computación en diferentes fasesdel desarrollo de la solución al problema planteado. Por ejemplo, algunos de ellos son:

1. ANTES de empezar el cálculo o computación,

Construyendo el MODELO. Si el problema es muy complejo, siempre podemos olvi-dar o despreciar algunos detalles (obviamente, de poca importancia) de la física delproblema (fricción, viscosidad, aislamiento, etc...)

Tomando los DATOS. Siempre podemos realizar más y/o mejores MEDIDAS u OB-SERVACIONES que eviten o minimicen ruido o sesgos, o también completar unamuestra insuficiente

Preparando COMPUTACIONES PREVIAS. Tratar de mejorar la precisión y exacti-tud en los cálculos previos necesarios para los datos de entrada y que solamente sonaproximadas.

2. DURANTE el proceso de computación, en los procesos de

TRUNCAMIENTO, usando un número finito de términos en una serie en vez de todaella,

1.3. Aproximaciones en Computación Científica 5

Page 12: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

DISCRETIZACIÓN, por ejemplo usando diferencias finitas en los valores de las varia-bles, en vez de derivadas,

REDONDEO, cuando calculamos (a mano, o usando la calculadora o el computador)la representación de los números reales y las operaciones aritméticas están limitadasintrínsecamente por la precisión finita de ellos.

1.4 Error Absoluto y Error Relativo. Precisión y Exactitud

La expresión de un resultado científico siempre debe hacerse utilizando solamente sus cifras sig-nificativas y/o indicando el error en el resultado. Para ello debemos conocer o estimar el posibleerror en tal resultado.

El sentido o significado de un error está relacionado con la magnitud de la cantidad que se mide ose computa. De esta forma se define:

Error absoluto = VALOR APROXIMADO - VALOR VERDADERO.

Error relativo = ERROR ABSOLUTO / VALOR VERDADERO.

A veces se define como error absoluto el valor absoluto de la definición anterior. Normalmenteno conocemos el valor verdadero, de forma que simplemente acotaremos o estimaremos el erroren vez de computarlo exactamente. Como consecuencia, el error relativo se toma generalmenterespecto al valor aproximado si no conocemos el verdadero. El error relativo multiplicado por 100nos da el error porcentual (en tanto por ciento) en el resultado.

Una interpretación interesante del error relativo en una medida o cálculo es el siguiente: si unvalor aproximado tiene un error relativo de 1.0 × 10−𝑛, entonces su representación decimal tiene𝑛 dígitos.

Los dígitos o cifras significativas del valor numérico de una magnitud (o medida) son aquellosdígitos que tienen significado, la cantidad de cifras significativas de dicha magnitud se define delsiguiente modo:

1. El primer dígito diferente de cero por la izquierda es el más significativo.

2. Si no hay punto decimal, el dígito más a la derecha distinto de cero es el menos significativo.

3. Si hay un punto decimal, el dígito más a la derecha es el menos significativo aunque sea un0.

4. Todos los dígitos entre el más y el menos significativo son contados como cifras significati-vas.

Por ejemplo: 780 y 0.0078 tienen el mismo número de cifras significativas (dos); en cambio 780.0y 0.7800 tienen cuatro. Otro ejemplo: 430, 430., 430.0 tienen diferentes cifras significativas (dos,tres y cuatro respectivamente) ya que fueron obtenidas con precisión de una decena, una unidad yuna décima, respectivamente.

6 Capítulo 1. La Computación Científica y sus herramientas

Page 13: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

Usar la notación científica tiene la ventaja que usa siempre todas las cifras significativas de unnúmero, y sólo ellas, con un argumento en notación decimal y acompañado con la potencia de 10apropiada para representarlo. Por ejemplo, 320 lo escribiríamos 3.2 × 102. Otro ejemplo: 86420 y0.00008642 (ambos con 4 cifras significativas) los escribimos como 8.642×104 y 8.642×10−5. Enpython y, en general cualquier lenguaje de ordenador, estos numeros se escribirán así: 8.642e04 y8.642e-05 .

En el caso de resultados experimentales productos de la observación, el número de cifras significa-tivas que se escriben suele ser una más que la que da la precisión experimental para evitar erroresde redondeo en sucesivos cálculos. Por ejemplo, si medimos una longitud como 1.348 m con unaincertidumbre de 0.011 m, el resultado podríamos expresarlo como: 1.348± 0.011; no obstante, sila incertidumbre es 0.073 (el dígito más significativo es mayor que 5) podríamos expresarlo como:1.35 ± 0.07. Fijénse que hemos redondeado el dígito menos significativo.

Esto nos lleva a los conceptos de precisión y exactitud. La diferencia entre precisión o exactituden una medida o cálculo la podemos establecer aquí como:

PRECISIÓN. Se refiere al número de dígitos o cifras significativas con el que se expresa unamedida. Es una valoración de lo ‘cuidadoso’ que ha sido el cálculo o la medida. Cuantos mássean mayor es la precisión.

EXACTITUD. Se relaciona mejor con un error absoluto pequeño; cuanto más pequeño másexacto. Es una valoración de cuán cercano al valor real o verdadero es una medida o cálculo.

Por ejemplo: tengamos el número 3.141345654320976810345 con todas las cifras significativascomo resultado de una medida; se trata de un número muy preciso (22 cifras significativas) peromuy poco exacto como valor de 𝜋 (su error absoluto es de 0.0003). En cambio, 3.1416 (5 cifrassignificativas) es un valor menos preciso pero más aproximado (exacto) a 𝜋 (número irracional quevale 3.14159265...) que el anterior.

1.5 Aritmética computacional

En cualquier ordenador o calculadora los números se almacenan en un número finito de bits. Losnúmeros enteros no tienen problema y se almacenan exactamente, si disponemos del número su-ficiente de bits para ello. Sin embargo, en el caso de los números reales esto no ocurre así ya quemuchos de ellos no tienen representación exacta y se procede al redondeo para poder representar-los; de hecho, se habla de números en coma flotante (floating point). Su representación se toma dela notación científica y consta de: signo, mantisa y exponente; por ejemplo: −3.9267 × 10−8, elsigno es negativo, la mantisa es 3.9267 y el exponente es -8. La notación habitual que nos ofrecenlos ordenadores es -3.9267e-8 o también -3.9267E-8.

El almacenamiento de estos números en un ordenador depende de las características de éste y, aveces, del lenguaje de programación que utilicemos. Python sigue la norma “IEEE standard 754”que consiste en representar los números en coma flotante en una notación binaria normalizada(tiene una base 2 y una mantisa menor que 2). Utiliza para ello 64 bits de los cuales reserva unopara el signo, 52 para la mantisa y 11 para el exponente. Esto determina el intervalo de números

1.5. Aritmética computacional 7

Page 14: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

que puede almacenar; alrededor de 2.2 × 10−308 y 1.7 × 10308, es decir, lo más aproximado a 0 einfinito que tenemos.

Todo ello hace que tengamos errores, normalmente pequeños, al hacer cálculos con números encoma flotante. Algunas de las características peculiares que todo esto conlleva son las siguientes:

En la pantalla, Python nos ofrece sólo los primeros 17 decimales, el último redondeado.El redondeo consiste en buscar el número en coma flotante más próximo al que queremosrepresentar.

No todos los números reales pueden representarse así; por ejemplo, prueben con 0.1. Seredondea el último.

La precisión depende del propio número. Cuanto más próximos a 0 sean los números me-jor precisión podremos obtener en las operaciones con ellos; para números grandes vamosperdiendo precisión; pueden comprobarlo probando a sumar a 1e8 la cantidad de 1e-9.

Volviendo a los números enteros, normalmente en Python se almacenan en 32 bits (el mayor sería231) sin redondeos. No obstante, Python utiliza también los llamados enteros largos que utilizanel número de bits necesario para almacenar el entero de que se trate. Es muy rápido operar conenteros pero si el resultado de una operación es un entero que no le cabe en 32 bits, Python seencarga de alargarlo convenientemente, con el consiguiente mayor gasto en memoria y en rapidezde cálculo; esto no sucede así en otros lenguajes de programación pero es muy cómodo no tenerque preocuparse de estos problemas.

Nota: Les será muy útil que repasen el Sistema Internacional de Unidades, que pueden encontraren cualquiera de estas direcciones en la red, entre otras:

http://es.wikipedia.org/wiki/Sistema_Internacional_de_Unidades

http://en.wikipedia.org/wiki/International_System_of_Units

http://physics.nist.gov/cuu/Units/

En la siguiente dirección podemos encontrar además tablas con múltiplos y submúltiplos decimales(potencias de 10): http://recursos.citcea.upc.edu/unidades/sicas.html

1.6 Ejercicios

1. Calcular los errores absolutos y relativos si se aproxima el valor de 𝜋 por las siguientescantidades: 3 ; 3.14 ; 22/7 .

2. Si a, con error relativo R, es el valor aproximado para una cantidad cuyo valor verdadero esv, probar a partir de las definiciones que a = v (1 + R).

3. Tenemos que 𝑥 = 0.012, con dos cifras significativas. Si 𝑦 = exp(𝑥), encontrar con cuántascifras significativas podemos evaluar 𝑦.

8 Capítulo 1. La Computación Científica y sus herramientas

Page 15: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

CAPÍTULO 2

Introducción a la programación con Python

Para crear un algoritmo para resolver un problema matemático, necesitamos conocer un lenguaje deprogramación e implementarlo en un ordenador. Un lenguaje de programación, como los lenguajesnaturales, son una serie de órdenes que nos permiten “hablar” con un ordenador pero a diferenciade los naturales, los lenguajes de programación son estrictos y no permiten ambigüedades. Existencientos de lenguajes de programación, cada uno con sus peculiaridades, pero solo con unos pocosse han programado la mayoría de los programas que usamos diario como navegadores, editores detexto, aplicaciones en smartphones o muchas páginas web como Wikipedia o Facebook. Entre loslenguajes más usados están C/C++, Java o Python, aunque en ciencia también son muy popularesFORTRAN y Matlab, entre otros.

En cualquier caso, el objetivo de un lenguaje de programación es ofrecer un idioma relativamentesencillo con el que dar órdenes a un ordenador; éste, no comprende directamente ningún lenguajede programación, únicamente el llamado “lenguaje de máquina”, que es propio de cada tipo deordenador y por tanto el programa, hecho en cualquier lenguaje, debe traducirse a este lenguaje demáquina.

Según cómo se convierte un código o programa a lenguaje de máquina, los lenguajes se clasificanen dos tipos, los compilados, como C/C++ o FORTRAN, en los cuales mediante una orden setraduce (compila) completamente el programa una única vez generándose un programa ejecutableque se puede usar cuantas veces queramos. Por otro lado están los lenguajes interpretados comoPython, Perl o Ruby, que se van traduciendo y ejecutando línea a línea. Por regla general losprogramas compilados son más rápidos, pero los interpretados tienen la ventaja de que son muchomás interactivos y flexibles y es mucho más facil y rápido programar y corregir errores con ellos ypor eso se usan mucho en el análisis de datos.

Python es lo que se denomina un lenguaje interpretado (no compilado), que puede utilizarse comoun programa ejecutable desde una terminal de comandos o también, de manera interactiva medianteuna consola de comandos, donde se dan instrucciones línea a línea. Python incorpora una consolapor defecto, pero también existen otras alternativas con características muy útiles para el análisiscientífico de datos. Un ejemplo es ipython 1 que se trata de una consola de Python mejorada,incluyendo completado de funciones y variables, funcionalidad de los comandos básicos de la

1 Mucha más información en la web oficial: http://ipython.org/

9

Page 16: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

consola del sistema (cd, ls, pwd, etc.), comandos adicionales (llamados comandos mágicos) yun largo etcétera. Esta es la consola de Python que usaremos preferentemente durante este curso,aunque se puede trabajar sin problema con la consola por defecto.

2.1 Empezando con Python

Se puede iniciar Python de manera interactiva desde una terminal de comandos estándar de Linuxo Mac sin más que escribir python. Los usuarios de Windows deben lanzar la consola de Python(o IPython) desde el menú de programas y se abrirá una ventana nueva. Aparecerá el prompt >>>(en la consola estándar de Python) y entonces estará listo para empezar. Este símbolo de prompt,que puede ser distinto en otras consolas Python, indica que el sistema está preparado para recibirinstrucciones del usuario. Veamos un comando sencillo:

>>> print('Hola, esto es Python')Hola, esto es Python

>>>

Aquí hemos usado la función print() para imprimir una frase en la pantalla. Nota que la fraseestá entre comillas, que pueden ser dobles (”) o simples (‘). El resultado se muestra inmediatamentepor pantalla y vuelve a aparecer de nuevo el prompt esperando por nuevos comandos. En el caso dequerer iniciar la consola ipython hay que escribir ipython y tendremos un prompt algo diferente:

In [1]: print('Esto es Python, con la consola ipython')Esto es Python, con la consola ipython

In [2]:

En este caso cada línea de entrada y salida está numerada y además tenemos otras funcionalidadesmuy útiles para el trabajo interactivo que iremos conociendo.

Nota: Cuando iniciamos una sesión de trabajo con ipython, suele ser muy útil guardar todo loque vamos haciendo para repasar o estudiar lo que se hizo. Para ello se empieza la sesión con elcomando mágico de ipython 2 %logstart con el objeto de grabarla en un fichero, por ejemplo:

In [1]: %logstart -o clase_25_septiembre_2015.txt

donde el parámetro opcional -o guarda también la salida (respuesta) de python en el ficheroclase_25_septiembre_2015.txt. De esta manera tendremos en un fichero todo lo quehicimos durante la sesión. Con los comandos%logoff y%logon podemos, respectivamen-

2 Los comandos y funciones mágicos de ipython son una serie de utilidades de esta consola y no de Python en sí.Para ver más información y la lista completa de comandos mágicos disponibles, escribe%magic en la consola deipython. Para salir de%magic teclea q.

10 Capítulo 2. Introducción a la programación con Python

Page 17: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

te, detener temporalmente y continuar el registro de sesión que hayamos iniciado previamentecon%logstart.

Si queremos guardar todo lo que hemos hecho en un fichero ejecutable o continuar a partir de dóndelo dejamos, tendríamos que guardarlo con la extensión .py en vez de .txt. Si posteriormente,queremos recuperar las sesiones hechas y guardadas en un fichero de registro, podemos hacerlocon el comando run dentro de ipython:

In [1]: run clase_25_septiembre_2015.py

al hacerlo, se ejecuta todo el código de entrada que está en el fichero, repitiendo una a una todaslas operaciones.

2.2 Tipos básicos de datos

En cualquier lenguaje de programación existen distintos tipos de datos, que podemos almacenar yoperar de forma diferente con ellos y que poseen distintas propiedades. Los más comunes son lasllamadas cadenas de texto o string (indicadas siempre entre comillas) y los números ( int o float,enteros o de “coma flotante” respectivamente):

>>> print("Esta es una linea de texto")Esta es una linea de texto>>> print(28) # este es un entero28

Las variables son componentes fundamentales de un lenguaje de programación y no son más queun nombre que se refiere a un registro en el computador (una serie de bits de memoria) que contieneuno o varios datos, que pueden ser de distinto tipo. Veamos unos ejemplos:

>>> frase = "Esta es una linea de texto">>> num = 22>>> num*244>>> frase*2Esta es una linea de textoEsta es una linea de texto

Aquí, frase es una variable tipo string mientras que num es otra variable numérica entera. Nóteseque mientras se multiplicó num por 2 de forma conocida, la cadena de texto frase fué duplicadaal multiplicarla por 2. En este caso hemos operado con dos tipos de datos distintos, un string yun int, algo que muchos lenguajes de programación produce un error por no tener sentido, sinembargo, Python interpreta el producto de un string y un int como la unión o concatenación de lamisma cadena de texto varias veces, y es por eso que vemos frase duplicada.

A lo largo del trabajo podemos acabar definiendo muchas variables de distinto tipo. Con el coman-do type() podemos saber el tipo de dato que se asigna a una variable si en cualquier momento

2.2. Tipos básicos de datos 11

Page 18: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

no recordamos como la definimos:

>>> type(frase)<type 'str'>>>> type(num)<type 'int'>

Los nombres de las variables pueden ser cualquier combinación de letras y números (siempreque no empiece por número) pero no están permitidos carácteres especiales como tildes, puntos,espacios en blanco, etc. Algunas palabras están además reservadas ya por el propio Python para suuso como: def, class, return, etc. por lo que tampoco las podremos usar como nombres devariables.

Algo muy importante es que, como casi todos los lenguajes de programación, hay una distinciónclara y de funcionalidad entre enteros y decimales, es decir, entre int y float; aunque ambos seanvalores numéricos, tienen propiedades distintas que afectan al cálculo. Así, la variable num lahemos definido de tipo entero estricto y el cálculo entre números enteros siempre da comoresultado otro número entero, redondeándose al más cercano en caso de no ser entero exacto,por ejemplo:

>>> 113/274 # en lugar de 4.1851851851851851

Si queremos usar números decimales, también llamados de coma flotante, debe emplearse directa-mente un valor decimal (float); en estos casos:

>>> 113.0/27.04.1851851851851851

>>> type(113.0/27.0)<type 'float'>

Es decir, numero = 3 no es lo mismo que numero = 3.0 aunque ambos tengan el mismovalor. Como dijimos en el tema anterior, Python emplea números de 64 bits (por defecto) en losfloat. En cualquier operación es muy importante usar los enteros y float correctamente y tenercuidado al mezclarlos, de otro modo se obtendrá un resultado no deseado llegando a hacernoscreer que el computador se ha equivocado.

Algunos tipos de datos pueden ser convertidos de unos a otros, empleando str() para convertira cadena de texto, int() a entero y float() a coma flotante:

>>> float(3)3.0

>>> int(3.1416)3

12 Capítulo 2. Introducción a la programación con Python

Page 19: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

>>> str(34)'34'

Para el caso de los float, se pueden redondear con round(), que redondea al entero más próxi-mo. La funciones ceil() y floor() del módulo math redondean hacia arriba y hacia abajorespectivamente:

>>> print(round(4.4)) , (round(4.5))4.0 5.0>>> # Importamos todas las funciones matemáticas del módulo math>>> from math import *>>> print(ceil(4.4)) , (ceil(4.5))5.0 5.0

>>> print(floor(4.4)) , (floor(4.5))4.0 4.0

Más adelante veremos qué son los módulos, que ofrecen otras funciones predefinidas muy intere-santes y aprenderemos cómo importarlos y a utilizarlos.

Nota: La versión de Python que empleamos siempre en este curso es la 2.7, que la más usadaactualmente, aunque la versión más moderna es la serie 3.0, en concreto la versión Python 3.5.Entonces ¿por qué no usamos Python 3.0? El motivo es porque hay varias diferencias importantesentre la series Python 2 y Python 3 y aunque el lenguaje es el mismo, hay aún muchos paquetesque no están completamente soportados en Python 3, por lo que por ahora Python 2.7 es aún condiferencia la versión de Python más usada, aunque Python 3 lleva existiendo muchos años. Desdeluego, Python 3 es una versión más moderna y mejor, por lo que con el tiempo poco a poco se vapasando a Python 3. Una peculiaridad de Python 3 es su forma de operar entre enteros. A diferenciade muchos lenguajes de programación, incluyendo Python 2, la división entre entero devuelve unfloat:

Python 3.3.2 (default, Sep 9 2013, 12:40:26)[GCC 4.7.2 20120921 (Red Hat 4.7.2-2)] on linuxType "help", "copyright", "credits" or "license" for more information.>>> 1 / 20.5>>> type(1*2)<class 'int'>>>> type(1/2)<class 'float'>>>>

2.2. Tipos básicos de datos 13

Page 20: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

2.3 Operadores aritméticos y lógicos

Con python se pueden hacer las operaciones aritméticas habituales usando los símbolos corres-pondientes:

Operación SímboloSuma +Resta −Multiplicación *División /Exponenciación **Residuo o resto %

La prioridad en la ejecución (de mayor a menor, separados por ;) es la siguiente: **; *, /, %; +, - .:

>>> x=3.5>>> x**212.25>>> x+x**215.75>>> x**(2./3.)2.3052181460292234>>> x**(2/3)1.0>>> 123%83>>> x+x/2+x*x-x**1.25-x%211.212761600464169

Los operadores lógicos son aquellos operadores que permiten comparar valores entre sí. En con-creto se usan:

Operacion SimboloIgual a (comparación) ==Distinto de (comparación) != o <>Mayor que, Menor que >, <Mayor o igual, Menor o igual >=, =<y, o and, orcierto, falso True, False

Como resultado de una operación lógica, obtenemos como respuesta un elemento, True o False,según se verifique o no la operación. Estos elemento lógicos los podemos usar a su vez para otrasoperaciones. Veamos algunos ejemplos:

>>> resultado = 8 > 5>>> print resultadoTrue

14 Capítulo 2. Introducción a la programación con Python

Page 21: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

>>> resultado = (4 > 8) or (3 > 2)>>> print resultadoTrue>>> resultado = True and False>>> print resultadoFalse>>> resultado = (4 > 8) and (3 > 2)>>> print resultadoFalse

Ahora que conocemos los operadores lógicos, podemos consultar si una variable es de un tipoconcreto:

>>> numero = 10.0>>> type(numero) == int>>> False>>> type(numero) == float>>> True

En este caso ìnt y float no son cadenas de texto, sino un indicador del tipo de dato. Estose puede usar para cualquier tipo de dato más complejos, no únicamente números o cadenas, loscuales veremos más adelante.

2.4 Cadenas de texto

Las cadenas de texto, como hemos visto, no son mas que texto formado por letras y números decualquier longitud y son fácilmente manipulables. Para poder hacerlo, cada carácter de una cadenade texto tiene asociado un índice que indica su posición en la cadena, siendo 0 el de la izquierdadel todo (primero), 1 el siguiente hacia la derecha y así sucesivamente hasta el último. Veamosejemplos:

>>> # Variable "frase" que contiene una cadena de texto>>> frase = "Si he logrado ver más lejos, ha sido porque he subido

→˓ahombros de gigantes"

>>> print frase[0] # Primera letra de la cadenaS

>>> print frase[10] # Decimoprimera letra, con índice 10a>>> len(frase) # Longitud de la cadena76

>>> print frase[18:29] # Seccion de la cadena

2.4. Cadenas de texto 15

Page 22: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

más lejos,

>>> print frase[68:] # Desde el indice 68 hasta el finalgigantes

>>> print frase[:10] # Desde el principio al caracter deSi he logr # indice 10, sin incluirlo

También se pueden referir con índices contando desde la derecha, usando índices negativos, siendo-1 el primero por la derecha:

>>> print(frase[-1]) # El último carácter, contando desde la derechas

El comando len() nos porporciona el número de caracteres (longitud) de la cadena de texto:

>>> len(frase) # 76 es el número de caracteres de la cadena76>>> print(frase[len(frase)-1]) # El último carácter, contando desde la

→˓izquierdas>>> print( frase[-1] == frase[len(frase)-1] ) # Compruebo si son

→˓igualesTrue

Desde luego es irrelevante qué sistema de índices se use, ya que sólo son dos formas distintas dereferirse a un mismo caracter, pero lo más habitual es usar índices positivos de izquierda a derecha.

Figura 2.1: Ejemplo de indexado de cadenas de texto con Python. Nótese que el último índice delrango no está incluído en la selección.

Los caracteres en Python son de tipo ascii (7 bits), si queremos que no haya problemas con losacentos o con la letra ñ tienen que ser definidos como de tipo unicode de 8 bits. Para no te-ner problemas con estos símbolos en la variable frase, la podemos definir como un string decaracteres unicode.

16 Capítulo 2. Introducción a la programación con Python

Page 23: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

>>> frase = u"Si he logrado ver más lejos, ha sido porque he subido ahombros de gigantes"

Si ahora comprobamos de qué tipo de variable se trata:

>>> type(frase)<type 'unicode'>

Existen varios métodos o funciones específicas para tratar y manipular cadenas de texto, éstos nospermiten cambiar de varias maneras las cadenas. Veamos algunos:

>>> frase_mayusculas = frase.upper() # Cambia a mayusculas y lo→˓guardo en

>>> print(frase_mayusculas) # la variable frase_mayusculasSI HE LOGRADO VER MAS LEJOS, HA SIDO PORQUE HE SUBIDO A HOMBROS DE

→˓GIGANTES

Probar qué ocurriría si no hubiésemos definido la variable frase como un string de caracteres detipo unicode:

>>> frase_minusculas = frase.lower() # Cambia a minúculas y lo→˓guardo en

# la variable frase_minusculas>>> print(frase_minusculas)si he logrado ver más lejos, ha sido porque he subido a hombros de

→˓gigantes

>>> # Reemplaza una cadena de texto por otra>>> frase.replace("hombros", "la chepa")

u'Si he logrado ver m\xe1s lejos, ha sido porque hesubido a la chepa de gigantes'

Aparece la u delante de la frase y \xe1s en vez de á.

Este último comando devuelve una nueva cadena de texto cambiada, que vemos por pantalla, sincambiar la original. Podemos comprobar que la frase no se ha alterado de forma permanente ha-ciendo un print(frase). Para cambiar la variable frase deberemos volver a definir la cadenade texto:

>>> # Reemplaza definitivamente una cadena de texto por otra>>> frase = frase.replace("hombros", "la chepa")>>> print(frase)

'Si he logrado ver mas lejos, ha sido porque hesubido a la chepa de gigantes'

2.4. Cadenas de texto 17

Page 24: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

Advertencia: Recordar que el índice en las cadenas de texto y en general cualquier lista denúmeros, empieza siempre con el 0, por lo que el primer elemento de una cadena de texto ode una lista es frase[0] y no frase[1]. Al escribir frase[10] estamos tomando elelemento ordinal 11, no el 10.

2.5 Impresión de texto y de números

La cadenas de texto se pueden concatenar o unir con +:

>>> "Esta es un frase" + " y esta es otra"'Esta es un frase y esta es otra'

Sin embargo, la concatenación sólo es posible para texto (string), por lo que no se pueden conca-tenar letras y números. Una posibilidad es convertir los números a string:

>>> a, b = 10, 10**2 # Definimos dos numeros, a=10 y b=10**2>>> print(str(a) + " elevado al cuadrado es " + str(b))10 elevado al cuadrado es 100

Una manera más práctica y correcta de hacer esto es imprimiendo los números con el formato quequeramos; veamos como hacerlo:

>>> # Calculamos el logaritmo base 10 de 2**100 e imprimimos>>> # el resultado con 50 decimales>>> print("%.50f") % log10(2.0**100)30.10299956639811824743446777574717998504638671875000>>> # Otro ejemplo usando texto, enteros y decimales>>> print("El %s de %d es %f") % ('cubo', 10, 10.**3)El cubo de 10 es 1000.000000

Aqui se reemplaza cada símbolo%s (para cadenas de texto),%d (para enteros) o%f (para floats)sucesivamente con los valores después de % que están entre paréntesis. En caso de los floats sepuede utilizar el formato%10.5f, que significa imprimir 10 carácteres en total, incluído el pun-to, usando 5 decimales. Se puede escribir también floats en formato científico utilizando%e, porejemplo:

>>> print("%.5e" % 0.0003567)3.56700e-04

Los formatos son muy útiles a la hora de expresar el resultado de un cálculo con los dígitos signi-ficativos solamente o con la indicación del error en el resultado. Así por ejemplo, si el resultado deun cálculo o de una medida es 3.14158 ± 0.00013 podemos expresarlo como:

18 Capítulo 2. Introducción a la programación con Python

Page 25: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

>>> # resultado de un cálculo obtenido con las cifras>>> # decimales que proporciona el ordenador>>> resultado = 3.1415785439847501>>> # este es su error con igual número de cifras decimales>>> error = 0.0001345610900435>>> # así expresamos de forma correcta el resultado>>> print("El resultado del experimento es %.5f +/- %.5f" ) %

→˓(resultado, error)El resultado del experimento es 3.14158 +/- 0.00013

2.6 Estructuras de datos: listas, tuplas y diccionarios

Los datos se pueden almacenar en variables univaluadas como ya hemos visto. No obstante, envariables estructuradas también pueden almacenarse uno o más datos. Los tipos de variablesestructuradas que ofrece Python son las llamadas listas, tuplas y diccionarios que se definen de lasiguiente forma:

2.6.1 Listas

Se trata de un conjunto de números, cadenas de texto u otras listas (aquí tendríamos listas de listas),ordenadas de alguna manera:

>>> # Lista de datos string>>> alumnos = ['Miguel', 'Maria', 'Luisma', 'Fran', 'Luisa', 'Ruyman']

>>> # Lista de enteros>>> edades = [14, 29, 19, 12, 37, 15, 42]

>>> # lista de datos mixto(entero, string y lista)>>> datos = [24, "Juan Carlos", [6.7, 3.6, 5.9]]

En el último ejemplo se puede comprobar que es posible mezclar varios tipos de datos, comoenteros, strings y hasta otras listas. Se puede utilizar la función len() para ver el número deelementos de una lista:

>>> len(alumnos)6

Es posible utilizar el método split() para separar por medio de los espacios una cadena de textocualquiera y colocar los elementos resultantes en una lista:

>>> Definimos la cadena de texto>>> frase = "Dios no juega a los dados"

2.6. Estructuras de datos: listas, tuplas y diccionarios 19

Page 26: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

>>> palabras = frase.split() # separo la frase por espacios en→˓blanco

>>> print(palabras)['Dios', 'no', 'juega', 'a', 'los', 'dados'] # el resultado es una

→˓lista>>> palabras2 = frase.split('no') # separo la frase por 'no'>>> print(palabras2)['Dios ', ' juega a los dados']

Como se ve en el ejemplo anterior, el método split() separa (por defecto, por espacios enblanco) los elementos, palabras en este caso, de la cadena de texto y da como resultado una listacon los elementos. Se puede usar otro separador, como la coma en este ejemplo la cadena ‘no’,usándolo como parámetro. Nótese que en este caso ‘no’ ya no está en ningún elemento de la lista,ya que ahora se usa de separador y por eso desaparece.

En este caso hemos llamado método a una función que se aplica a un tipo de dato en concreto, eneste caso un string, usando la variable y el método unidos por un punto, en lugar de un funciónnormal como es len(alumnos), por ejemplo.

Existen varias formas de añadir nuevos elementos a una lista existente, estas son la formas máscomunes:

>>> alumnos.append('Iballa') # Añade "Iballa" al final de la lista>>> print(alumnos)['Miguel', 'Maria', 'Luisma', 'Fran', 'Luisa', 'Ruyman', 'Iballa']

A diferencia de replace, append guarda el cambio realizado.:

>>> alumnos.insert(3, 'Jairo') # Añade "Jairo" en la posición 3>>> print(alumnos)['Miguel', 'Maria', 'Luisma', 'Jairo', 'Fran', 'Luisa', 'Ruyman',

→˓'Iballa']

>>> alumnos.index("Jairo")>>> 3

En la última orden del ejemplo anterior hemos usado index() para encontrar el índice o posi-ción del primer elemento de la lista que es “Jairo”.

Es posible ordenar alfabéticamente una lista con el método sort():

>>> alumnos.sort()>>> print(alumnos)['Fran', 'Iballa', 'Jairo', 'Luisa', 'Luisma', 'Maria', 'Miguel',

→˓'Ruyman']

Para extraer un elemento de la lista podemos usar los métodos pop() y remove():

20 Capítulo 2. Introducción a la programación con Python

Page 27: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

>>> alumnos.pop(2) # Extraemos el elemento número 2 y lo elimino de→˓la lista

'Jairo'>>> print(alumnos)['Fran', 'Iballa', 'Luisa', 'Luisma', 'Maria', 'Miguel', 'Ruyman']

>>> alumnos.remove('Maria') # Eliminamos el elemento "Maria" (primera→˓ocurrencia)

>>> print(alumnos)['Fran', 'Iballa', 'Luisa', 'Luisma', 'Miguel', 'Ruyman']

Las listas se manipulan de manera similar a las cadenas de texto, utilizando índices que indican laposición de cada elemento siendo 0 el primer elemento de la lista y -1 el último (si se empieza anumerar por el final):

>>> alumnos[2:6]['Luisma', 'Fran', 'Luisa', 'Ruyman']

>>> print(alumnos[0], alumnos[-1])('Fran', 'Ruyman')

Y aquí va un truco. Si queremos invertir el orden de la lista, podemos hacerlo de esta manera:

>>> alumnos_invertida = alumnos[::-1]>>> print alumnos_invertida>>> ['Ruyman', 'Miguel', 'Luisma', 'Luisa', 'Iballa', 'Fran']

Una función muy útil es la función range(), que permite crear una lista de números enteros. Porejemplo, para crear un lista de 10 elementos, de 0 a 9, e imprimirlos podemos hacer esto:

>>> print( range(10) )[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

Con esta función se puede crear también una lista de números indicando el inicio, final y el inter-valo entre dos consecutivos. Por ejemplo, para crear una lista con números enteros de 100 a 200 aintervalos de 20 podemos escribir:

>>> print( range(100, 200, 20) )[100, 120, 140, 160, 180]

Nótese que el último número, 200, no se incluye la lista. La función range() se emplea paragenerar listas de números enteros solamente. Más adelante veremos cómo crear listas similares defloats.

Con las variables listas podemos operar de forma parecida a las cadenas de texto, por ejemplo:

2.6. Estructuras de datos: listas, tuplas y diccionarios 21

Page 28: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

>>> a=range(100, 200, 20)>>> print(a)[100, 120, 140, 160, 180]>>> print(a+a)[100, 120, 140, 160, 180, 100, 120, 140, 160, 180]>>> print(a*3)[100, 120, 140, 160, 180, 100, 120, 140, 160, 180, 100, 120, 140, 160,

→˓180]

Como se ve en este ejemplo, se pueden unir dos listas usando + o incluso multiplicarla por unnúmero entero, que equivale a sumar varias veces la misma lista.

La forma de indexar las listas y los strings de Python, de manera que el segundo índice en un rangono se incluye en la sublista resultante, puede parecer confuso, pero está bien pensado. Recordemosesto con un ejemplo

>>> numeros = range(1, 11) # lista de números de 1 a 10 (11 no→˓incluido)

>>> mitad = len(numeros)/2 # indice de la mitad de la lista>>> primeros5 = numeros[:mitad] # lista con los primeros cinco>>> ultimos5 = numeros[mitad:] # lista con los últimos cinco

>>> print primeros5>>> [1, 2, 3, 4, 5]

>>> print ultimos5>>> [6, 7, 8, 9, 10]

como vemos, el mismo índice (5) con que termina la primera la lista, empieza la segunda. De estamanera, si queremos recuperar la lista original sólo tenemos que unir las dos partes:

>>> print primeros5 + ultimos5>>> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

y así las cuentas y manipulaciones con strings y listas se hacen más fácilmente.

2.6.2 Tuplas: listas inalterables

Las tuplas son listas que no se pueden modificar o alterar y se definen enumerando sus elementosentre paréntesis en lugar de corchetes, por ejemplo:

>>> lista_alumnos = ('Miguel', 'Maria', 'Luisma', 'Fran', 'Luisa',→˓'Ruyman')

También podemos definirlas como una variable con varios valores separados por comas; pythoninterpreta esto como una tupla aunque no esté entre paréntesis:

22 Capítulo 2. Introducción a la programación con Python

Page 29: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

>>> c = 1, 3 # Defino una variable con dos valores separados por→˓comas

>>> print(c)>>> (1, 3)

Podemos comprobarlo viendo el tipo de dato del que se trata:

>>> type(c)<type 'tuple'>>>> print(c[0]) # imprimimos el primer elemento de la tupla1>>> print(c[1]) # imprimimoa el segundo elemento de la tupla3

Si se intenta insertar, quitar o reordenar la tupla con los comandos que ya conocemos para laslistas, o en definitiva modificar la tupla, aparecerá un error indicando que no es posible.

2.6.3 Diccionarios

Los diccionarios son listas en las que cada elemento se identifica no con un supuesto índice (nú-mero de orden), sino con un nombre o clave, por lo que siempre se usan en parejas clave-valorseparadas por ”:”. La clave va primero y siempre entre comillas y luego su valor, que puede seren principio cualquier tipo de dato de Python; cada pareja clave-valor se separa por comas y todose encierra entre llaves. Por ejemplo, podemos crear un diccionario con los datos básicos de unapersona:

>>> datos = 'Nombre': 'Juan', 'Apellido': 'Martinez', 'Edad': 21,→˓'Altura': 1.67

>>> type(datos)<type 'dict'>

En este caso hemos creado una clave “Nombre” con valor “Juan”, otra clave “Apellido” con valor“Martínez”, etc. Al crear los datos con esta estructura, podemos acceder a los valores de las clavesfácilmente:

>>> print( datos['Nombre'] )Juan

Fíjense que ya no podemos acceder a los datos por su índice y obtenemos error:

>>> print(datos[0])Traceback (most recent call last):

File "<stdin>", line 1, in <module>KeyError: 0

2.6. Estructuras de datos: listas, tuplas y diccionarios 23

Page 30: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

También podemos conocer todas las claves y los valores de un diccionario usando los métodoskeys() y values() respectivamente:

>>> datos.keys()['Apellidos', 'Nombre', 'Altura']

>>> datos.values()['Martinez', 'Juan', 1.6699999999999999]

Como vemos, la respuesta de estos dos métodos es una lista con las claves y valores del diccionario,que podemos manipular como tales.

2.7 Módulos y paquetes de Python

Python viene con muchos módulos (un conjunto de funciones) que ofrecen funcionalidades adi-cionales muy interesantes. Uno de ellos es el módulo de funciones matemáticas básicas math, queya hemos visto brevemente, otro el paquete de utilidades del sistema sys y muchos más. Se puedeimportar un módulo cualquiera haciéndolo implícitamente, o sea importando el módulo completoo bien nombrando una, varias o todas sus funciones; veamos cómo hacerlo:

>>> import math # importa el módulo math>>> import math as M # importa el módulo math llamándolo

→˓M>>> from math import sin, cos, pi # importa funciones sin, cos y pi

→˓de math>>> from math import * # importa todas las funciones de

→˓math

Podemos ver un listado de las funciones que ofrece un módulo usando la función dir():

>>> import math>>> dir(math) # Lista todas las funciones y subpaquete del modulo

→˓math['__doc__', '__name__', '__package__', 'acos', 'acosh', 'asin','asinh', 'atan', 'atan2', 'atanh', 'ceil', 'copysign', 'cos', 'cosh','degrees', 'e', 'exp', 'fabs', 'factorial', 'floor', 'fmod', 'frexp','fsum', 'hypot', 'isinf', 'isnan', 'ldexp', 'log', 'log10', 'log1p','modf', 'pi', 'pow', 'radians', 'sin', 'sinh', 'sqrt', 'tan','tanh', 'trunc']

Para conocer otros módulo de la librería estándar pueden consultar el “tutorial” oficial de Pythono la guía oficial de la Librería de Python. En ocasiones nos encontraremos con módulos más gran-des y complejos, que en realidad son módulos que contienen otros módulos y se les suele llamarpaquetes, aunque se usan de manera similar y a veces se mezclan una y otra definición.

24 Capítulo 2. Introducción a la programación con Python

Page 31: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

Por nuestra parte iremos introduciendo más adelante otros módulos y paquetes numéricos de Pyt-hon más avanzados que nos aportan éstas y muchas otras funciones matemáticas, muy útiles parala computación científica.

2.8 Información y ayuda sobre funciones y módulos

Prácticamente todas las funciones de Python tienen un texto de ayuda que nos explican qué haceny cómo funcionan. Para consultar esta ayuda usamos la función help() y entre paréntesis elnombre de la función que queremos consultar:

>>> help(round)

Help on built-in function round in module __builtin__:

round(...)round(number[, ndigits]) -> floating point number

Round a number to a given precision in decimal digits (default 0→˓digits).

This always returns a floating point number. Precision may be→˓negative.

Si lo que queremos consultar es un método (es decir, una función que se aplica a un tipo de datoo variable en concreto) y no una función general, podemos ver la ayuda empleando la variable oelemento con el que queremos usarlo:

>>> frase = "Hombros de gigantes">>> help(frase.replace)

de esta manera vemos la ayuda del método replace() de los string. Deberemos teclear q parasalir de la ayuda. Como acabamos de ver, si queremos ver las funciones disponibles en un módulopodemos hacerlo con dir(modulo). Si usamos ipython, también podemos obtener la ayudaañadiendo ? a la función, método o módulo que nos interese:

In [1]: round? # da ayuda sobre la función round

In [2]: frase.replace? # ayuda sobre el método replace de los strings

Si escribimos help() sin ningún parámetro, entramos en un entorno de ayuda general de Python,donde además de la ayuda de funciones y módulos también podemos saber los módulos instaladosen nuestro ordenador entre otras cosas.

Recuerda que la fuente de información más completa y actualizada es la documentación oficial dePython, donde además de una guía de uso (tutorial), hay una referencia completa de las funcionesy módulos que Python trae por defecto.

2.8. Información y ayuda sobre funciones y módulos 25

Page 32: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

2.9 Ejercicios

1. Calcular a mano cada una de las expresiones siguientes y comprobar, con la ayuda de Pythonen el ordenador, si el resultado es correcto:

16**(1/2)+1/2

16**(1./2)+1/2

3e3/10

15/5e-3+1

2. Evaluar en punto flotante las siguientes funciones para los valores de x=-0.5, 1.1, 2, 3.1:

𝑥4 + 𝑥3 + 2𝑥2 − 𝑥 + 3

4𝑥 3√

| sin𝑥 + tan𝑥|𝑥3−5𝑥(𝑥2+ 1

2)2

3. Calcular a mano cada una de las expresiones siguientes y comprobar, con la ayuda de Pythonen el ordenador, si el resultado es correcto:

int(exp(2*log(3)))

round(4*sin(3*pi/2))

abs(log10(0.01)*sqrt(25))

round(3.21123*log10(1000),3)

4. Calculen a mano cada una de las expresiones siguientes y comprueben, con la ayuda dePython en el ordenador, si ambas soluciones son iguales:

str(2.1) + str(1.2)

int(str(5) + str(7))

int('5' + '7')

str(5 + 7)

str(int(83.6) + float(7))

5. Dada la frase de S. Hawking: “Dios no solo juega a los dados, a veces los tira donde no sepueden ver”, ¿qué funciones o comandos de Python utilizarían para responder o ejecutar losiguiente?:

¿Cuántos carácteres tiene (incluyendo letras, espacios y signos de puntuación)? ¿y pa-labras?

Pasa a una variable los 15 primeros carácteres. Pasa a una lista las cinco primeraspalabras.

26 Capítulo 2. Introducción a la programación con Python

Page 33: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

¿Cuántas letras tiene la última palabra?

Concatenen (unan) el primer tercio de la frase con el último tercio.

6. Crear una variable tipo string con todas las letras del abecedario en minúsculas juntas, sinincluir la eñe, es decir “abcd...”.

Buscar la posición en la cadena de texto de todas las vocales.

Crea otra variable igual, pero formada por las mayúsculas (es decir “ABCD...”).

Divide la cadena de mayúsculas por la mitad y crea una nueva variable con segundamitad primero y después la primera, separadas por un guión.

Usa los índices en cadenas de texto para extraer cada una de las letras necesarias paraescribir “Bohr”, concatenándolas (uniéndolas con +).

7. Crear una lista con el apellido de diez físico/as importantes en la historia. Usando métodose índices de listas hacer lo siguiente:

Ordenar la lista alfabéticamente.

Añadir al final de la lista a Curie si no estaba.

Sacar de la lista a Newton (lo habrás puesto, ¿no?).

En su lugar incluir en la lista a Chandrasekhar (¿o ya lo habían puesto?).

Quitar el primer nombre de la lista.

8. Generar una lista de enteros que vaya de 1 a 19, ambos inclusive, de dos en dos. Usando losíndices de listas hacer lo siguiente:

Añadir el 20 a la lista.

Invertir el orden de la lista (usa la ayuda de Python si no sabes cómo).

Imprimir la lista, salvo el primero y el último.

Crear una nueva variable que contenga los cinco primeros elementos de la lista (conca-tenados, no sumados) y otra con los cinco penúltimos.

Sumar todos los elementos de la lista y divídelo entre su longitud (número de elemen-tos).

9. Crear una variable del tipo string con el valor del número 𝜋, con al menos seis decimales.Dividir la cadena de texto con el número 𝜋 en una lista que tenga en el primer elemento laparte entera y en el segundo elemento la parte decimal. Recordar que sólo las cadenas detexto se pueden separar en listas, no los números.

10. El valor de 𝜋 se puede obtener del módulo math con pi. Imprimir su valor mostrando sólotres decimales.

2.9. Ejercicios 27

Page 34: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

11. Crear una variable que valga 174 (entero) y calcular su raíz cuadrada que almacenan en otravariable. Imprimir ahora una frase que diga “La raiz cuadrada de 174 es 13.1909.” usandolas variables creadas junto con el formato de impresión adecuado.

12. Consideremos una lista de python llamada “cosas” que posee distintos tipos de datos:

cosas = ['a=', '3.14', ['perro', 'gato', 'liebre', 'cabra'], 'coche→˓', 1e4, 4]

Para esta lista, hacer lo siguiente:

Contar el número de elementos de la lista

Calcular el resultado de dividir el segundo elemento por el último.

Extraer la lista de animales y decir cuántos hay.

Contar el número de letras en el tercer elemento de la lista de animales.

Añadir ‘elefante’ a la lista de animales dentro de la lista “cosas”, ordenándola alfabeti-camente.

13. Crear una lista de Python llamada “planetas” con los nombres de los planetas del SistemaSolar, hasta Neptuno. Se pide:

Utilizar una función de Python para conocer la longitud de la lista (es decir, sabercuántos planetas incluye la lista).

Comprobar con algún operador de Python que el último planeta de la lista es Neptuno(¿es cierto o falso?)

Añadir al final de la lista los planetas enanos: Pluton, Ceres, Eris, Makemake y Haumea.

A partir de esta lista y usando los índices de listas creen tres nuevas listas que incluirrespectivamente: a) Los planetas terrestres (hasta Marte, inclusive), b) los planetas ga-seosos (el resto, hasta Neptuno), c) los planetas enanos recién añadidos.

Imprimir por pantalla todas las listas creadas hasta ahora diciendo qué son cada una deellas.

Eliminar la Tierra de la lista original y colocar en su lugar la Luna.

Añadir la Tierra al principio de la lista original.

Ordenar alfabéticamente la lista completa de planetas.

28 Capítulo 2. Introducción a la programación con Python

Page 35: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

CAPÍTULO 3

Análisis de errores

3.1 Tipos de errores

3.1.1 Errores en los Datos y Computacionales

Aunque a veces algunos errores en un cálculo se pueden atribuir a los datos de entrada, en otrasocasiones se atribuyen al propio cómputo o cálculo. Tal distinción no siempre es clara. veámoslocon un ejemplo: en el caso del problema típico de evaluar una función 𝑓(𝑥), donde tenemos que:

𝑥, es valor verdadero de la variable de entrada,

𝑦 = 𝑓(𝑥), es el valor verdadero deseado de salida,

𝑥𝑖 , es valor inexacto o aproximado de entrada,

𝑓𝑎, es la aproximación mejor (algoritmo) a la función 𝑓 ,

podemos calcular que el valor del error absoluto total acumulado en el cálculo será:

𝑦𝑎 − 𝑦 = 𝑓𝑎(𝑥𝑖) − 𝑓(𝑥) = [𝑓𝑎(𝑥𝑖) − 𝑓(𝑥𝑖)] + [𝑓(𝑥𝑖) − 𝑓(𝑥)] ,

que podemos asignar como: [error del cómputo] + [error propagado de los datos].

Fíjense que el algoritmo escogido para realizar el cálculo no influye en el segundo sumando y que,por lo tanto, sólo es el resultado de la propagación de los errores de los datos. El valor del primersumando depende del algoritmo escogido y el segundo depende de cuánto se aproxime el valoraproximado usado al valor verdadero.

Además, en el error del cómputo, podemos diferenciar los siguientes tipos de error:

1. Error de truncamiento. Diferencia entre el resultado verdadero (dada la entrada real) y elresultado que se produciría usando un algoritmo determinado utilizando aritmética exacta.Depende básicamente de la máquina de cómputo empleada. El truncamiento es el númerode dígitos a la derecha del separador decimal con el que cuenta nuestro sistema de cálculo.Algunas veces proporcionará el mismo resultado que el redondeo, pero el truncamiento su-pone poner un límite al número de dígitos decimales por lo que, en definitiva, produce un

29

Page 36: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

redondeo hacia abajo. El error de truncamiento puede ser hasta el doble del error máximo deredondeo.

2. Error de redondeo. Es la diferencia entre el resultado obtenido con un algoritmo con aritméti-ca exacta y el resultado producido por el mismo algoritmo utilizando aritmética de precisiónfinita.

Por medio de la resolución de un ejemplo práctico podemos entender mejor estos conceptos:

Ejemplo: Calculen una aproximación al 𝑠𝑒𝑛(𝜋/10) y los errores (computacional, de los datos yel total) que cometen tomando como dato de entrada (𝑥𝑖) el valor de 𝜋 ≈ 3 y el del algoritmoaproximado (𝑓𝑎) como 𝑠𝑒𝑛(𝑥) ≈ 𝑥.

Solución: error computacional = 0.00448 , error datos = -0.013497. Pero continuen un poco máspara responder a estas preguntas:

¿Qué pasaría si repetimos los cálculos para 𝑠𝑒𝑛(𝜋/50) o 𝑠𝑒𝑛(𝜋/5)?

¿Cuál es el resultado si utilizamos una calculadora simple en vez del computador?, ¿a todosles sale igual?, ¿Cómo explican las diferencias si las hay?.

RECUERDEN que: la calidad en el resultado de un cálculo depende primordialmente de la cali-dad de los datos de entrada, entre otras cosas. Por ejemplo, si nuestros datos de entrada tienen hasta5 cifras significativas en el resultado del cálculo, independientemente de lo bien que lo hagamos,no podemos esperar tener dicho resultado con más de 5 cifras significativas.

3.1.2 Error hacia Adelante (EAD) y Error hacia Atrás (EAT)

Debemos enfatizar una vez más que si los errores con que conocemos los datos de entrada songrandes, por mucho que utilicemos un algoritmo perfecto no vamos a obtener un resultado con unaprecisión mejor. Por ello, es importante estudiar como se propagan los errores y cuáles son susposibles fuentes durante la computación, con el objeto de minimizarlos o al menos acotarlos.

Supongamos que queremos evaluar una función 𝑦 = 𝑓(𝑥) para un cierto valor de 𝑥 dado, y sólopodemos obtener un valor aproximado 𝑦𝑎, utilizando un algoritmo 𝑓𝑎; entonces podemos estimarel error absoluto que cometemos definiendo ERROR ADELANTE como ∆𝑦 = 𝑦𝑎 − 𝑦.

No obstante, no siempre es posible calcularlo y, a veces, debemos resolver el problema de otra for-ma: obtener la solución (aproximada) al problema original podría hacerse obteniendo la soluciónexacta de un problema ‘’modificado’‘, pero no demasiado. Por lo tanto, podríamos preguntarnoscuán grande puede ser la modificación al problema propuesto para obtener la solución real. Enotras palabras, definimos la cantidad ∆𝑥 = 𝑥𝑖 − 𝑥, donde 𝑓(𝑥𝑖) = 𝑦𝑎, como el ERROR ATRÁS;es decir, cuánto error en los datos de entrada podemos ‘’admitir” para explicar todo el error obteni-do al final. Obviamente, éste lo deberemos estimar en un análisis hacia atrás del problema. Desdeeste punto de vista una solución aproximada para un problema dado es buena si es la soluciónexacta a un ‘’problema parecido” al original.

Unas veces será más fácil utilizar uno u otro de los procedimientos y siempre que podamos eligi-remos el algoritmo o procedimiento que nos de menor error.

30 Capítulo 3. Análisis de errores

Page 37: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

Ejemplo: Queremos calcular la raíz cuadrada de 2, 𝑦 =√

2, con la aproximación 𝑦𝑎 = 1.41.Calculen los errores hacia adelante y hacia atrás.

Solución: hacia adelante: |∆𝑦| = |𝑦𝑎−𝑦| = |1.41−1.4142...| = 0.0042. Para calcular el error haciaatrás tenemos en cuenta que

√1.9881 = 1.41 = 𝑥𝑖, entonces |∆𝑥| = |𝑥𝑖 − 𝑥| = |1.9881 − 2| =

0.0119.

3.2 Propagación de errores

Como ya hemos visto, a lo largo de la computación de un problema, los errores iniciales en losdatos de entrada, o en cualquier paso del cómputo, se irán transmitiendo a lo largo del proceso(error computacional) y tendrán influencia en el resultado final. Por lo tanto es importante tratar demantener este error que se va propagando lo más pequeño posible y para ello es interesante sabercomo se propaga el error a lo largo de un cálculo. Veámoslo con un ejemplo.

Si tenemos dos magnitudes 𝑟 y 𝑠 (cuyos errores relativos son 𝑅𝑟 y 𝑅𝑠) y las medimos con erroresabsolutos de ∆𝑟 y ∆𝑠 , con ∆𝑟 ≪ 𝑟 y ∆𝑠 ≪ 𝑠, si efectuamos su producto 𝑄 = 𝑟·𝑠, lo obtendremoscon un error:

𝑄 = 𝑟 · 𝑠 = 𝑟𝑣(1 + 𝑅𝑟) · 𝑠𝑣(1 + 𝑅𝑠) = 𝑟𝑣𝑠𝑣(1 + 𝑅𝑟 + 𝑅𝑠 + 𝑅𝑟𝑅𝑠) ≈ 𝑟𝑣𝑠𝑣(1 + 𝑅𝑟 + 𝑅𝑠) = 𝑄𝑣(1 + 𝑅𝑄) ,

con lo que tenemos finalmente RQ = Rr + Rs.

Ustedes mismos pueden comprobar que, de forma similar, se puede mostrar que si:

𝑄 = 𝑟 · 𝑠 · 𝑡 · 𝑢 · 𝑣 ... entonces 𝑅𝑄 = 𝑅𝑟 + 𝑅𝑠 + 𝑅𝑡 + 𝑅𝑢 + 𝑅𝑣+ ... ,

𝑄 = 𝑟𝑛 entonces 𝑅𝑄 = 𝑛𝑅𝑟 , para 𝑛 ≥ 0.

No obstante podrían comprobar igualmente que en el caso de una división, es decir si 𝑄 = 𝑟/𝑠,entonces 𝑅𝑄 = 𝑅𝑟 −𝑅𝑠. Podría parecer pues que en el caso de una división el error relativo puedeser menor que los de sus miembros pero no es así. Debemos notar que, en general, 𝑅𝑟 y 𝑅𝑠 puedenser positivos o negativos (redefiniendo el valor absoluto) con lo que 𝑅𝑄 = 𝑅𝑟 + 𝑅𝑠 puede variarentre (−|𝑅𝑟| − |𝑅𝑠|) y (|𝑅𝑟| + |𝑅𝑠|).

Esta manera de estimar errores resulta bastante tediosa y a menudo no aporta información relevanteal problema. Normalmente, se suele hablar del error más probable que, para los errores relativosdel producto (o igualmente para el cociente), se define como la raíz cuadrada de la suma de loscuadrados de los errores de los factores que intervienen en el producto (o cociente). En general,se puede demostrar sin demasiadas complicaciones, utilizando el cálculo diferencial, el llamadoprincipio de superposición de errores para una función cualquiera 𝑄(𝑟, 𝑠, 𝑡, ...). En este caso, elerror en 𝑄, ∆𝑄, en función de los errores ∆𝑟,∆𝑠,∆𝑡,... vendría dado por:

(∆𝑄)2 = (𝜕𝑄

𝜕𝑟)2(∆𝑟)2 + (

𝜕𝑄

𝜕𝑠)2(∆𝑠)2 + (

𝜕𝑄

𝜕𝑡)2(∆𝑡)2 + ...

donde 𝜕𝑄𝜕𝑟

es la derivada parcial de 𝑄 respecto de 𝑟 y análogamente las demás.

3.2. Propagación de errores 31

Page 38: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

3.3 Sensibilidad y Acondicionamiento de un problema

Una solución inexacta a un problema también puede ser debida al propio problema que queremosresolver puesto que éste puede ser altamente sensible a pequeñas perturbaciones en los datos deentrada. Esta cualidad es la sensibilidad, que se define como lo sensible que es la solución de unproblema a pequeñas perturbaciones o a los errores en los datos de entrada. Como vemos, tanto lasensibilidad como su medida, el acondicionamiento, están relacionados con la propagación de loserrores en los datos de entrada. Así se habla de:

Problema bien acondicionado o insensible, si el cambio relativo en la solución del problemapuede ser menor o igual que en los datos de entrada.

Problema mal acondicionado o sensible, cuando no sucede lo anterior.

Definimos el acondicionamiento de un problema como el cociente entre el Cambio Relativo en laSolución y el Cambio Relativo en la Entrada, es decir:

|𝑓(𝑥𝑖)−𝑓(𝑥)𝑓(𝑥)

|

| (𝑥𝑖−𝑥)𝑥

|=

|Δ𝑦𝑦|

|Δ𝑥𝑥|,

o también: Error Relativo Adelante / Error Relativo Atrás , que siempre resulta difícil de obtener.

Así que a menudo se define que:

Error Relativo Adelante ≤ C · Error Relativo Atras ,

Es interesante darse cuenta que 𝐶 se interpreta como un factor de amplificación del cambio enlos datos de entrada. Si es mucho mayor que uno tendremos un problema mal acondicionado oaltamente sensible a los errores en los datos de entrada.

De la definición anteriormente efectuada, y teniendo en cuenta la aproximación 𝑓(𝑥𝑖) = 𝑓(𝑥) +𝑓 ′(𝑥)∆𝑥 + ... podemos calcular 𝐶 de forma aproximada como:

𝐶 = |𝑓 ′(𝑥)Δ𝑥𝑓(𝑥)

Δ𝑥𝑥

| = |𝑥𝑓′(𝑥)

𝑓(𝑥)|

3.4 Estabilidad y Exactitud de un algoritmo

El concepto de estabilidad de un algoritmo computacional es parecido al de sensibilidad de unproblema matemático. La diferencia entre ellos es que la estabilidad se refiere al efecto de loserrores de computación mientras que el de sensibilidad (o acondicionamiento) se refiere a losefectos de los errores de los datos de entrada en la solución del problema.

Así pues un algoritmo es estable si el resultado que produce es relativamente insensible a lasperturbaciones hechas en la computación; desde el punto de vista de análisis de errores, es establesi el resultado es la solución exacta al problema aproximado. Esta sería la estabilidad en sentido

32 Capítulo 3. Análisis de errores

Page 39: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

estricto. Podemos ser más permisivos, estable en sentido laxo, si el algoritmo produce la solución‘casi exacta’ al problema aproximado.

La exactitud, como ya sabemos, se refiere a lo cerca que está la solución computada de la so-lución verdadera del problema matemático. La estabilidad de un algoritmo no garantiza que lasolución computada sea exacta. La exactitud depende tanto de la sensibilidad (acondicionamiento)del problema matemático como de la estabilidad del algoritmo utilizado para resolverlo.

3.5 Ejercicios

1. Tengamos un movimiento armónico simple definido por 𝑦 = sin(2𝜔𝑡 + 𝜑), donde 𝜔 =5.5𝐻𝑧. Encontrar el error relativo en 𝑦 debido a un error relativo en 𝑡 del 0.1 % cuando:𝑡 = 𝜋

2𝜔s, y 𝑡 = 𝜋

𝜔s. Finalmente calculen los errores relativos antedichos para el caso de

𝜑 = 𝜋/3.

2. Aproximemos la función sin(𝑥) por su desarrollo en serie sin(𝑥) ≈ 𝑥− 𝑥3

3!+ 𝑥5

5!− 𝑥7

7!+ .... Se

pide que calculen los errores hacia adelante y hacia atrás para 𝑥 = 0.1, 0.5, 1.0, en los casosen que:

Se aproxima la función por el primer término del desarrollo en serie solamente.

Se aproxima la función por los tres primeros términos del desarrollo en serie solamente.

3. Calculemos la densidad media del planeta Tierra contestando a las cuestiones siguientes:

Indiquen las hipótesis más importantes del modelo.

Indiquen el algoritmo que van a usar y busquen los datos de entrada necesarios con suserrores, si los hay.

Calculen primero el volumen de La Tierra y sus errores absoluto y relativo. Tomencomo valor verdadero 1.08321 × 1012𝐾𝑚3.

Calculen finalmente su densidad y expliciten cuantas cifras significativas tiene el resul-tado final.

4. Cuando un electrón 𝑒−, de masa 𝑚𝑒, se mueve a velocidad 𝑣 en un acelerador sincrotrón sumasa aumenta según 𝑚 = 𝑚𝑒[1 − (𝑣/𝑐)2]−(1/2), donde 𝑚𝑒 es su masa en reposo y 𝑐 es lavelocidad de la luz en el vacío. Se pide:

Demostrar que el incremento (error) relativo en 𝑚 es aproximadamente (𝑣/𝑐)2 veces elincremento (error) relativo en 𝑣, suponiendo que (𝑣/𝑐) ≪ 1.

Calculen la masa del 𝑒− si su velocidad es de 35500. Km/s y en cuánto aumenta siacelera hasta 36000. Km/s.

5. Supongamos que medimos la aceleración de la gravedad 𝑔, a nivel del mar en un punto dela Tierra de 0∘ de latitud y 0∘ de longitud, utilizando el método de las oscilaciones de un

3.5. Ejercicios 33

Page 40: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

péndulo simple (midiendo su longitud ℓ y su periodo 𝜏 ). Del resultado de la experiencia seobtiene que ℓ = 10.002 ± 0.0001𝑚 y 𝜏 = 6.42559𝑠± 1𝜇𝑠. Se pide:

Cuál es el error relativo que tendrá la determinación de 𝑔.

Cuál es la medida final de la aceleración de la gravedad con su error absoluto.

6. Se ha observado el cuásar más lejano conocido midiendo un desplazamiento hacia el rojo de𝑧 = 8.1 ± 0.3. Utilizando el efecto Doppler relativista nos permite calcular una velocidadde recesión de 288748 ± 2338𝐾𝑚/𝑠 . Utilicen la Ley de Hubble para calcular la distancia ala que se encuentra e indiquen la precisión con que se conoce. Nota: La ley de Hubble diceque 𝑣 = 𝐻 · 𝑑, donde 𝑣 es la velocidad de recesión del objeto en cuestión, 𝑑 es su distanciay 𝐻 es la llamada constante de Hubble, una constante cuyo valor medido (en 2009 usandoel HST) es de 74.2 ± 3.6𝐾𝑚/𝑠/𝑀𝑝𝑐. 1𝑀𝑝𝑐 = 106𝑝𝑐 ; 1 pc es la distancia desde la cual seve la unidad astronómica (UA, distancia media entre la Tierra y el Sol) bajo un ángulo de 1segundo de arco.

34 Capítulo 3. Análisis de errores

Page 41: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

CAPÍTULO 4

Programas ejecutables

4.1 Reutilizando el código

Además de usar python de manera interactiva desde una consola, es posible crear programas oscripts (guiones) ejecutables; de hecho es la forma más habitual de trabajar. Un programa o scriptes un fichero de texto con los comandos o sentencias de python escritos de manera consecutiva yque se interpretarán línea a línea al ejecutar el script desde una consola de comandos del sistemaoperativo. Bastará utilizar un editor de textos cualquiera (kate, gedit, notepad, etc.), crear un ficherocon el nombre que queramos y con extensión .py para que éste lo identifique como un programaen Python. En él escribiremos las sentencias o comandos uno detrás de otro, en el orden en quequeramos que sean ejecutados.

El siguiente ejemplo es un pequeño programa que llamaremos cubo.py que calcula el cubo de unnúmero cualquiera dado por el usuario:

#!/usr/bin/python#-*- coding: utf-8 -*-

# Mensaje de bienvenidaprint("Programa de calculo del cubo de un numero.\n")# La \n antes de las comillas introduce una línea en blanco

# Numero de entradax = 23.0

# Calculo el valor del cubo de xy = x**3

# Imprimo el resultadoprint("El cubo de %.2f es %.2f" % (x, y))

El programa se puede ejecutar ahora desde una consola desde el directorio en donde tenemos elarchivo con el programa, escribiendo en ella

35

Page 42: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

$ python cubo.py

y la respuesta del programa será:

Programa de calculo del cubo de un numero.

El cubo de 23.00 es 12167.00

En la primera línea del programa hemos escrito #!/usr/bin/python (válido para Linux o Mac OS,no Windows)para indicar la ruta donde tenemos instalado python. La segunda línea, #-*- coding:utf-8 -*- hemos indicado el tipo de codificación UTF-8, para poder poner caracteres especialescomo tildes y eñes.

Ya que la primera línea indica en qué directorio está el ejecutable de python, el programa tam-bién se puede ejecutar como un comando o programa del sistema escribiendo, fuera de Python,únicamente:

$ ./cubo.py

Pero para que funcione esto tenemos que asegurarnos de que el programa tiene permisos de ejecu-ción. Si no lo tiene se lo damos (ver Apéndice B), que para Linux o Mac se hace como sigue:

$ chmod u+x cubo.py # Para Linux y Mac

La primera línea del programa depende del sistema operativo que está instalado en el ordenador,que en el ejemplo se supone para Linux (o Mac). En el caso de Windows debemos escribir en laprimera línea de programa algo similar a esto:

#!C:/Python/python.exe -u # o el lugar en donde resida el# ejecutable python.exe en Windows

pero puede variar según la instalación de python del ordenador y además, en Windows es máscomún ejecutar un programa desde el Explorador de Ficheros (File manager) donde funcionarásiempre que esté configurado para que los ficheros .py se ejecuten con Python, por lo que notiene tanta utilidad en el el caso de Windows. De cualquier manera, la ejecución de un programadesde fuera de la consola de python siempre funcionará usando:

$ python cubo.py

Si quieres ejecutar el programa desde dentro de la consola de python, puedes usar lo siguente:

>>> execfile('cubo.py')

de igual manera, si estamos usando ipython podemos usar el comando mágico run:

In [1]: run cubo.py

36 Capítulo 4. Programas ejecutables

Page 43: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

La ventaja en este último caso con ipython es que una vez ejecutado, las variables definidas en elprograma lo estarán ahora en la sesión de ipython a nuestra disposición, lo que es muy útil paraprobar y corregir nuestro programa interactivamente.

In [2]: print x23.0

es decir, vemos ahora tenemos la variable x está definida en nuestra sesión.

Hay que fijarse que en el programa muy a menudo hay sentencias comentadas, que son las queempiezan con #. Estas líneas no son ejecutables y son ignoradas por el intérprete de python;se usan solamente para añadir notas o comentarios. Es muy recomendable incluir comentarios deeste tipo que expliquen lo que el programa va haciendo, porque nos ayudarán a recordar qué haceo cómo funciona el programa cuando volvamos a leerlo nosotros, u otros usuarios, y queramosreutilizarlo o modificarlo. Se pueden incluir comentarios de varias líneas, por ejemplo al inicio delprograma para explicar lo que hace, usando comillas triples; todo lo que vaya entre ellas será uncomentario y por tanto ignorado por el intérprete.:

# Este es un comentario de una lineaprint("La raíz cuadrada de 2 es %.2f" % sqrt(2.))

"""Este un comentario queusa varias lineas y está limitadopor comillas triples. Todo lo que estéentre ellas no se intenta ejecutar"""print("El cubo de 2 es %.1f" % 2.0**3)

4.2 Definiendo funciones

En capítulos anteriores ya hemos aprendido a usar funciones; algunas de ellas están predefinidas(abs(), round(), etc.) mientras que otras deben importarse de módulos antes de poder ser uti-lizadas (sin(), sqrt() se importan del módulo math). No obstante, además de las funcionesincluidas en python, el usuario puede crear las suyas propias, que permiten reutilizar partes delcódigo de un programa sin necesidad de repetirlo varias veces. Las funciones para poder ser utiliza-das o llamadas o invocadas, antes hay que definirlas. Veamos por ejemplo, como podemos escribirun programa con una sencilla función para calcular el cubo de un número y otra para imprimir unmensaje:

#!/usr/bin/python#-*- coding: utf-8 -*-

# ahora definimos una función que calcula el cubo de un número→˓cualquiera

def cubo(x):

4.2. Definiendo funciones 37

Page 44: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

y = x**3return y

# Ahora utilizamos la funcion para calcular el cubo de 4resultado = cubo(4.0)

# imprimo el resultadoprint(resultado)

Definimos la función cubo() que calculará el cubo de un número cualquiera. Nótese que ladefinición de la función se hace en líneas identadas (con sangría) y acaba con la sentencia returnpara devolver el valor calculado de la función, sin imprimirlo necesariamente. Esto es lo máshabitual cuando se crea un función: hacer todas las operaciones necesarias y luego utilizar returnpara devolver un valor. Después de utilizar la función, el resultado puede imprimirse, volcarse auna variable, o lo que el programador necesite. También podemos definir funciones que dependande varios parámetros (separados por comas); lo único que debemos hacer a la hora de utilizarladespués será invocarla con el mismo número de parámetros y los valores que queramos en el mismoorden que en la definición. Alternativamente, podemos definir una función en la que hacemosvarios cálculos que queremos que nos devuelva; en este caso, los podemos devolver por medio delreturn en una lista que contenga dichos resultados. Más adelante veremos un ejemplo.

Vamos a definir a continuación una función con dos variables:

#!/usr/bin/python#-*- coding: utf-8 -*-

# Definimos una función que calcula el área de un triángulodef area_triangulo(b,h):

area = b*h/2.return area

# Utilizamos la funcion para calcular el área de un triángulo de 2.3→˓de base

y 3 de alturaresultado = area_triangulo(2.3,3.0)

# imprimo el resultadoprint(resultado)

No obstante, no todas las funciones devuelven un valor y en este caso los llamamos procedimien-tos. Veamos un ejemplo interesante, la función que llamamos saludo() en el que no calculamosnada y por tanto no devolvemos un valor:

#!/usr/bin/python#-*- coding: utf-8 -*-

# definimos una función que muestra en pantalla un mensaje de saludo

38 Capítulo 4. Programas ejecutables

Page 45: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

def saludo(nombre):print("Buenas tardes, %s " % nombre)

# Utilizamos ahora la función para saludar a Juansaludo('Juan')# Imprime: Buenas tardes, Juan

En este caso no calculamos nada y por lo tanto, no necesitamos acabar con un return la defi-nición del procedimiento. Lo que hacemos es ordenar que se imprima una variable y por lo tantosiempre se imprime una línea cada vez que se llama a la función.

Advertencia: En Python el sangrado (o identación) es obligatorio, porque se emplea paraseparar los bloques que indican donde empiezan y terminan las funciones (también comoveremos más adelante los bucles y condicionales). Si el sangrado no es correcto, se obtendráun resultado equivocado o nos devolverá un errror. El sangrado habitual es de 4 espacios, si noes así en nuestro editor, deberemos cambiarlo en las preferencias.

4.2.1 Variables locales y globales

En la definición de las funciones es posible definir y utilizar variables cuya acción y definiciónqueda circunscrita a la propia función. Son las llamadas variables locales que fuera de la funciónno tienen validez. Veamos un ejemplo. Calculemos el volumen, area superficial y la longitud decualquier circunferencia máxima en una esfera de radio R definiendo una función que llamamosesfera():

#!/usr/bin/python#-*- coding: utf-8 -*-

# importamos todas las funciones del módulo mathfrom math import *

# ahora definimos una función que calcula los parámetros de la esferadef esfera(r):

pir = pi*rlongitud = 2.*pirsuperficie = 4.*pir*rvolumen = superficie*r/3.# devolvemos una lista con los resultadosreturn [longitud,superficie,volumen]

# Ahora utilizamos la función para el caso de una esfera de radio 3.215l,s,v = esfera(3.215)

4.2. Definiendo funciones 39

Page 46: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

# imprimimos el resultadoprint('La longitud del circulo maximo es: %.3f' % l)print('La superficie de la esfera es: %.3f' % s)print('El volumen de la esfera es: %.3f' % v)

Nótese que en la definición de la función usamos la variable pir que es interna o local, es decir, sólose usa dentro de la función ya que no la devolvemos al hacer el return. Por lo tanto, si la quisiéramosusar (o saber el valor que tiene) fuera del cuerpo de la función, en el programa principal, nopodríamos (por ejemplo, no podemos hacer print). Los parámetros de entrada en una funcióntambién son variables locales; en este caso r. Las demás variables definidas son variables llamadasglobales ya que las podemos usar fuera del cuerpo de la función. Es conveniente no mezclarlas,aunque podemos hacerlo si tenemos cuidado; es decir, una misma variable podemos usarla fueray dentro del cuerpo de la función y a pesar de que se llamen igual dentro del cuerpo de la funcióntendrá el valor que sea (como local) y fuera de él también lo tendrá, como global.

4.3 Entrada de datos por pantalla

Generalmente el valor de una variable se asigna haciendo por ejemplo pi=3.1416, pero se puedehacer que pida una entrada por teclado usando la función raw_input() de la forma siguiente(pueden probarlo en la consola de Python):

>>> entrada_numero = raw_input('Dame un numero: ' )Dame un numero: # Escribimos 22 con el teclado y pulsamos Enter/

→˓Intro

y esperará hasta que se le de un número o cualquier otro carácter (por ejemplo, le damos 22). Esmuy importante saber que el valor que se asigna a la variable, en este caso entrada_numero, essiempre un string, aunque se introduzca un número. Por ejemplo, pueden comprobar que en elejemplo anterior el valor de la variable entrada_numero es “22”, con comillas, o sea un string. Siqueremos operar aritméticamente con el resultado debemos pasarlo a int o a float, según cómo lovayamos a usar, por ejemplo:

entrada_numero = float(entrada_numero)

Ahora, la variable entrada_numero es del tipo float y vale 22.0. Con la ayuda de esta funciónpodemos crear programas que pidan uno o varios números (u otro tipo de dato) al usuario y hacercálculos tan complejos como queramos con ellos, sin tener que cambiar los valores de entrada enla correspondiente línea del programa cada vez que se utilice. Por ejemplo, podríamos modificarel programa anterior de manera que pida al usuario el radio de la esfera cuando se ejecute elprograma:

#!/usr/bin/python#-*- coding: utf-8 -*-# este programa calcula el volumen, la superficie y la longitud

40 Capítulo 4. Programas ejecutables

Page 47: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

# del círculo máximo de una esfera de radio r que solicita por pantalla# teo# marzo 2012

# importamos todas las funciones del módulo mathfrom math import *

# ahora definimos una función que calcula los parámetros de la esferadef esfera(r):

pir = pi*rlongitud = 2.*pirsuperficie = 4.*pir*rvolumen = superficie*r/3.# devolvemos una lista con los resultadosreturn [longitud,superficie,volumen]

# ahora solicitamos por pantalla el radio de la esferaradio = float(raw_input('Deme el radio de la esfera: ' ))

# Ahora utilizamos la función, guardando el resultado en tres variableslongitud, superficie, volumen = esfera(radio)

# imprimimos el resultadoprint('La longitud del circulo maximo es: %.3f' % longitud)print('La superficie de la esfera es: %.3f' % superficie)print('El volumen de la esfera es: %.3f' % volumen)

De esta forma, si queremos reutilizar el programa para el cálculo en el caso de otra esfera de radiodiferente no tenemos que cambiar nada del mismo y podemos volver a ejecutarlo tal cual está sinproblemas, introduciendo el radio que queramos cada vez que la usemos.

También podemos usar a función eval() para introducir valores de una variable. Esta funciónevalúa el tipo de dato que introducimos:

# Introducimos dos valores float en la variable datos>>> datos = eval(raw_input('x, y = '))x, y = # Introducimos 1.2, 1.3

>>> print datos(1.2, 1.3)

>>> type (datos)<type 'tuple'> # Nos devuelve una tupla

Introducimos ahora dos variables separadas x e y:

4.3. Entrada de datos por pantalla 41

Page 48: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

# Introducimos dos valores float en dos variables diferentes>>> x, y = eval(raw_input('x, y = '))x, y = # Introducimos 1.2, 1.3

#Imprimimos una de ellas>>> print x1.2

>>> type (x)<type 'float'> # Nos devuelve un float porque lo introdujimos como

→˓tal

4.4 Definiendo un módulo personal

Ya hemos visto como las funciones ayudan a hacer los programas más legibles y cortos al evitar quetengamos que escribir una y otra vez los mismos algoritmos en un mismo programa. Sin embargoa medida que vayamos aprendiendo a programar iremos haciendo más y más programas. Es muyposible que en varios de estos programas usemos las mismas funciones con lo que acabaremosteniendo que escribir la misma función en cada programa. Para evitar esta cuestión lo mejor esdefinir nuestro propio módulo que incluya las funciones que vamos definiendo.

Un módulo no es más que una colección de funciones que podemos utilizar desde cualquier pro-grama. Ya hemos visto que la distribución estándar de python ofrece un buen número de módulospredefinidos que se agrupan normalmente por ámbitos de aplicación: funciones matemáticas enmath; las de numeros aleatorios en random; las que tratan con cadenas en string, etc... Así pues,¿para qué vamos a re-escribir continuamente en nuestros programas funciones que nosotros yahemos escrito antes? Pues para evitarlo, creamos un módulo.

Para ello, creamos un fichero de texto que llamamos por ejemplo: funciones.py y vamos a incluiren él todas las funciones que vayamos creando. El sufijo o extensión py significa que lo que habrádentro del fichero va a ser código python. Incluyamos en él las funciones que hayamos definidoen este capítulo:

from math import *

def cubo(x):y = x**3return y

def saludo(nombre):print("Buenas tardes, %s" % nombre)

def esfera(r):pir=pi*r

42 Capítulo 4. Programas ejecutables

Page 49: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

longitud = 2.*pirsuperficie = 4.*pir*rvolumen = superficie*r/3.return [longitud, superficie, volumen]

Listo. Ya podemos utilizar o importar el módulo en cualquier programa sin más que hacer:

>>> # importamos la funcion esfera del módulo funciones>>> from funciones import esfera

>>> # o bien, importamos todas las funciones del módulo funciones>>> from funciones import *

Cuando se importa o ejecuta por vez primera funciones.py verás que python crea automáticamen-te un fichero llamado funciones.pyc; este fichero contiene una versión del módulo más fácil decargar en memoria que el original, pero ininteligible para nosotros ya que está codificado en “có-digo binario”. De esta forma python acelera la carga del módulo en sucesivas ocasiones sin quetengamos que preocuparnos nosotros de nada. Si se borra el .pyc no afectará al programa originaly simplemente se volverá a crear cuando se importe el módulo otra vez. Igualmente, si se modi-fica de alguna manera el programa el funciones.py, se vuelve a crear una versión actualizada defunciones.pyc. Ahora podemos probar nuestro módulo de funciones personales:

>>> saludo("Teo")>>> Buenas tardes, Teo

Se trata de una manera muy práctica de tener a mano las funciones más usadas en nuestros cálculossin tener que copiar el código de un programa a otro.

4.5 Estructura de un programa o script y normas de es-critura

Al hacer un programa es siempre conveniente guardar una cierta estructura que ayudará a enten-derlo y corregirlo. No hay reglas definidas para ello pero una buena práctica podría ser la siguiente:

1. Primero poner los comentarios con el tipo de codificación, objeto del programa, nombre delprogramador y fecha de la última modificación.

2. Después incluir las sentencias que importan los módulos que nos van a hacer falta para eldesarrollo del algoritmo solución del problema.

3. Después incluimos la definición de las funciones y procedimientos que vayamos a utilizar.

4. A continuación vendría el grueso del algoritmo o programa principal.

5. Finalmente, incluimos las órdenes de salida o de escritura de la solución del problema plan-teado.

4.5. Estructura de un programa o script y normas de escritura 43

Page 50: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

Además de una correcta y ordenada estructura general del programa, es conveniente mantener cier-tas buenas prácticas de codificación. Estas normas no son obligatorias, como la propia sintaxisdel lenguaje, pero conviene seguir las recomendaciones de los desarrolladores de Python. Un ejem-plo básico para entender a lo que nos referimos es el sangrado, que como hemos visto en Python enobligatorio, pero mientras la estructura de bloques sea correcta, a Python no le importa el númerode espacios que se usen. Pues bien, aunque a Python le da igual, la recomendación es usar cuatroespacios (no tabuladores) para la sangrar bloques. Hay otras normas similares muy sencillas quedebemos intentar seguir, como estas:

Cuando sea posible, define variables con nombres que tengan algún sentido o que puedas identificarfácilmente, no importa que sean más largas. Por ejemplo, en un programa podríamos escribir:

a = 10. # alturab = 3.5 # baseprint("El volumen es %.1f" % (a*b))

pero, ¿qué significan a y b? lo sabemos por el comentario (bien hecho), pero si más adelante nosencontramos con esas variables, tendremos que recordar cual es cual. Es mejor usar nombres consignificado:

altura = 10.base = 3.5print("El volumen es %.1f" % (altura*base))

De hecho podemos usar el nombre para dar más información sobre la variable:

velocidad_metros_segundo = 12.5angulo_radianes = 1.3

Las líneas de código no deben ser muy largas, como mucho 72 caracteres. Si se tiene una línealarga, se puede cortar con una barra invertida (\) y continuar en la siguiente línea:

print("Esta es una frase muy larga, se puede cortar con una \y seguir en la línea inferior.")

Dentro de paréntesis, corchetes o llaves, no dejar espacios inmediatamente dentro de ellos:

Sí: funcion(num[1], pares: 2)No: funcion( num[ 1 ], pares: 2 )

Justo después de coma, punto y coma y punto, separar con un espacio, para mayor claridad, perono antes:

Sí: print x, y; x, y = y, xNo: print x , y ; x , y = y , x

44 Capítulo 4. Programas ejecutables

Page 51: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

4.6 Ejercicios

1. Escribir una función que calcule la distancia cartesiana entre dos puntos cualesquiera decoordenadas (𝑥1, 𝑦1) y (𝑥2, 𝑦2).

2. Escribir un programa que calcule la densidad media de cualquier planeta, pidiendo comoentrada su masa y su radio medio.

3. La variación de temperatura de un cuerpo a temperatura inicial 𝑇0 en un ambiente a 𝑇𝑠

cambia de la siguiente manera:

𝑇 = 𝑇𝑠 + (𝑇0 − 𝑇𝑠) 𝑒−𝑘𝑡

con 𝑡 en horas y siendo k un parámetro que depende del cuerpo (usemos k=0.45). Una latade refresco a 5ºC queda en la guantera del coche a 40ºC. ¿Qué temperatura tendrá 1, 5,12 y 14 horas? Encuentren las horas que tendríamos que esperar para que el cuerpo esté a0.5ºC menos que la temperatura ambiente. Definir funciones adecuadas para realizar amboscálculos para cualquier tiempo y cualquier diferencia de temperatura respecto al ambienterespectivamente.

4. Crear una función dentro de un programa que calcule el resto (o residuo) de una división.Probarlo haciendo un programa que pida dos números al usuario para dividir y devuelva elresto usando esta función.

5. Para el cálculo de la letra del DNI se calcula el residuo 23 del número, es decir, el resto quese obtiene de la división entera del número del DNI entre 23. El resultado será siempre unvalor entre 0 y 22 y cada uno de ellos tiene asignado una letra según la siguiente tabla:

0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22

T R W A G M Y F P D X B N J Z S Q V H L C K E

Escribir un programa que solicite el número de DNI al usuario y calcule la letra que lecorresponde.

6. Escribir su propio módulo o librería que contenga todas las funciones que haya hecho pararesolver los problemas anteriores. Escribir un programa principal en el que las utilice y deesta forma comprueba si funciona correctamente.

4.6. Ejercicios 45

Page 52: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

46 Capítulo 4. Programas ejecutables

Page 53: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

CAPÍTULO 5

Control de flujo

Hemos visto que un programa o script consiste en una serie de sentencias que se ejecutan unadetrás de otra siguiendo así el flujo natural de ejecución. No obstante, puede convenirnos cambiaresta secuencia de ejecución, de manera que nuestro programa haga una acción u otra según ciertascondiciones. Para ello se utilizan las sentencias de control de flujo, que nos permiten interactuarcon el programa, tomar decisiones, saltar hacia adelante o hacia atrás y ejecutar sentencias en unorden diferente al habitual. Son un elemento básico presente en cualquier lenguaje programacióny en este capítulo veremos las más importantes.

5.1 El bucle for

Realiza una misma acción o serie de acciones o sentencias varias veces. Una manera común deusar el for es para recorrer con una variable cada uno de los elementos de una lista. Esta seríauna manera básica de usarla en un programa de Python:

for isla in ['La Gomera', 'Maui', 'Cuba', 'Sri Lanka']:print("La isla de %s" % isla) # El sangrado es obligatorio

"""Resultado:La isla de La GomeraLa isla de MauiLa isla de CubaLa isla de Sri Lanka"""

En este caso isla es una variable muda (no definida previamente) que va tomando el valor decada uno de los elementos de la lista que queramos de forma sucesiva; el bucle finaliza cuando seterminen los elementos de la lista. Hay que darse cuenta de la importancia del sangrado del bucleya que Python reconoce que el bucle termina cuando el sangrado cambia.

Naturalmente, también es posible hacerlo definiendo antes la lista en una variable:

47

Page 54: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

islas = ['La Gomera', 'Maui', 'Cuba', 'Sri Lanka']for isla in islas:

print("La isla de %s" % isla)

Aquí es especialmente útil la función range() que, como ya vimos, crea automáticamente unalista de números enteros; con ella, podemos usar un bucle for para hacer cálculos con los elementosde una lista de números; por ejemplo:

for i in range(2,12,2):print("El cubo de %d es %d" % (i, i**3) )

"""ResultadoEl cubo de 2 es 8El cubo de 4 es 64El cubo de 6 es 216El cubo de 8 es 512El cubo de 10 es 1000"""

El mismo resultado al que llegamos al principio se puede llegar utilizando el bucle for de otraforma. Consiste en definir una variable índice para escoger o recorrer los elementos de lalista; en este caso, la variable índice recorrerá otra lista (con idéntico número de elementos de lalista que se quiere recorrer) que contiene el valor de los índices; la podemos crear usando len()dentro de range(). Veamos un ejemplo:

islas = ['La Gomera', 'Maui', 'Cuba', 'Sri Lanka']

for j in range(len(islas)):print("%d- La isla de %s" % (j+1, islas[j]))

"""Resultado1- La isla de La Gomera2- La isla de Maui3- La isla de Cuba4- La isla de Sri Lanka"""

Aquí, con la función range(len(islas)) hemos creado una lista nueva de tantos elemen-tos (números enteros en este caso) como elementos tiene la lista islas, es decir, desde 0 hastalen(islas)-1 (la longitud de la lista); después hacemos recorrer al índice j esta lista e iden-tificamos los elementos de la otra lista con el índice apropiado islas[j]. Esta forma de utilizarel bucle for nos permite manejar elementos de otras listas que tengan la misma longitud.

Como trabajar de esta manera con elementos de una lista y sus índices al mismo tiempo es muycomún, Python tiene la función enumerate(), que devuelve un elemento y su índice en unbucle, sin tener que usar range(). Se usa de la siguiente manera:

48 Capítulo 5. Control de flujo

Page 55: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

for j, isla in enumerate(islas):print("%d- La isla de %s" % (j+1, isla))

como se ve el resultado es el mismo sin tener que preocuparnos por el índice. Puesto queenumerate() devuelve en cada ciclo dos elementos, índice y valor, hemos tenido que usar dosvariables, j e isla en lugar de una.

Nota: Además de la función range(), python también tiene un función llamada xrange() quees prácticamente igual, pero usada en un bucle for, va creando los elementos a medida que los vanecesitando, en lugar de crearlos todos de una vez y guardarlos en memoria ( es decir, no poduceuna lista). Por eso, xrange() es mucho más rápido y eficiente que range(), especialmentecuando trabajamos con listas de muchos números.

Los bucles for nos permiten crear nuevas listas con resultados de cálculos fácilmente, por ejem-plo:

# Importo la función log10 del módulo mathfrom math import log10

b = [2.3, 4.6, 7.5, 10.]

c = [log10(x) for x in b]

print(c)

# Resultado:# [0.36172783601759284, 0.66275783168157409, 0.87506126339170009, 1.0]

Al hacer esto hemos creado una nueva lista que contiene el logaritmo en base 10 de cada uno denúmeros en la lista b. Con respecto a la función logaritmo, generalmente se denota el de base 10como acabamos de ver, mientras que la función log() calcula el logaritmo natural o de basee. Con la función log() también se puede calcular el logaritmo de cualquier base, indicándolacomo un segundo parámetro; por ejemplo, para calcular el logaritmo en base 3 de 5 haríamoslog(5,3).

Otra aplicación muy interesante del bucle for es la suma de series de números. Supongamos quequeremos calcular el sumatorio siguiente

∑10𝑛=1

1𝑛2 . Para ello debemos definir una variable en la

que vamos acumulando los términos del sumatorio. Abrimos un fichero para escribir el programaque realiza este cálculo:

suma = 0.0 # Variable para ir acumulando los términos del sumatorio

print "n termino n sumatorio hasta n"print "--------------------------------"

5.1. El bucle for 49

Page 56: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

for n in range(1,11):term = 1/n**2.0 # calculamos el término del sumatoriosuma = term + suma # acumulamos el término en la variable sumaprint("%3d %10.6f %10.6f" % (n, term, suma)) # imprimimos el

→˓resultado

"""RESULTADO QUE OBTENEMOS EN PANTALLA AL EJECUTARLOn termino n sumatorio hasta n--------------------------------1 1.000000 1.0000002 0.250000 1.2500003 0.111111 1.3611114 0.062500 1.4236115 0.040000 1.4636116 0.027778 1.4913897 0.020408 1.5117978 0.015625 1.5274229 0.012346 1.539768

10 0.010000 1.549768"""

En este ejemplo definimos una variable suma con valor inicial cero para ir acumulando en ella cadauno de los términos de la suma, que metemos en la variable term y sumándola en cada ciclo delbucle hasta que termina. El valor final de la suma será el que tenga la variable suma al terminar elbucle.

Si no conocemos el número de veces que hay que ejecutar las operaciones (es decir, el número detérminos de la serie a sumar) existe otra forma de definir los bucles utilizando la sentencia while.

5.2 El bucle while

En este bucle se ejecutan una o varias operaciones mientras cierta condición que definimos seacierta. Por ejemplo para imprimir los números naturales del 0 al 5 podemos hacer (los númerosnaturales pueden definirse considerando el cero o no según el área de la ciencia):

cuentas = 0

while cuentas < 6:print(cuentas)cuentas = cuentas + 1

0123

50 Capítulo 5. Control de flujo

Page 57: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

45

En este ejemplo se define inicialmente un valor 0 para la variable cuentas y su valor se va re-definiendo, aumentado en 1 e imprimiéndolo. Mientras cuentas sea menor que 6 las sentenciasdentro del bucle while seguirán ejecutándose y se detendrá cuando la condición deje de cumplirse,es decir cuando cuentas valga 6, algo que podemos comprobar después del bucle sin más queescribir:

print(cuentas)# Imprime 6

Nótese que, a diferencia del bucle for, en este caso debemos incrementar explícitamente el valorde la variable que interviene en la condición, de no haber aumentado el valor de cuentas en cadaciclo del bucle, su valor nunca cambiaría y tendríamos bucle infinito. Si esto nos ocurre podemosparar el programa con las teclas Ctrl+C (pueda tardar un poco en responder).

Veamos otro ejemplo. Supongamos que tenemos unos ahorros en el banco (unos míseros 100euros) y queremos saber el tiempo que nos llevará tener cierta cantidad (p.e. 500 euros) graciasa los intereses que producen. Lo que hacemos es crear un bucle while en el que añadiremosanualmente los intereses y vamos contando los años. Cuando lleguemos a la cantidad deseada elbucle se detendrá y tendremos los años que nos llevaría; el código del programa podría ser este:

mis_ahorros = 100 # Partimos de 100 eurosinteres = 1.05 # Interés del 5% anualanhos = 0 # Tiempo de inicio, cuando tenemos 100

→˓euros

# Queremos llegar a tener 500 euroswhile mis_ahorros < 500:

# Añado los intereses anuales a los ahorrosmis_ahorros = mis_ahorros * interes

# Añado un año a la cuenta de años ya que# cada ciclo while equivale a un añoanhos = anhos + 1

print("Me llevará %d anhos ahorrar %d euros." % (anhos, mis_ahorros))

# Resultado que obtendremos al final del programa:# Me llevará 33 anhos ahorrar 500 euros.

Podemos utilizar el bucle while con una condición negativa, es decir de que no se cumpla,usando while not de la forma siguiente:

5.2. El bucle while 51

Page 58: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

Figura 5.1: Diagrama de flujo de una sentencia while.

x = 0while not x == 5:

x = x + 1print("x = %d" % x)

""" Resultado que obtenemos del programa:x = 1x = 2x = 3x = 4x = 5"""

Sin embargo, hay que tener cuidado cuando se comparan, mediante una igualdad exacta, númerosdecimales o de coma flotante floats entre sí. Debido a la precisión finita de los ordenadores, esposible que una determinada igualdad nunca se cumpla exactamente y por lo tanto la ejecucióndel bucle nunca se detendrá. Comprobemos este aspecto con un ejemplo en el que imprimimos losnúmeros que van de 0.0 a 1.0 a intervalos de 0.1,:

x = 0.0# Mientras x no sea exactamente 1.0, suma 0.1 a la variable *x*while not x == 1.0:

x = x + 0.1print("x = %19.17f" % x)

52 Capítulo 5. Control de flujo

Page 59: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

""" Resultado que obtenemos:x = 0.10000000000000001x = 0.20000000000000001x = 0.30000000000000004x = 0.40000000000000002x = 0.50000000000000000x = 0.59999999999999998x = 0.69999999999999996x = 0.79999999999999993x = 0.89999999999999991x = 0.99999999999999989 <-- El bucle while debió detenerse aquí, pero

→˓no lo hizox = 1.09999999999999987x = 1.19999999999999996x = 1.30000000000000004

.

.

. <-- Presionar Ctrl+C para detener el programa"""

y así sucesivamente; el bucle no se para nunca. El código anterior produce un bucle que no se pa-ra nunca porque la condición x == 1.0 nunca se da exactamente debido a la precisión limitadade los ordenadores (el valor más cercano es 0.99999999999999989 pero no 1.0). La conclusión quepodemos extraer de aquí es que es preferible no comparar nunca variables o números de tipofloat exactamente. Una opción para resolver el problema anterior es usar intervalos de precisión,por ejemplo:

x = 0.0while abs(x - 1.0) > 1e-8:

x = x + 0.1print("x = %19.17f" % x)

""" Resultado que obtenemos:x = 0.10000000000000001x = 0.20000000000000001x = 0.30000000000000004x = 0.40000000000000002x = 0.50000000000000000x = 0.59999999999999998x = 0.69999999999999996x = 0.79999999999999993x = 0.89999999999999991x = 0.99999999999999989"""

de esta forma cuando x se acerque a 0.1 con una precisión igual o inferior a 1 × 10−8 se detendrá

5.2. El bucle while 53

Page 60: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

el bucle.

Advertencia: Recuerden que en Python el sangrado es obligatorio, porque se emplea paraseparar los bloques que indican donde empiezan y terminan los bucles y otros condicionales.Si el sangrado no es correcto, se obtendrá un resultado equivocado o nos devolverá un error desangrado.

Por otro lado, como regla general para usar el bucle for o el while podemos decir que cuandosepamos el número de veces que deseamos calcular el bucle es mejor utilizar el for mientrasque en los demás casos es más recomendable usar el while.

5.3 Sentencias condicionadas if-else

Este conjunto de sentencias realizan una o varias operaciones si una determinada condición queimponemos es cierta. De no cumplirse tal condición, se pueden realizar opcionalmente otras ope-raciones o detener el proceso de cálculo. Un ejemplo de su utilización es el siguiente:

c = 12

if c>0: # comprueba si es positivoprint("La variable c es positiva")

elif c<0: # si no lo es, comprueba si es negativoprint("La variable c es negativa")

else: # Si nada de lo anterior se cumple, haz lo siguienteprint("La variable c vale 0")

En el ejemplo anterior, primero se define una variable c con valor entero 12 y luego se emplea lasentencia if para comprobar si c es positiva, luego se usa elif para que en caso de no cumplirseel if anterior, compruebe si c es negativa. Si no se cumple ninguna de las condiciones anterioresy sólo en ese caso, se ejecutan las sentencias que vienen después de else. Hay que notar que encaso de cumplirse la primera condición if, el bucle se interrumpe y el intérprete ya no continúacomprobando las posibles condiciones elif (pueden haber varias) o else final.

Advertencia: Es muy importante darse cuenta nuevamente los bloques de sangrado o espa-cios que separan los condicionales if-else en el ejemplo anterior. Al ejecutarse el códigoy en contrarse el primer if, el intérprete de Python sabe que todo lo que viene después delos “:” y sangrado con espacios es lo que debe ejecutarse en caso de cumplirse la condicióny esto termina cuando se encuentra con un bloque de sangrado inferior, que en este caso es lasentencia elif.

Veamos lo anterior con un ejemplo usando sólo la sentencia if. Tenemos dos números diferentes ysólo queremos calcular y escribir su diferencia si el primero es mayor que el segundo; el programa

54 Capítulo 5. Control de flujo

Page 61: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

Figura 5.2: Diagrama de flujo de una sentencia if-else.

podría ser:

a, b = 9.3, 12.0

if a > b:c = a - bprint ("La variable a es mayor que b")

print ("El valor de c es %f" % c)

En este ejemplo se comprueba si a es mayor que b y en ese caso se calcula su diferencia e imprimeun mensaje. Luego se imprime el valor de c en otra sentencia, pero como esa línea está ya fueradel bloque de identación del if, el condicional termina justo antes y esa sentencia se intentaráimprimir aunque la condición del if no se cumpla, ya que no está contenido en ella. El códigocorrecto sería simplemente:

a, b = 9.3, 12.0

if a > b:c = a - bprint ("La variable a es mayor que b")print ("El valor de c es %f" % c)

Así, el valor de c sólo imprime si el condicional se cumple.

Hay varias variantes para escribir estas sentencias que se irán viendo y aprendiendo con el tiempo.Por ejemplo, cuando después de un condicional hay una única sentencia, ésta se puede escribiren la misma línea sin necesidad de sangrar:

5.3. Sentencias condicionadas if-else 55

Page 62: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

if a > b: print ("La variable a es mayor que b")else: print ("La variable a es menor o igual que b")

Evidentemente, los elementos de control de flujo pueden contener a su vez otros elementos deflujo; por ejemplo, después de un if puede venir otra vez otro if con otras condiciones. Tambiénes posible reproducir el comportamiento de un while combinando if y for, etc., pero comosiempre, hay que ser muy cuidadoso con los bloques de sangrado.

5.4 Declaraciones break y continue y sentencia else enbucles

La sentencia break se puede usar para interrumpir el bloque más cercano en un bucle whileo for. De manera similar, continue continua con la siguiente iteración dentro del bucle máspróximo. La sentencia else en bucles permite ejecutar una acción cuando el bucle termina unalista (en bucles for) o cuando la condición es falsa (con while) pero no si el bucle se interrumpeusando break. Veamos el ejemplo de un programa que calcula los números primos entre 2 y 10:

for n in range(2, 10):for x in range(2, n):

if n % x == 0:print("%d es igual a %d*%d." % (n, x, n/x))break # corto el bucle for

else:# El bucle termina sin encontrar factorprint("%d es numero primo." % n)

""" Imprime:2 es numero primo.3 es numero primo.4 es igual a 2*2.5 es numero primo.6 es igual a 2*3.7 es numero primo.8 es igual a 2*4.9 es igual a 3*3."""

En este ejemplo usamos break para cortar el bucle for más interno si el if se cumple (es True)y así evitar que muestre multiplicaciones equivalentes (e.g.: 3*4 = 4*3); podemos comprobarlo que ocurre si no pusiésemos break. Es útil para por ejemplo, evitar que un bucle siga corriendosi ya se consiguió la condición.

Algo muy interesante en este ejemplo es que usamos la sentencia else con for, en lugar delusarla con if como es habitual. Un else en for se ejecuta cuando la lista en el for llega al

56 Capítulo 5. Control de flujo

Page 63: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

final, sin cortarse. De esta manera imprimimos un aviso si el bucle termina (el for agota la lista)sin llegar a usar break, lo que indica que ningún número de la lista es múltiplo suyo y por tantoes primo.

La declaración continue indica continuar con el siguiente elemento del bucle más interior, inte-rrumpiendo el ciclo actual. Vámoslo con un ejemplo:

for k in range(8):if k> 4:

print("%d es mayor que 4." % k)continue

print("%d es menor o igual que 4." % k)

0 es menor o igual que 4.1 es menor o igual que 4.2 es menor o igual que 4.3 es menor o igual que 4.4 es menor o igual que 4.5 es mayor que 4.6 es mayor que 4.7 es mayor que 4.

Es este caso, con continue evitamos que se ejecute el último print() si k>4, continuandoel bucle con el siguiente elemento de la lista. Fíjate que pudimos haber hecho un código similarusando una sentencia if-else.

5.5 Atrapando los errores. Sentencia try-except

Hemos visto que cuando existe algún error en el código, Python detiene la ejecución y nos devuelveuna excepción o mensaje de error indicándonos qué fue lo que ocurrió. Por ejemplo, supongamosque por algún motivo hacemos una división por cero:

In [4]: a, b = 23, 0

In [5]: a/b-----------------------------------------------------------------------

→˓----ZeroDivisionError Traceback (most recent call

→˓last)

/home/japp/<ipython console> in <module>()ZeroDivisionError: integer division or modulo by zero

al hacer esto, nos avisa del error indicando el tipo en la última línea, ZeroDivisionError,terminando la ejecución. Que Python nos dé tanta información al ocurrir una excepción es muy

5.5. Atrapando los errores. Sentencia try-except 57

Page 64: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

útil pero muy a menudo sabemos que estos errores pueden ocurrir y lo ideal es estar preparadocapturando la excepción y actuar en consecuencia en lugar de interrumpir el programa. Para haceresto podemos usar la sentencia try-except, que nos permite “probar” (Try) una sentencia ycapturar un eventual error y hacer algo al respecto (except) en lugar de detener el programa. En elcaso anterior podríamos hacer lo siguiente:

a, b = 23, 0try:

a/bexcept:

print("Hay un error en los valores de entrada")

Ahora el código intenta ejecutar a/b y de haber algún tipo de error imprime el mensaje indicadoy sigue adelante en lugar abortar la ejecución del programa. Al hacer esto hemos “capturado” laexcepción o error evitando que el programa se detenga, suponiendo que éste puede continuar apesar del error. Nótese que de esta manera no sabemos qué tipo de error ha ocurrido, que antes seindicaba con la clave ZeroDivisionError, que es uno de los muchos tipos de errores que Pyt-hon reconoce. Si quisiésemos saber exactamente qué tipo de error ocurrió, debemos especificarloen except, por ejemplo:

a, b, c = 23, 0, "A"

try:a/b

except ZeroDivisionError:print("Error, division por cero.")

except TypeError:print("Error en el tipo de dato.")

# Resultado:# Error, division por cero.

try:a/c

except ZeroDivisionError:print("Error, division por cero.")

except TypeError:print("Error en el tipo de dato.")

# Resultado:# Error en el tipo de dato.

De esta manera, sabemos exactamente qué tipo de error se cometió en cada caso, una división porcero o un error en el tipo de dato (que es lo que indica TypeError). Naturalmente, si no ocurrieseninguno de estos errores específicamente, Python daría un error y terminaría el programa de manerahabitual. Pueden consultar la documentación oficial de Python para tener más información sobrela captura de excepciones y los tipos de errores reconocidos.

58 Capítulo 5. Control de flujo

Page 65: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

5.6 Una aplicación interesante: Raíces de ecuaciones al-gebraicas cualquiera

A menudo en ciencia nos encontramos con que los modelos con los que intentamos describir larealidad de un fenómeno natural nos lleva a tener que resolver ecuaciones polinómicas o tras-cendentes (que no tienen solución algebraica) u otras en las que, por su complejidad, la soluciónes complicada. La búsqueda de las raices de tales ecuaciones en un intervalo prefijado podemoshacerlo con el cálculo numérico de forma sencilla utilizando lo que sabemos hasta ahora.

El método más sencillo es el llamado método del bisector que nos permite encontrar una raíz deuna función real cualquiera 𝑓(𝑥), continua en el intervalo [𝑎, 𝑏] donde 𝑓(𝑎) y 𝑓(𝑏) tienen diferentesigno. Recuerden que el Teorema de Bolzano nos dice que esto es posible y lo que hay que haceres implementar un programa en Python para resolverlo en el caso de funciones de una sola variablereal.

El método consiste en dividir el intervalo dado [𝑎, 𝑏] por la mitad y llamemos 𝑚 al punto medio. Siel signo de 𝑓(𝑚) es diferente al de 𝑓(𝑎) aplicamos otra vez el método al intervalo [𝑎,𝑚]; si, por elcontrario, el signo de f(m) es diferente al de f(b) aplicamos otra vez el método al intervalo [𝑚, 𝑏].El nuevo intervalo en cualquier caso es menor que el anterior y contiene la raiz buscada, por lotanto lo único que tenemos que hacer es repetir el método anterior tantas veces como sea necesariohasta que 𝑓(𝑚) = 0 o, como ya sabemos, es mejor utilizar la condición 𝑓(𝑚) < 𝜖, donde 𝜖 esun número tan pequeño como queramos. Este es un método iterativo, es decir, que se repite tantasveces como sea necesario hasta que se cumpla la condición que impongamos a la solución.

5.7 Ejercicios

1. Escribir un programa que calcule el factorial de un número n entero y positivo. Es decir,calculen:

𝑛! =𝑛∏

𝑘=1

𝑘 para 𝑛 ≥ 0

2. Crear una lista con 10 números enteros con valores distintos y arbitrarios de 0 a 100. Progra-mar una función que encuentre el mayor de ellos y que dé su posición en la lista.

3. Utilizando la lista anterior, crear una lista nueva que incluya los números que son primos yotra que incluya sus índices en la lista original.

4. Generar una lista con 100 números enteros aleatorios de -100 a 100, utilizando la fun-ción randint() (escribir from numpy.random import randint y luego nums= randint(-100,100,100). Separar en tres listas distintas los números negativos, lospositivos y los mayores de 50, pero de manera que la suma de los números de cada lista nosea mayor que 200; es decir, vayan rellenando las listas mientras se cumpla la condición.

5.6. Una aplicación interesante: Raíces de ecuaciones algebraicas cualquiera 59

Page 66: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

5. Obtener un valor de 𝜋 calculando la suma siguiente para n=200:

4𝑛∑

𝑘=1

(−1)𝑘+1

2𝑘 − 1

6. Modificar el programa anterior para obtener el valor de 𝜋 con una precisión determinada (porejemplo 10−6) comparado con el valor más aproximado tomado del módulo math.

7. Diseñar un programa que calcule volumen de una esfera, cilindro o un cono. El programadebe preguntar primero qué es lo que se desea calcular y luego pedir los datos necesariossegún lo que se elija.

8. Dada la lista de notas de los alumnos de una clase, decir quien ha obtenido aprobado (entre5 y 6.9), notable (entre 7 y 8.9), sobresaliente (más de 9) o ha suspendido.

Alumnado NotaCarolina 7.1Enar 4.4Patricia 9.6Matias 5.0Ruyman 6.7Maria 8.3Nayra 5.6

Suponiendo que todos los nombres de mujer terminan con “a” (lo que casualmente en esteejemplo es cierto), decir del alumnado quien es varón o mujer.

9. Escribir un programa que calcule la suma de los elementos necesarios de la serie siguiente:

𝑛∑𝑖=0

1

(𝑖 + 1)(𝑖 + 3)=

3

4,

para obtenerla con 5 cifras significativas. Como resultado dar el valor de la suma y el númeron de sumandos sumados.

10. La nota final de la asignatura de Computación Científica (p) se calcula añadiendo a la notadel examen final (z) una ponderación de la evaluación contínua (c) a lo largo del curso de laforma:

𝑝 = 0.6𝑐 + 𝑧(10 − 0.6𝑐)

10

El alumno estará aprobado cuando la nota final p sea mayor o igual a cinco, siempre quez supere un tercio de la nota máxima (z>10/3); en caso contrario, se queda con p=z. Ungrupo de alumnos ha obtenido las siguientes calificaciones en la evaluación contínua y en elexamen final:

c 8.2 0.0 9.0 5.0 8.4 7.2 5.0 9.2 4.9 7.9z 7.1 5.1 8.8 3.1 4.6 2.0 4.1 7.4 4.4 8.8

60 Capítulo 5. Control de flujo

Page 67: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

Hacer un programa que calcule sus notas finales indicando además quién ha aprobado yquién ha suspendido. Calcular también la nota media de la evaluación continua, del examenfinal y de la nota final. En todos los resultados debe mostrarse una única cifra decimal.

11. Dada la serie geométrica cuya suma exacta es:

∞∑𝑛=0

𝑎𝑥𝑛 =𝑎

1 − 𝑥

válida siempre que 0 < x < 1 y siendo a un número real cualquiera, escribir un programaque calcule esta suma con diez cifras significativas solamente para cualquier valor de x y a,comprobando que se cumple la condición necesaria para x. Dar como resultado el valor dela suma y el número de sumandos sumados para obtenerla.

12. Se llama sucesión de Fibonacci a la colección de n números para la que el primer elementoes cero, el segundo 1 y el resto es la suma de los dos anteriores. Por ejemplo, la sucesiónpara n=5 es (0, 1, 1, 2, 3). Crear un programa que calcule la lista de números para cualquiern.

13. Escribir un programa que proporcione el desglose en el número mínimo de billetes y mone-das de una cantidad entera cualquiera de euros dada. Recuerden que los billetes y monedasde uso legal disponibles hasta 1 euro son de: 500, 200, 100, 50, 20, 10, 5, 2 y 1 euros. Paraello deben solicitar al usuario un número entero, debiendo comprobar que así se lo ofrece ydesglosar tal cantidad en el número mínimo de billetes y monedas que el programa escribiráfinalmente en pantalla.

14. Escribir un programa que pida el valor de dos números enteros n y m cualesquiera y calculeel sumatorio de todos los números pares comprendidos entre ellos (incluyéndolos en el casode que sean pares). Comprobar que efectivamente los números proporcionados son enteros.

15. Crear un programa que resuelva la ecuación de segundo grado 𝑎𝑥2+𝑏𝑥+𝑐 = 0 para cualquiervalor de a, b y c comprobando el valor del discriminante ∆ = 𝑏2 − 4𝑎𝑐.

16. Una de las formas de medir distancias en el cosmos es utilizar el llamado módulo de dis-tancias, en el que la diferencia entre las magnitudes aparente 𝑚𝑣 (proporcional al logaritmodel flujo recibido) y absoluta 𝑀𝑣 (proporcional al logaritmo del flujo recibido si el astro seencontrara a 10 parsec de distancia) de un astro es 𝑚𝑣 −𝑀𝑣 = 5 log

(𝑑10

)+ 𝑎𝑑, donde, 𝑑 es

la distancia en parsec y 𝑎 es el coeficiente de absorción interestelar. Lo aplicamos a un casoconcreto. En la Gran Nube de Magallanes, en 1987 se descubrió una supernova la SN1987Aque en su máximo de luminosidad alcanzó una magnitud de 𝑚𝑣 = 3. Sabiendo que este tipode supernovas tienen una magnitud absoluta de 𝑀𝑣 = -19.3 y que el coeficiente de absorcióninterestelar es de 𝑎 = 0.8 × 10−4, ¿a qué distancia se encuentra la galaxia?.

5.7. Ejercicios 61

Page 68: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

62 Capítulo 5. Control de flujo

Page 69: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

CAPÍTULO 6

Probabilidad y números aleatorios

Juguemos con el azar. Si lanzamos una moneda, el resultado puede ser cara o cruz; decimos quela probabilidad de que salga cara es de 1/2 al igual que lo es de que salga cruz. La Probabilidades una forma de asignar a cada resultado del experimento un valor entre cero y uno, teniendo encuenta que el suceso formado por todos los posibles resultados (en nuestro caso cara o cruz) tieneuna probabilidad de 1. Decimos que el resultado del lanzamiento de una moneda es una variablealeatoria (discreta), puesto que a pesar de que sabemos que el resultado es cara o cruz, no sabemoscuál va a ser el resultado del próximo lanzamiento. La teoría de la Probabilidad es una rama de lamatemática que trata del análisis de fenómenos aleatorios, sucesos no deterministas, resultados deexperimentos u observaciones de fenómenos naturales sujetos a “ruido” que parecen evolucionarcon el tiempo en forma aleatoria.

Desde un punto de vista matemático una “probabilidad” es una función ℘ real que actúa sobre loselementos de un conjunto 𝐶 de tal forma que ℘(𝐶) = 1 y que para cualquier subconjunto 𝑆 ⊂ 𝐶se tiene que 0 ≤ ℘(𝑆) ≤ 1. Además para cualquier familia 𝑆𝑖 de subconjuntos de 𝐶, disjuntos dosa dos, se verifica que: ℘(𝑆1 ∪ 𝑆2 ∪ ... ∪ 𝑆𝑛) = ℘(𝑆1) + ℘(𝑆2) + ... + ℘(𝑆𝑛). Estas propiedades,desde un punto de vista físico, son propiedades deseables para una función que debe describirla probabilidad de obtener un resultado u otro, producto de un experimento u observación. Estafunción ℘ descrita hasta aquí se suele llamar también distribución de probabilidad por muchosautores.

Sigamos jugando con el azar. Si lanzamos un dado de 6 caras, el resultado puede ser cualquiera deellas; decimos que la probabilidad de que salga cualquier cara es de 1/6. Por lo tanto, el resultadodel lanzamiento de un dado es un suceso aleatorio cuya probabilidad de que salga cualquier caraes la misma. Si realizamos el experimento un número muy grande de veces (𝑛) y vemos cuantasveces ha salido cada una de las caras obtendremos como distribución subyacente (el número deveces que ha salido cada una de las caras) del experimento una muy parecida a la llamada dis-tribución uniforme, en la que todas las caras (de la 1 a la 6) han salido igual número de veces(𝑛/6). Tal distribución la definimos como un número finito de resultados conocidos con la mismaprobabilidad de que suceda uno cualquiera de ellos. Por otro lado, decimos que el resultado dellanzamiento de un dado es también una variable aleatoria.

Con Python podemos jugar a estos juegos, o más bien podemos simular la realización de este juegoutilizando un módulo que nos proporciona los llamados números aleatorios. Es decir, números

63

Page 70: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

o secuencias de números que tienen la misma probabilidad de que sucedan como resultado decualquier experimento o, dicho de otro modo, secuencias de resultados de un experimento o devalores de una variable aleatoria.

Aclaremos que una secuencia de números se dice que es aleatoria cuando no se puede recono-cer cuadros de regularidad en ella; como por ejemplo, los resultados del lanzamiento de un dadoideal o también los dígitos del número pi. La aleatoriedad estadística no implica necesariamentealeatoriedad “verdadera”, es decir “impredicibilidad objetiva”. La llamada pseudo-aleatoriedad essuficiente para muchos usos y consiste en secuencias de números aleatorios que pasan suficientestests o pruebas de nula regularidad.

Para ello usamos el módulo random que implementa funciones generadoras de números aleatoriospara varios tipos de distribuciones de probabilidad. En nuestro caso, para una introducción al tema,nos quedaremos con las más básicas de las que hemos expuesto algunos ejemplos antes.

Casi todas las funciones del módulo se basan en la función básica random(), que se fundamentaen un algoritmo generador de números aleatorios (del tipo Mersenne-Twister) en coma flotanteen el intervalo [0.0, 1.0). La secuencia presenta regularidad despues de (2**19937-1) numerosgenerados lo que le concede una pseudo-aleatoriedad muy cercana a la aleatoriedad objetiva; entodo caso suficiente para nuestros usos.Para usar el módulo hay que importarlo primero:

>>> import random # importamos el módulo>>> help(random) # obtenemos ayuda informativa sobre él

En concreto, para obtener un número aleatorio entero, entre 1 y 20 por ejemplo, utilizamos:

>>> random.randint(1,20) # obtenemos un entero aleatorio en el→˓intervalo [1,20]

6

Si repetimos el comando obtendremos otro número. No obstante poco podemos hacer con un sólonúmero aleatorio. En general, nos interesará simular secuencias más o menos largas de númerosaleatorios. Podemos utilizar bucles (for o while) para obtener secuencias de ellos pero podemosutilizar otras funciones más interesantes. Por ejemplo, para obtener una muestra de 10 númerosaleatorios, de una población de 20 (de 0 a 19 obtenida con el conocido range), podemos hacerlode la forma siguiente:

>>> random.sample(range(20),10)[1, 2, 13, 11, 12, 14, 4, 7, 16, 3]

Alternativamente podemos simular una lista de números aleatorios sin más que crear una lista yescogerlos de ella o mezclarlos de forma aleatoria; veamos cómo:

>>> x=range(15) # obtenemos una lista ordenada con numeros del 0 al 14[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]

>>> random.choice(x) # escogemos aleatoriamente uno de ellos9

64 Capítulo 6. Probabilidad y números aleatorios

Page 71: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

>>> random.shuffle(x) # mezclamos aleatoriamente los elementos de la→˓lista

>>> x[5, 7, 9, 12, 11, 6, 10, 2, 13, 14, 3, 8, 4, 1]

Obviamente si ustedes prueban estos comandos les saldrán resultados diferentes cada vez que lohagan ya que de esto se trata: obtener muestras de números aleatorios en los que todos ellos tienenla misma probabilidad. Podemos comprobar que se trata de números aleatorios con una distribu-ción uniforme sin más que hacer un histograma de la secuencia de números aleatorios creada. Unhistograma nos da la frecuencia con que hemos obtenido cada resultado de un experimento dadoy aunque aprenderemos a dibujarlo más adelante podemos entender el resultado con un ejemplopráctico. Volvamos al juego de tirar un dado ideal; los siguientes comandos de python nos ayudarána ello:

>>> import random as r # importamos el módulo random como r>>> n=60 # definimos el número de tiradas del dado>>> dado= range(6) # creamos lista donde contamos el resultado de las

→˓tiradas>>> for i in range(6): dado[i]=0 # ponemos la lista/contador a cero>>> for i in range(n): # tiramos el dado n veces

res=r.randint(0,5) # obtenemos el resultado de una tiradadado[res]= dado[res]+1 # la acumulamos y guardamos en el lugar

→˓apropiado>>> print (dado) # escribimos el resultado de las n tiradas

Si 𝑛 es pequeño (𝑛 = 60) es muy posible que el número de veces que sale cada cara sea diferentede 10 (distribución uniforme); podemos calcular cual es la desviación respecto a este valor paracada cara calculando su respectivo error relativo:

>>> for i in range(6):print((dado[i]-n/6.)*100./(n/6.))

No obstante, si repetimos la operación un gran número de veces (digamos 𝑛 = 6000, por ejemplo)el resultado para cada cara se irá aproximando a 𝑛/6. Pueden comprobarlo repitiendo la serie decomandos anterior para un número creciente de veces (𝑛) la desviación decrece al aumentar elnúmero de tiradas.

6.1 Algunas distribuciones de probabilidad: la Distibu-ción Binomial

Los datos obtenidos por la observación y experimentación en muchos campos tales como la cien-cia, la ingeniería, la sociología, las finanzas y varios juegos de azar presentan muy diferentes dis-tribuciones subyacentes. No obstante, la mayoría de ellas son muy similares o se aproximan biena alguna de las tres, especialmente importantes, tipos de distribuciones de probabilidad que son:

6.1. Algunas distribuciones de probabilidad: la Distibución Binomial 65

Page 72: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

la Binomial, la de Poisson y la Gaussiana. Todas ellas pueden derivarse y expresarse matemática-mente usando la teoría de la probabilidad; aquí introduciremos la primera de ellas puesto que nopodemos abarcar más en este curso.

Retomemos el juego del lanzamiento de una moneda. Si repetimos el lanzamiento un gran númerode veces (digamos 𝑛) el resultado será de 𝑛/2 caras y cruces, aproximadamente. No obstante, si𝑛 es pequeño (𝑛 = 10) es muy posible que el número de caras sea diferente de 5; la cuestión quepodemos plantearnos entonces es : si lanzamos una moneda 𝑛 veces, >cuál es la probabilidad deque obtengamos un resultado en el que nos salgan 𝑚 caras? (obviamente 0 ≤ 𝑚 ≤ 𝑛). Puededemostrarse que si lanzamos la moneda 𝑛 veces la probabilidad de obtener 𝑚 = 0, 1, 2, ..., 𝑛 vecescara (o cruz) viene dada por los términos sucesivos del binomio (1/2 + 1/2)𝑛.

Vamos a repasar algunos conceptos de combinatoria que nos ayudarán a justificar esta afirmación.

6.1.1 Combinatoria: Variaciones, Permutaciones y Combinaciones

Variaciones. Si tenemos un conjunto de 𝑛 elementos, nos podemos preguntar cuántos grupos de𝑚 elementos se pueden formar de modo que en cada uno de ellos no se repita ningún elemento oestén en orden diferente. La respuesta nos viene dada por las Variaciones de n elementos tomadosde m en m, y se calcula de la forma siguiente:

𝑉 (𝑛,𝑚) =𝑛!

(𝑛−𝑚)!

Podemos entender este resultado si pensamos que la primera posición de nuestro grupo puede estarocupada por uno cualquiera de los 𝑛 elementos, la segunda sólo por (𝑛− 1) puesto que ya hemosutilizado uno, la tercera por (𝑛 − 2) ya que hemos utilizado 2 y así hasta la m-ésima en la quepodemos poner uno de los (𝑛 − (𝑚 − 1)) que quedan. Recordemos que 𝑛! es el llamado factorialde 𝑛 y consiste en multiplicar todos los números naturales desde 1 hasta n.

Nota: Ejemplo. En una carrera de campo a través en la que participan 143 atletas, ¿de cuántasmaneras se puede configurar el podio al final de la carrera?. Está claro que aquí podemos aplicarlas variaciones de 143 atletas tomados de 3 en 3, puesto que son 3 los que caben en el podioy además el orden en el que están importa mucho. Por lo tanto la respuesta sería: 𝑉 (143, 3) =143!/140! = 143 × 142 × 141 = 2863146.

Variaciones con Repetición. Nótese que si está permitido repetir los elementos del conjunto apartir del cual generamos los grupos de 𝑚 elementos y también importa el orden en que estén,entonces estamos en un caso en que el uso de un elemento en un grupo no lo elimina para estaren otro y por tanto hablamos de Variaciones con repetición de n elementos tomados m en m, y localcularemos así:

𝑉 𝑅(𝑛,𝑚) = 𝑛𝑚

66 Capítulo 6. Probabilidad y números aleatorios

Page 73: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

Nota: Ejemplo. ¿Cuántas columnas diferentes debemos rellenar en una quiniela de fútbol paraasegurarnos un pleno de 14 aciertos?. Como pueden repetirse los resultados en diferentes partidosse trata de un caso claro de variaciones con repetición de 3 elementos (1,X,2) tomados de 14 en14, por lo que la solución será: 𝑉 𝑅(𝑛,𝑚) = 𝑛𝑚 = 314 = 4782969.

Permutaciones. El problema ahora es ligeramente diferente y lo que nos preguntamos es de cuán-tas formas podemos ordenar los 𝑛 elementos diferentes de un conjunto dado (ahora m = n). Lasolución se llama Permutaciones de n elementos, que no es más que las variaciones de 𝑛 elementostomadas de 𝑛 en 𝑛 y por lo tanto lo calculamos como (recuerden que 0!=1):

𝑃 (𝑛) = 𝑉 (𝑛, 𝑛) = 𝑛!

Nota: Ejemplo. ¿De cuántas maneras se pueden sentar 6 amigos en sus seis asientos de una salade conciertos? Este es un caso claro de permutaciones de 6 elementos. Su solución es: 𝑃 (6) =6! = 720.

Combinaciones. Supongamos que ahora estamos interesados en un problema similar al de lasvariaciones pero en el que dos grupos son diferentes sólo si difieren en alguno de sus elementos.De esta forma, se dice que las Combinaciones de n elementos tomados de m en m son todos lossubconjuntos de 𝑚 elementos que podemos formar del conjunto de 𝑛 elementos sin que importe elorden en que elijamos a los elementos.

Un ejemplo típico son los casos en los que repetimos un experimento un numero de veces cual-quiera y deseamos saber en cuantas de ellas hemos obtenido un resultado concreto. Se calculautilizando la fórmula:

𝐶(𝑛,𝑚) =𝑛!

𝑚!(𝑛−𝑚)!

esta fórmula puede interpretarse como el número de permutaciones de los 𝑛 elementos (𝑛!) divi-dido por el número de permutaciones de los 𝑚 elementos seleccionados (𝑚!) multiplicadas por elnúmero de permutaciones de los restantes 𝑛−𝑚, ((𝑛−𝑚)!).

Nota: Ejemplo. ¿De cuántas formas podemos lanzar una moneda 12 veces y obtener cua-tro cruces?. Imaginen que tenemos 12 monedas de las cuales cuatro son cruces. Además tene-mos 12 posiciones donde colocar nuestras monedas. De cuántas formas podemos colocarlas, sa-biendo que no distinguimos unas monedas de otras más que por el hecho de ser o no ser ca-ras?. Tenemos 12! formas de colocarlas, pero podemos intercambiar las caras entre ellas de 4!formas y las cruces de 8! maneras. Así que como nos dice la fórmula de las combinaciones,𝐶(12, 4) = 12!

4!8!= 12·11·10·9

4·3·2·1 = 495.

6.1. Algunas distribuciones de probabilidad: la Distibución Binomial 67

Page 74: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

Continuando con la distribución binomial...

De forma más general Bernouilli, a finales del siglo XVII, demostró que si la probabilidad de queobtengamos un resultado en un experimento cualquiera es 𝑝 y la de que no lo obtengamos es 𝑞 (detal forma que 𝑝+ 𝑞 = 1), las probabilidades de que suceda en 0, 1, 2, ..., 𝑛 veces de las 𝑛 veces quelo intentemos, viene dado por los términos sucesivos del binomio (𝑞 + 𝑝)𝑛, es decir:

𝑞𝑛 + 𝑛𝑞𝑛−1𝑝 +𝑛(𝑛− 1)

2!𝑞𝑛−2𝑝2 +

𝑛(𝑛− 1)(𝑛− 2)

3!𝑞𝑛−2𝑝2 + ... + 𝑝𝑛 =

𝑚=𝑛∑𝑚=0

𝑛!

𝑚!(𝑛−𝑚)!𝑞𝑚𝑝𝑛−𝑚

Veámoslo con un ejemplo práctico. En un experimento lanzamos 12 veces una moneda, las pro-babilidades de obtener 0, 1, 2, 3, 4,... 12 veces cara nos viene dada por los términos sucesivos deldesarrollo de binomio (1

2+ 1

2)12, es decir:

℘(𝑚,𝑛) =𝑛!

𝑚!(𝑛−𝑚)!𝑝𝑚𝑞𝑛−𝑚 𝑚 = 0, ..., 𝑛

para n=12 tenemos los diferentes términos:

℘𝐵(0, 12), ℘𝐵(1, 12), ℘𝐵(2, 12), ..., ℘𝐵(12, 12) =1

212, 12

1

212,12 · 11

2 · 1

1

212, ...,

1

212

es decir,

=1

212(1, 12, 66, 220, 495, 792, 924, 792, 495, 220, 66, 12, 1)

En la práctica para obtener una distribución como ésta es necesario que se intente en un númeromuy elevado de veces.

6.2 Ejercicios

1. Verifiquen que los datos de la tabla adjunta, en la que 𝑓 denota la frecuencia con la que un su-ceso ocurre 𝑛 veces, forma una distribución binomial y encuentren su media y su desviaciónestándar.

n 0 1 2 3 4 5f 1 10 40 80 80 32

2. Una fábrica que produce chips de memoria para portátiles, al final de su cadena de produc-ción se examina su calidad tomando una muestra de 5 unidades cada hora. Comprobadasmuchas muestras se encuentra que el número de ellas que contienen 0, 1, 2, 3 , 4, 5 me-morias defectuosas son 58, 32, 7, 2, 1, 0 respectivamente. Mostrar que esta distribución esaproximadamente binomial y deducir el porcentaje de memorias que salen defectuosas.

68 Capítulo 6. Probabilidad y números aleatorios

Page 75: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

CAPÍTULO 7

Cálculo numérico con Numpy

Ya hemos visto el potencial de cálculo que tiene un lenguaje de programación como Python cuan-do se usan las operaciones y sentencias de programación disponibles con funciones matemáticasestándar como las que ofrece el módulo math. Si tenemos muchos números con los que calcular,podemos usar listas y operar entre ellas con bucles. Sin embargo, esto puede ser un trabajo labo-rioso porque las listas de Python están pensadas para uso general y no precisamente para cálculonumérico y por eso tienen muchas limitaciones que pronto veremos.

Afortunadamente existen módulos adicionales de Python (es decir, que no vienen con la instalaciónde estándar de Python) para el cálculo numérico, que facilitan enormemente el cálculo, ofreciendonuevos elementos y funciones. En concreto, el módulo numpy nos ofrece un nuevo tipo de datollamado array (traducción del inglés: colección, formación), similar a las listas pero con propie-dades especiales muy útiles. En este capítulo veremos cómo se trabaja con arrays y las nuevasfuncionalidades que nos ofece numpy.

7.1 Listas y arrays

Los arrays son un tipo nuevo de dato, similar a las listas, pero orientados especialmente al cálculonumérico. En cierto modo se pueden considerar como vectores o matrices (parecidos a como selos conoce en álgebra) y son un tipo de dato fundamental para el cálculo científico de cierto nivelutilizando tipos de datos estructurados (conjuntos de datos).

El inconveniente principal de las listas, que es el tipo básico de dato estructurado en Python, es queno está pensado para el cálculo matemático o numérico; veámolo con un ejemplo:

In [1]: lista = range(5) # Lista de numeros de 0 a 4

In [2]: print(lista*2)[0, 1, 2, 3, 4, 0, 1, 2, 3, 4]

In [3]: print(lista*2.5)-----------------------------------------------------------------------

→˓----

69

Page 76: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

TypeError Traceback (most recent call→˓last)

/home/japp/<ipython console> in <module>()

TypeError: can't multiply sequence by non-int of type 'float'

En el ejemplo anterior vemos cómo al multiplicar una lista por un número entero, el resultado esconcatenar la lista original tantas veces como indica el número, en lugar de multiplicar cada unode sus elementos por este número. Peor aún, al multiplicarlo por un número no entero da un error,al no poder crear una fracción de una lista. Si quisiéramos hacer esto, se podría resolver iterandocada uno de los elementos de la lista con un bucle for, por ejemplo:

In [4]: lista_nueva = [i*2.5 for i in lista]In [5]: print(lista_nueva)[0.0, 2.5, 5.0, 7.5, 10.0]

aunque esta técnica es ineficiente y lenta, sobre todo cuando queremos evaluar funciones, polino-mios o cualquier otra operación matemática que aparece en cualquier problema científico.

Cuando realmente queremos hacer cálculos con listas de números, debemos usar los arrays. Elmódulo numpy nos da acceso a los arrays y a una enorme cantidad de métodos y funcionesaplicables a los mismos. Naturalmente, numpy incluye funciones matemáticas básicas similaresal módulo math, las completa con otras más elaboradas y además incluye algunas utilidades denúmeros aleatorios, ajuste lineal de funciones y otras muchas que iremos viendo más adelante yque pueden comprobar usando la ayuda como ya sabemos.

7.2 Creando arrays

Primero debemos importar el módulo numpy en sí o bien todas sus funciones:

In [6]: import numpy # Cargar el modulo numpy, o bienIn [7]: import numpy as np # cargar el modulo numpy, llamándolo

→˓np, o bienIn [8]: from numpy import * # cargar todas funciones de numpy

Si cargamos el módulo solamente, accederemos a las funciones como numpy.array() onp.array(), según cómo importemos el módulo; si en lugar de eso importamos todas las fun-ciones, accederemos a ellas directamente (e.g. array()). Por comodidad usaremos por ahora estaúltima opción, aunque muy a menudo veremos que usa la notación np.array(), especialmentecuando trabajamos con varios módulos distintos.

Un array se puede crear explícitamente o a partir de una lista de la forma siguiente:

70 Capítulo 7. Cálculo numérico con Numpy

Page 77: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

In [9]: x = array([2.0, 4.6, 9.3, 1.2]) # Creacion de un array→˓directamente

In [10]: notas = [ 9.8, 7.8, 9.9, 8.4, 6.7] # Crear un listaIn [11]: notas = array(notas) # y convertir la lista a

→˓array

Existen métodos para crear arrays automáticamente:

In [12]: numeros = arange(10.) # Array de numeros(floats) de 0 a→˓9

In [13]: print(numeros)[ 0. 1. 2. 3. 4. 5. 6. 7. 8. 9.]

In [14]: lista_ceros = zeros(10) # Array de 10 ceros→˓(floats)

In [15]: print(lista_ceros)[ 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]

In [16]: lista_unos = ones(10) # Array de 10 unos→˓(floats)

In [17]: print(lista_unos)[ 1. 1. 1. 1. 1. 1. 1. 1. 1. 1.]

In [18]: otra_lista = linspace(0,30,8) # Array de 8 números, de→˓0 a 30 ambos incluidos

In [19]: print(otra_lista)[ 0. 4.28571429 8.57142857 12.85714286 17.14285714

21.42857143 25.71428571 30. ]

7.3 Indexado de arrays

Los arrays se indexan prácticamente igual que las listas y las cadenas de texto; veamos algunosejemplos:

In [18]: print(numeros[3:8]) # Elementos desde el tercero al→˓septimo

[ 3. 4. 5. 6. 7.]

In [19]: print(numeros[:4]) # Elementos desde el primero al→˓cuarto

[ 0. 1. 2. 3.]

In [20]: print(numeros[5:]) # Elementos desde el quinto al→˓final

7.3. Indexado de arrays 71

Page 78: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

[ 5. 6. 7. 8. 9.]

In [21]: print(numeros[-3]) # El antepenúltimo elemento→˓(devuelve un elemento, no un array)

7.

In [24]: print(numeros[:]) # Todo el array, equivalente a→˓print(numeros)

[ 0. 1. 2. 3. 4. 5. 6. 7. 8. 9.]

In [25]: print(numeros[2:8:2]) # Elementos del segundo al→˓septimo, pero saltando de dos en dos

[ 2. 4. 6.]

7.4 Algunas propiedades de los arrays

Al igual que las listas, podemos ver el tamaño de un array unidimensional con len(), aunque lamanera correcta de conocer la forma de un array es usando el método shape():

In [28]: print(len(numeros))10In [29]: print(numeros.shape)(10,)

Nótese que el resultado del método shape() es una tupla, en este caso con un solo elemento yaque el array numeros es unidimensional.

Si creamos un array con arange() usando un número entero, el array que se creará será deenteros. Es posible cambiar todo el array a otro tipo de dato (como a float) usando el métodoastype():

In [31]: enteros = arange(6)

In [32]: print(enteros)[0 1 2 3 4 5]

In [33]: type(enteros)Out[33]: <type 'numpy.ndarray'>

In [34]: type(enteros[0])Out[34]: <type 'numpy.int32'>

In [35]: decimales = enteros.astype('float')

In [36]: type(decimales)

72 Capítulo 7. Cálculo numérico con Numpy

Page 79: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

Out[36]: <type 'numpy.ndarray'>

In [37]: type(decimales[0])Out[37]: <type 'numpy.float64'> # En algunos ordenadores puede dar

→˓float32

In [38]: print(decimales)[ 0. 1. 2. 3. 4. 5.]

In [38]: print(decimales.shape) # Forma o tamaño del array(6,)

7.5 Operaciones con arrays

Los arrays permiten hacer operaciones aritméticas básicas entre ellos en la forma que uno esperaríaque se hicieran, es decir, haciéndolo elemento a elemento; para ello siempre ambos arrays debentener la misma longitud; por ejemplo:

In [39]: x = array([5.6, 7.3, 7.7, 2.3, 4.2, 9.2])

In [40]: print(x+decimales)[ 5.6 8.3 9.7 5.3 8.2 14.2]

In [41]: print(x*decimales)[ 0. 7.3 15.4 6.9 16.8 46. ]

In [42]: print(x/decimales)[ Inf 7.3 3.85 0.76666667 1.05 1.84]

Como podemos apreciar las operaciones se hacen elemento a elemento, por lo que ambas debentener la misma forma (shape()). Fíjense que en la división el resultado del primer elemento esindefinido/infinito (Inf) debido a la división por cero.

Varios arrays se pueden unir con el método concatenate(), que también se puede usar paraañadir elementos nuevos:

In [44]: z = concatenate((x, decimales))

In [45]: print(z)[ 5.6 7.3 7.7 2.3 4.2 9.2 0. 1. 2. 3. 4. 5. ]

In [46]: z = concatenate((x,[7]))

In [47]: print(z)[ 5.6 7.3 7.7 2.3 4.2 9.2 7. ]

7.5. Operaciones con arrays 73

Page 80: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

Es muy importante fijarse que los arrays o listas a unir deben darse como una tupla y de ahí loselementos entre paréntesis como (x,[7]) o (x,[2,4,7]) o (x,array([2,4,7])).

Para añadir elementos, numpy tiene las funciones insert() y append(), que funcionan demanera similar a sus equivalentes en listas, pero en este caso son funciones y no métodos que seaplican a un array, si no que el array en cuestión hay que darlo como parámetro:

# Añadimos el elemento 100 al array z, al finalIn [55]: z = append(z, 100)In [56]: print(z)[ 5.6 7.3 7.7 2.3 4.2 9.2 7. 100. ]

# Añadimos el elemento 200 al array z, en el tercer puesto (índice 2)In [57]: z = insert(z, 2, 200)In [58]: print(z)[ 5.6 7.3 200. 7.7 2.3 4.2 9.2 7. 100. ]

Como se ve, a diferencia de las listas, el primer parámetro es el array y luego el elemento que sequiere añadir, en el caso de append() y el array, la posición y luego elemento a añadir en el casode append(). Si en lugar de un elemento a insertar se da una lista y otro array, añade todos loselementos de la lista (a append() habría que dar también una lista de posiciones, como segundoparámetro). También hay que notar que estas dos funciones no cambian el array original y por esoen este ejemplo redefinimos z con el array ampliado.

Además de las operaciones aritméticas básicas, los arrays de numpy tienen métodos o funcionesespecíficas para ellas más avanzadas. Algunas de ellas son las siguientes:

In [5]: z.max() # Valor máximo de los elementos del arrayOut[5]: 9.1999999999999993

In [6]: z.min() # Valor mínimo de los elementos del arrayOut[6]: 2.2999999999999998

In [7]: z.mean() # Valor medio de los elementos del arrayOut[7]: 6.1857142857142851

In [8]: z.std() # Desviación típica de los elementos del arrayOut[8]: 2.1603098795103919

In [9]: z.sum() # Suma de todos los elementos del arrayOut[9]: 43.299999999999997

In [16]: median(z) # Mediana de los elementos del arrayOut[16]: 7.0

Los métodos, que se operan de la forma z.sum() también pueden usarse como funciones de tipo

74 Capítulo 7. Cálculo numérico con Numpy

Page 81: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

sum(z), etc. Consulten el manual de numpy para conocer otras propiedades y métodos de losarrays o simplemente acudan y consulten la “ayuda” de las funciones que quieran utilizar.

Una gran utilidad de los arrays es la posibilidad de usarlos con datos booleanos (True o False) yoperar entre ellos o incluso mezclados con arrays con números. Veamos algunos ejemplos:

In [19]: A = array([True, False, True])In [20]: B = array([False, False, True])

In [22]: A*BOut[22]: array([False, False, True], dtype=bool)

In [29]: C = array([1, 2, 3])

In [30]: A*COut[30]: array([1, 0, 3])

In [31]: B*COut[31]: array([0, 0, 3])

En este ejemplo vemos cómo al multiplicar dos arrays booleanos es resultado es otro array boo-leano con el resultado que corresponda, pero al multiplicar los arrays booleanos con arrays nu-méricos, el resultado es un array numérico con los mismos elementos, pero con los elementos quefueron multiplicados por False iguales a cero.

Tambíén es posible usar los arrays como índices de otro array y como índices se pueden usararrays numéricos o booleanos. El resultado será en este caso un array con los elementos que seindique en el array de índices numérico o los elementos correspondientes a True en caso de usarun array de índices booleano. Veámoslo con un ejemplo:

# Array con enteros de 0 a 9In [37]: mi_array = arange(0,100,10)

# Array de índices numericos con numeros de 0-9 de 2 en 2In [38]: indices1 = arange(0,10,2)

# Array de índices booleanosIn [39]: indices2 = array([False, True, True, False, False, True,

→˓False, False, True, True])

In [40]: print(mi_array)[ 0 10 20 30 40 50 60 70 80 90]

In [43]: print(mi_array[indices1])[ 0 20 40 60 80]

In [44]: print(mi_array[indices2])[10 20 50 80 90]

7.5. Operaciones con arrays 75

Page 82: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

También es muy sencillo crear arrays booleanos usando operadores lógicos y luego usalos comoíndices, por ejemplo:

# Creamos un array usando un operador booleanoIn [50]: mayores50 = mi_array > 50

In [51]: print(mayores50)[False False False False False False True True True True]

# Lo utilizamos como índices para seleccionar los que cumplen esa→˓condición

In [52]: print(mi_array[mayores50])[60 70 80 90]

7.6 Arrays multidimensionales

Hasta ahora sólo hemos trabajado con arrays con una sola dimensión, pero numpy permite tra-bajar con arrays de más dimensiones. Un array de dos dimensiones podría ser por ejemplo unarray que tuviera como elementos un sistema de ecuaciones o una imagen. Para crearlos podemoshacerlo declarándolos directamente o mediante funciones como zero() o ones() dando comoparámetro una tupla con la forma del array final que queramos; o también usando arange() ycrear un array unidimensional y luego cambiar su forma. Veamos algunos ejemplos:

# Array de 3 filas y tres columnas, creado implícitamenteIn [56]: arr0 = array([[10,20,30],[9, 99, 999],[0, 2, 3]])In [57]: print(arr0)[[ 10 20 30][ 9 99 999][ 0 2 3]]

# Array de ceros con 2 filas y 3 columnasIn [57]: arr1 = zeros((2,3))In [59]: print(arr1)[[ 0. 0. 0.][ 0. 0. 0.]]

# Array de unos con 4 filas y una columnaIn [62]: arr2 = ones((4,1))In [63]: print(arr2)[[ 1.][ 1.][ 1.][ 1.]]

# Array unidimensional de 9 elementos y cambio su forma a 3x3

76 Capítulo 7. Cálculo numérico con Numpy

Page 83: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

In [64]: arr3 = arange(9).reshape((3,3))In [65]: print(arr3)[[0 1 2][3 4 5][6 7 8]]

In [69]: arr2.shapeOut[69]: (4, 1)

Como vemos en la última línea, la forma o shape() de los arrays se sigue dando como una tupla,con la dimensión de cada eje separado por comas; en ese caso la primera dimensión son las cuatrofilas y la segunda dimensión o eje es una columna. Es por eso que al usar las funciones zero(),ones(), reshape(), etc. hay que asegurarse que el parámetro de entrada es una tupla con lalongitud de cada eje. Cuando usamos la función len() en un array bidimensional, el resultado esla longitud del primer eje o dimensión, es decir, len(arr2) es 4.

El acceso a los elementos es el habitual, pero ahora hay que tener en cuenta el eje al que nosreferimos; además podemos utilizar ”:” como comodín para referirnos a todo el eje. Por ejemplo:

# Primer elemento de la primera fila y primera columna (0,0)In [86]: arr0[0,0]Out[86]: 10# Primera columnaIn [87]: arr0[:,0]Out[87]: array([10, 9, 0])# Primera filaIn [88]: arr0[0,:]Out[88]: array([10, 20, 30])# Elementos 0 y 1 de la primera filaIn [89]: arr0[0,:2]Out[89]: array([10, 20])

Igualmente podemos manipular un array bidimensional usando sus índices:

# Asigno el primer elemento a 88In [91]: arr0[0,0] = 88# Asigno elementos 0 y 1 de la segunda filaIn [92]: arr0[1,:2] = [50,60]# Multiplico por 10 la última filaIn [93]: arr0[-1,:] = arr0[-1,:]*10

In [94]: print(arr0)array([[ 88, 20, 30],

[ 50, 60, 999],[ 0, 20, 30]])

7.6. Arrays multidimensionales 77

Page 84: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

7.7 Ejercicios

1. Crea un array de 100 números aleatorios con valores de -100 a +100 como hicimos en elejercicio 5 del Capítulo 5. Usando arrays de booleanos crea otros arrays que contengan lospositivos, los negativos y los mayores de 50 de ese array.

2. Resuelve el ejercicio 11 del capítulo 5 sobre el cálculo de la nota de la asignatura usandoarrays de numpy e ignorando la condición de z>10/3. ¿Podrías hacerlo también de maneraque sí lo tenga en cuenta? Para ello podrías usar arrays de booleanos.

3. Crea un array bidimensional 5x5 con todos los valores cero. Usando el indexado de arrays,asigna 1 a todos los elementos de la última fila y 5 a todos los elementos de la primeracolumna. Finalmente, asigna el valor 100 a todos los elementos del subarray central 3x3 dela matriz de 5x5.

4. Para el ejercicio 4 del Apéndice C sobre los diámetros de las esporas del lycopodium, calcu-lar, usando funciones de numpy, el diámetro medio de las esporas y la desviación estándarde la muestra. Separar, en arrays independientes, las medidas de los diámetros:

Que tengan valores inferiores a la media menos la desviación estándar, es decir 𝑑 <𝑑− 𝜎𝑑

Que tengan valores superiores a la media más la desviación estándar, es decir 𝑑 > 𝑑+𝜎𝑑

Que tengan valores entre 𝑑− 𝜎𝑑 < 𝑑 < 𝑑 + 𝜎𝑑

78 Capítulo 7. Cálculo numérico con Numpy

Page 85: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

CAPÍTULO 8

Análisis estadístico de datos experimentales

8.1 Estadística y parámetros estadísticos

La Estadística es la rama de las Matemáticas que trata del estudio de fenómenos de los que no setiene toda la información completa y se diferencia del resto porque usa el concepto de Probabili-dad, que es una medida de la posibilidad de que algo ocurra o de que algo sea correcto como yahemos visto.

En el estudio de la naturaleza, en su observación y medida, nos encontramos con estas situacionescontinuamente. Por ejemplo, ¿cómo describiríamos el comportamiento del Sol?; si nos fijamosque en el Sol hay alrededor de 𝑁 ≈ 𝑀⊙/𝑚𝐻 ≈ 1057 partículas, nos damos cuenta de que nopodemos describir el estado de movimiento de cada una de ellas en cada instante de tiempo; seránconceptos y procedimientos de la Física Estadística los que nos ayudarán a describirlo. Por otrolado, cualquier observación y/o medida de cualquier magnitud en un experimento de laboratorionunca coincide exactamente con otra realizada un instante antes o después debido al “ruido” entreotros factores; el conjunto de medidas obtenidas forman un ejemplo de aplicación del análisisestadístico de datos.

Para el análisis de un conjunto de datos desde el punto de vista estadístico, hay que poder compri-mir o representar la información contenida en ellos en una serie de parámetros o indicadores quenos den una idea de como se comporta el conjunto. Estos números se llaman parámetros esta-dísticos y entre los más conocidos están: un parámetro de posición, la media, y otro de “amonto-namiento”, la dispersión. Por supuesto, estos parámetros estadísticos serán tanto mejores cuantomejor representen a todo el conjunto de datos. Hay dos condiciones básicas para que representenbien al conjunto: la ausencia de “sesgos” por un lado y la “robustez” por otro; al final del capítulonos referiremos a ellos.

8.2 La distribución de datos subyacente

Cada vez que realizamos un experimento o una observación de un fenómeno natural, estamos dealgún modo “preguntando” cual es el valor exacto o verdadero de una cierta cantidad. Esta actitud

79

Page 86: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

presupone la idea que tenemos de que tal valor existe y que además puede ser medido; no estrivial darse cuenta de que tal cosa no es cierta. No obstante, vamos a suponer que la cantidad quedeseamos medir tiene un valor y que además podemos obtenerlo, aunque sea de modo aproximado,a través de nuestras medidas. Cuán buena será nuestra aproximación y cuánto trabajo nos costaráobtenerlo y mejorarlo es, de hecho, el objetivo principal de la estadística aplicada a la Física.

Supongamos que hemos realizado un conjunto de 𝑁 medidas de una determinada cantidad 𝑥 yque las representamos por 𝑥𝑖 (𝑖 = 1, 2, ..., 𝑁). Esperamos que las diferentes medidas realizadas𝑥𝑖, se irán acumulando alrededor de un valor que esperamos que coincida con el valor real de lacantidad medida. Tal distribución de valores que podemos representar mediante un histograma 1

que según añadamos más medidas será cada vez más suave de forma que, en el límite (un númeroinfinito de medidas), reproducirá una distribución de probabilidad, que llamaremos distribuciónsubyacente. Nuestro objetivo será aprender lo máximo posible acerca de ella a partir de nuestrolimitado conjunto de datos.

8.2.1 Medidas de posición: media, mediana y moda

El primer parámetro que nos gustaría tener es un valor (aunque sea aproximado) al valor verda-dero de la cantidad medida, lo que llamamos el valor medio. Comenzaremos por definir la mediaaritmética (o simplemente media) como:

𝑥 =

∑𝑖 𝑥𝑖

𝑁

Esta definición coincide con la que habitualmente se usa en el lenguaje común para mencionarel valor medio o promedio de una serie de cantidades. En numpy de Python podemos utilizarmean() para calcularla.

De modo similar, se define la media geométrica utilizando la multiplicación en vez de la suma, esdecir:

𝑥 = (Π𝑖𝑥𝑖)(1/𝑁) ,

esta definición resulta útil cuando la incertidumbre en nuestro problema actúa de forma multipli-cativa en vez de aditiva. Se usa, por ejemplo, cuando queremos promediar porcentajes o casos enque la variable muestra valores acumulativos. De hecho, son muy pocas las veces en las que estamedida resulta útil en la práctica. Para calcularla en python hay que usar la función gmean() delmódulo stats de scipy.

Otra medida de posición interesante es la llamada mediana. Se define como el valor de la variableen la distribución tal que la mitad de los valores presentes en el conjunto son mayores que ellay la otra mitad restante son menores. La mediana 𝑥𝑚𝑒𝑑, cumple que 𝑛(𝑥 < 𝑥𝑚𝑒𝑑) = 𝑁/2 =𝑛(𝑥 > 𝑥𝑚𝑒𝑑). Su utilidad principal, como podemos comprobar, es que es un indicador más fiableque la media en el caso de tener algunos valores en la distribución muy alejados de la media o

1 El histograma es una representación gráfica del conjunto de medidas. Se dibuja el número de medidas (eje OY)que caen en un cierto intervalo de variación dado frente a estos intervalos (eje OX).

80 Capítulo 8. Análisis estadístico de datos experimentales

Page 87: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

que realmente son erróneos o que no pertenecen a la distribución que nos gustaría encontrar. Ennumpy de Python podemos utilizar median() para calcularla.

Finalmente, otra medida de posición es la moda de la distribución que es el valor que más veces seobserva en la misma; su utilidad en ciencia es realmente escasa.

8.2.2 Medidas de dispersión: desviación estándar y varianza

La segunda cuestión que nos interesa conocer es cómo se distribuyen las medidas del conjuntoalrededor de la media, por dos buenas razones:

1. por cuestiones de predicción; por ejemplo, en el caso de que queramos montar otro experi-mento sabremos el rango de variación de las medidas, o

2. porque nos da una idea de la incertidumbre o del error más probable de nuestras medidas.

Aunque se pueden definir varios indicadores de distancia, o medidas de dispersión, entre cada unode los elementos del conjunto de medidas y el valor medio, utilizaremos el más apropiado tantomatemáticamente como desde el punto de vista físico. Se define la varianza, el cuadrado de ladesviación estándar, como:

𝜎2 =

∑𝑖(𝑥𝑖 − 𝑥)2

𝑁

donde tomamos como valor real de la cantidad medida su valor medio. Por cierto, pueden demos-trar, sin demasiado problema, que también puede calcularse como 𝜎2 = 𝑥2 − 𝑥2; de hecho, esta esla definición más utilizada para su cálculo. En numpy de Python podemos utilizar las funcionesvar() y std() para calcularlas.

El hecho de utilizar como valor real el valor medio de la distribución subyacente, hace que alutilizar la 𝜎 como medida de dispersión haga que ésta sea mínima. Se puede demostrar (aunqueesta vez no es fácil quedando más allá de este curso hacerlo) que el denominador en la ecuaciónanterior debe cambiar de 𝑁 a (𝑁 − 1). Nótese que a medida que 𝑁 aumenta, el error relativo alutilizar una u otra definición decrece.

8.2.3 Población, muestra y error estándar de la media

En las medidas de fenómenos naturales es muy común encontrarse con que tales medidas siguenuna distribución subyacente muy parecida a la conocida como distribución gaussiana, de tal suer-te que suele llamársela también distribución normal (ver Apéndice C). Aunque fue obtenida pri-mero por Demoivre en 1733 cuando estudiaba un problema de lanzamiento de monedas, fue mástarde obtenida independientemente por Laplace y por Gauss; de ahí lo de distribución gaussiana,y fue ampliamente aplicada inicialmente a los errores accidentales (o aleatorios) en medidas astro-nómicas y de otros experimentos científicos. La forma de una distribución gaussiana, es decir suhistograma, es la famosa “Campana de Gauss”.

8.2. La distribución de datos subyacente 81

Page 88: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

Por otro lado, es bastante usual ver a un conjunto de observaciones o resultados de cualquier ex-perimento como una muestra finita del conjunto infinito, o mucho más grande que podríamosobtener si repirtiéramos el experimento indefinidamente, que se conoce como población. Comoesto no es posible, lo más que obtenemos son diferentes conjuntos de medidas de un mismo expe-rimento que serán muestras finitas. Cada una de ellas las podremos representar por su media y sudesviación estándar que, en general no coincidirán.

No obstante, puede demostrarse matemáticamente que la distribución de medias y la de desviacio-nes estándar también es una distribución gaussiana. Su media es igual a la media verdadera de todala población mientras que su desviación estándar es 𝜎/

√𝑛 donde 𝑛 es el número de datos de cada

muestra y 𝜎 la desviación estándar de toda la población.

Por lo tanto, cuando trabajamos con un conjunto de datos cuya distribución subyacente es unadistribución normal de media 𝑥 y desviación estándar 𝜎, es apropiado escribir el resultado final delexperimento u observación como: 𝑥 ± 𝜖, donde 𝜖 = 𝜎/

√𝑛, que es el llamado error estándar de

la media.

8.2.4 Introducción de pesos. Media ponderada

Cuando se realizan medidas repetidas de una misma cantidad es común encontrar que algunas deellas, por una razón u otra, son más fiables que otras. Por ejemplo, en Astronomía es corrienteutilizar observaciones realizadas por diferentes observadores, en diferentes instantes de tiempo,en diferentes observatorios y a menudo con diferentes instrumentos; si queremos utilizarlas todases interesante disponer de un método que permita promediarlas, dándoles a cada una de ellasuna influencia proporcional a la medida de su fiabilidad. Ello se consigue introduciendo pesosasociados a cada medida; es decir, que tenemos un conjunto de medidas 𝑥𝑖 cada una de ellas conun peso estadístico asociado, con lo que tendremos finalmente un conjunto de pesos 𝑤𝑖. En estecaso, para calcular la media, que se suele llamar media ponderada, hacemos:

𝑥 =

∑𝑖 𝑤𝑖𝑥𝑖∑𝑖 𝑤𝑖

(8.1)

Con numpy podemos utilizar average() para calcularla y análogamente, siguiendo el apartadoanterior, podemos calcular su varianza usando:

𝜎2 =

∑𝑖𝑤𝑖(𝑥𝑖 − 𝑥)2∑

𝑖 𝑤𝑖

(8.2)

En el caso de medidas experimentales, una elección habitual para los pesos es utilizar valores in-versamente proporcionales al cuadrado de los errores de cada medida, cuando éstas son conocidaso pueden ser estimadas, es decir, 𝑤𝑖 = 1/𝜖2𝑖 . La varianza asociada a este promedio la calculamossustituyendo apropiadamente en la relación anterior.

𝜎2 =

∑𝑖(𝑥𝑖 − 𝑥)2/𝜖2𝑖∑

𝑖 1/𝜖2𝑖(8.3)

82 Capítulo 8. Análisis estadístico de datos experimentales

Page 89: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

8.3 Sesgo y robustez

En palabras llanas nos gustaría que el conjunto de nuestras medidas tuvieran las cualidades si-guientes: que den el resultado que “queremos” y que no tuviera valores erróneos.

La primera cualidad exigiría que nuestro conjunto de medidas nos dé un valor medio que se aproxi-me de forma asintótica al valor de la media de la distribución subyacente al hacer muchas medidas.Un parámetro que cumple esta condición se dice que no tiene sesgos, es decir, que no contiene erro-res sistemáticos. Ejemplos de ellos serían: límites en la calibración de instrumentos, condicionesambientales en el que se desarrollan los experimentos, errores humanos entre otros.

En cuanto a la segunda cualidad, se exigiría que el parámetro de posición utilizado (media, porejemplo) no varíe sensiblemente si quitamos una o unas pocas medidas cualesquiera del conjunto.Si esto sucede, se dice que la media o el parámetro que sea es robusta. Pueden comprobar porejemplo, a partir de las definiciones, que la mediana es un parámetro de posición más robusto quela media.

En general, obtener medidas robustas y sin sesgos es lo que estamos buscando siempre y es impo-sible de obtener. No obstante, siempre podemos mejorar las observaciones, los instrumentos y losexperimentos de tal forma que minimicemos los sesgos posibles y dotemos de mayor robustez a lamedida final. La mejora en estos aspectos es el objetivo de cualquier científico y es lo que permiteavanzar a la ciencia.

8.4 Ejercicios

1. Comprobar que para un conjunto de datos de media 𝑥 y varianza 𝜎2, ésta última también apodemos calcular como 𝜎2 = 𝑥2 − 𝑥2.

2. El valor medio de un conjunto de 100 observaciones es 2.96 y la desviación estándar es 0.12. Hacemos otras 50 observaciones cuya media es de 2.93 y su desviación estándar es 0.16.Encuentren la media y la varianza del conjunto de las 150 observaciones.

3. Comprobar de qué forma podemos calcular también la media y la varianza de una distribu-ción de datos con sus correspondientes pesos (𝑤𝑖 = 1/𝜎2

𝑖 ) en los casos en que: (a) Todos loserrores son iguales, y (b) una sola de las medidas tiene una precisión mucho mejor que lasdemás.

4. Escribir un programa que calcule las medias aritmética, aritmética ponderada y geométricapara la lista de números 34.4, 30.1, 29.8, 33.5, 30.9, 31.1; ponderada con los pesos 0.9, 0.79,0.84, 0.6, 0.88, 0.78.

5. Crear un programa que calcule la varianza y la desviación estándar de los elementos (núme-ros) de la misma lista del problema anterior.

6. En observaciones de dispersión de electrones, en el detector se mide la intensidad relativadel haz a diferentes radios de curvatura obteniendo los datos de la tabla adjunta. Encontrar

8.3. Sesgo y robustez 83

Page 90: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

el radio de curvatura medio y su desviación estándar.

Radio Curvatura (cm) 5.4 5.5 5.6 5.7 5.8 5.9 6.0Intensidad Relativa 0 11 36.5 40.5 31 9.5 0

84 Capítulo 8. Análisis estadístico de datos experimentales

Page 91: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

CAPÍTULO 9

Lectura y escritura de ficheros

Muy a menudo tenemos datos iniciales para un cálculo o medidas de un experimento en un fichero(de texto). Para poder manipular estos datos y calcular con ellos debemos aprender a leerlos comonúmeros o arrays. Igualmente, el resultado de un cálculo o un análisis es necesario volcarlo a unfichero de texto en lugar de mostrarlo por pantalla para conservar el resultado. Esto es especial-mente necesario cuando los resultados son arrays largos o cuando tenemos que procesar un grannúmero de ficheros. Vamos a ver cómo leer y escribir ficheros de texto, es decir letras y números ysignos de puntuación, con Python.

9.1 Creando un fichero sencillo

El primer paso para manipular un fichero, ya sea para crearlo, leerlo o escribir en él es crear lo queen Python se llama una instancia a ese fichero; una instancia es una llamada o referencia, en estecaso a un fichero, a la que se le asigna un nombre. Esto consiste simplemente en “abrir” el ficheroen modo de lectura, escritura, para añadir o una combinación de estos, según lo que necesitemos:

In [48]: fichero_leer = open('mi_fichero.txt', 'r')In [48]: fichero_escribir = open('mi_fichero.txt', 'w')In [48]: fichero_escribir = open('mi_fichero.txt', 'a')In [48]: fichero_leer = open('mi_fichero.txt', 'rw')

En los ejemplos anteriores se ha abierto un fichero de varias maneras posibles, donde hemos indi-cado en el primer parámetro el nombre del fichero y el segundo el modo de apertura:

'r' -> Abre el fichero mi_fichero.txt para leer (debe existir→˓previamente)

'w' -> Abre el fichero mi_fichero.txt para escribir. Si noexiste lo crea y si existe sobrescribirá el contenido que

→˓tenga.'a' -> Abre el fichero mi_fichero.txt para añadir texto. Si no

85

Page 92: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

existe lo crea y si existe continua escribiendo al final del→˓fichero.

'rw' -> Abre el fichero mi_fichero.txt para leer y escribir

Vamos a crear un fichero y escribir algo en él. Lo primero es abrir el fichero en modo escritura:

In [49]: fs = open('prueba.txt', 'w')In [50]: type(fs)Out[50]: <type 'file'>

aquí la variable fs es una instancia o llamada al fichero. A partir de ahora cualquier operaciónque se haga en el fichero se hace utilizando esta instancia fs y no el nombre del fichero en sí.Escribamos ahora algo de contenido, para esto se emplea el método write() a la instancia delfichero:

In [51]: fs.write('Hola, estoy escribiendo un texto a un fichero')In [52]: fs.write('Y esta es otra linea')In [53]: fs.write( str(exp(10)) )In [54]: fs.close() # Cerramos el fichero

Al teminar de trabajar con el fichero debemos cerrarlo con el método close(), es aquí cuandorealmente se escribe el fichero y no hay que olvidar cerrarlo siempre al terminar de trabajar con él.Una vez cerrado, se puede abrir con un editor de textos cualquiera como Kate o gEdit. Veremosque cada orden de escritura se ha hecho consecutivamente y no línea a línea. Si queremos añadirlíneas nuevas debemos ponerlas explícitamente con \n que es el código ASCII para el “intro” o el“return”, es decir para generar una nueva línea:

In [55]: fs = open('prueba.txt', 'a')In [56]: fs.write("\n\n") # Dejo dos lineas en blancoIn [57]: fs.write("Esta es una linea nueva\n")In [58]: fs.write("Y esta es otra linea\n")In [59]: fs.close()

De igual manera podemos usar un bucle for para escribir una lista de datos:

In [60]: from math import *In [61]: fsalida = open('datos.txt', 'w')In [62]: for i in range(100):

....: fsalida.write('%d %10.4f\n' % (i, exp(i)))In [63]: fsalida.close()

De esta forma creamos un fichero de nombre datos.txt en el que hay escrito, a dos columnas, loscien primeros números enteros positivos y su exponencial (con 10 caracteres en total y cuatrodecimales). Podemos ver el contenido de este fichero con cualquier editor de texto o desde unaconsola de linux usando cat como ya sabemos.

86 Capítulo 9. Lectura y escritura de ficheros

Page 93: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

9.2 Lectura de ficheros

Ahora podemos leer este fichero de datos u otro similar que ya exista. Una vez abierto el ficheropara lectura, podemos crear una lista vacía para cada columna de datos y luego con un bucleleerlo línea por línea separando cada una en columnas con el método split(). Veámoslo conun ejemplo: queremos leer el fichero datos.txt que acabamos de crear antes. Contiene 100 filascon dos columnas, la primera un número y la segunda su exponencial. Lo podríamos hacer de estaforma:

In [68]: # Abrimos el fichero "datos.txt" para lecturaIn [69]: fdatos = open('datos.txt', 'r')In [70]: x_datos = [] # Creamos una lista para la

→˓primera columnaIn [71]: y_datos = [] # Creamos una lista para la

→˓segunda columnaIn [72]: lineas = fdatos.readlines() # Leemos el fichero línea a líneaIn [73]: for linea in lineas:

....: x, y = linea.split() # Se separa cada línea en dos→˓columnas....: x_datos.append(float(x)) # Añado el elemento x a la lista

→˓x_datos....: y_datos.append(float(y)) # Añado el elemento y a la lista

→˓y_datos....:....:

In [75]: fdatos.close()

En este ejemplos usamos el método readlines() al fichero para que lea línea a linea y devuel-ve una lista donde cada elemento es una cadena de texto con una línea, por lo que si hacemoslen(lineas) para ver la longitud de la lista nos da el número de líneas del fichero. En realidadeste paso nos lo podemos ahorrar ya que python es capaz de iterar línea a línea una instancia defichero, es decir, podemos poner:

for fdatos in lineas:

en lugar de:

for linea in lineas:

pero así es más fácil entender lo que realmente está haciendo.

Es importante recordar que los datos (números, letras, caracteres, etc...) se escriben y leen comovariables string. Por lo tanto, si queremos operar con ellos debemos transformarlos en los tipos devariables apropiadas (int, float, list, array, ...).

9.2. Lectura de ficheros 87

Page 94: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

In [77]: type(x_datos)Out[77]: <type 'list'>

In [78]: len(x_datos)Out[78]: 100

In [79]: x_datos, y_datos = array(x_datos), array(y_datos)

In [80]: type(x_datos)Out[80]: <type 'numpy.ndarray'>

In [81]: x_datos.shapeOut[81]: (100,)

Ahora que tenemos todos los datos en arrays los podemos manipular como tales. Recuerda quesplit() separa, por defecto, datos en el texto separados por espacios; si queremos separar porcomas u otro carácter debemos incluirlo como parámetro: split(',').

9.3 Lectura y escritura de ficheros de datos con numpy

Una manera alternativa y muchísimo más sencilla de escribir y leer arrays es usando los métodossavetxt() y loadtxt() de numpy, que escriben (guardan) y leen ficheros de texto pero conun formato prefijado por defecto.:

# Guardamos en el fichero "datos2.txt" (creándolo) dos columnas# que contienen los arrays x_datos e y_datossavetxt("datos2.txt", (x_datos, y_datos))

# Leemos el fichero que acabamos de crear y# almacenamos los arrays en x e yx, y = loadtxt("datos2.txt")

Hay que notar que si guardamos varios arrays en un fichero de esta manera, savetxt() guardacada uno en una fila, de manera que x_datos ocupa la primera fila del fichero y y_datosla segunda, en lugar de en columnas y al leerlo con loadtxt(), la variable x contiene todala primera fila e y la segunda. No obstante, en el caso de que sólo queramos guardar un arrayunidimensional, se escribe en una única columna.

Por otro lado, si leemos el fichero y cargamos los datos en un único array veamos la forma quetiene:

d = loadtxt("datos2.txt")d.shape()(2, 100)

88 Capítulo 9. Lectura y escritura de ficheros

Page 95: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

es decir, un array bidimensional de 2 x 100, que corresponde primero a las dos filas y luego 100columnas. Esto quiere decir que si tenemos un fichero de texto con varias columnas (como eshabitual), como datos.txt que contiene:

# tiempo x1 x21.0 1.2 1.42.0 2.1 2.33.0 3.3 3.04.0 4.2 4.25.0 5.1 5.1

podemos leerlo de esta manera:

d = loadtxt("datos.txt") # d es un array de 6 x 3t = d[0,:] # columna 1 (tiempo)x1 = d[1,:] # columna 2 (x1)x2 = d[2,:] # columna 1 (x2)

pero si queremos pasarlo directamente a arrays individuales debemos usar el parámetrounpack=True, que lo que hace es intercambiar filas por columnas (traspuesta del array):

t, x1, x2 = loadtxt("datos.txt", unpack=True)

Lo anterior sólo es necesario si el fichero tiene varias columnas, si sólo tiene una no hace falta usarunpack=True.

Supongamos ahora que estamos interesados en leer los datos de un fichero a partir de la línea 50 yno desde el principio y que además las columnas están separadas por comas en lugar de espacios;podemos indicarlo con parámetros adicionales:

x, y = loadtxt("datos.txt", skiprows=49, delimiter=",")

Consulten la ayuda de la función loadtxt() de numpy para conocer otras opciones de lectura,como seleccionar columnas determinadas, definir otro símbolo de comentario, entre otras opciones.

9.4 Ejercicios

1. En el fichero datos_2col.txt hay dos columnas de datos. Calcular la raíz cuadrada de losvalores de la primera columna y el cubo de la segunda y escribirlos a un nuevo fichero dedos columnas, pero solo para las entradas cuyos valores de la segunda columna de datosoriginal sean mayor o igual a 0.5.

2. El fichero datos_4col.txt contiene cuatro columnas de datos. Escribir un fichero de datos concuatro columnas que incluya el número de entrada (empezando por 1), el promedio entrelas dos primeras columnas, el promedio entre las dos últimas y la diferencia entre ambasmedias.

9.4. Ejercicios 89

Page 96: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

3. Usando la función randint() de numpy.random, generen una lista de 30 números en-teros aleatorios (hasta 100). Calculen la media aritmética y la desviación estándar de gruposde elementos de 5 en 5 poniendo los resultados en dos arrays diferentes; es decir, obtener unarray con las medias y otro con las desviaciones estándar, que serán de longitud 30/5. Crearun fichero con tres columnas que contenga el número de línea, la media y la desviaciónestándar.

4. Calcule en un array los valores que toma la función seno-cociente: 𝑠𝑒𝑛(𝜃)/𝜃 para valoresde 𝜃 entre -45 y 45 grados a intervalos de 0.1 grados. Escriba el resultado en un fichero queincluya en una columna el ángulo 𝜃 en grados y en otra el valor del seno-cociente correspon-diente.

5. A lo largo de la historia desde que O. Roemer en 1676 midiera por vez primera la veloci-dad de la luz, se han publicado bastantes medidas de la velocidad de la luz por diferentesmétodos. Una colección de ellas hechas en el siglo XX (recopiladas por R.T. Birge, (1941),Rep. Prog. Phys., 8, 95 con sus errores, y alguna más, están en el fichero velocidad_luz.txt.Se pide escribir un programa en el que se lea el fichero en cuestión donde, como pueden leeren la cabecera del fichero, las tres columnas son: el año de la medida, el resultado obtenidoy su error en Km/s y calculen el valor medio ponderado por la inversa del cuadrado de loserrores y su dispersión.

6. En un experimento de laboratorio se tiene un circuito eléctrico al que vamos variando elvoltaje de la fuente de alimentación desde 0.05 V hasta 15.00 V, a intervalos de 0.01 V y semide la intensidad de corriente que circula por él con un amperímetro. Se repite el experi-mento cinco veces, de forma que para cada voltaje V aplicado se obtienen cinco medidas deI (en amperios) que se almacenan en una tabla que contiene el fichero datos_intensidad.txt.Dibujar un histograma y calcular el valor medio y la desviación estándar de las cinco seriesde medidas de la intensidad para cada voltaje aplicado al circuito.

90 Capítulo 9. Lectura y escritura de ficheros

Page 97: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

CAPÍTULO 10

Representación gráfica de funciones y datos

La representación de funciones y/o datos científicos mediante gráficos resulta ser fundamentalpara expresar una gran variedad de resultados. Cualquier informe, artículo o resultado a menudose expresa de manera mucho más clara mediante gráficos. Python posee varios paquetes gráficos;nosotros usaremos matplotlib, una potente librería gráfica de alta calidad también para gráficosbidimensionales y sencilla de manejar. Matplotlib posee el módulo pylab, que es la interfaz parahacer gráficos bidimensionales. Veamos un ejemplo sencillo:

>>> from pylab import * # importar todas las funciones de pylab>>> x = arange(10.) # array de floats, de 0.0 a 9.0>>> plot(x) # generar el gráfico de la función y=x>>> [<matplotlib.lines.Line2D object at 0x9d0f58c>]>>> show() # mostrar el gráfico en pantalla

Hemos creado un gráfico que representa diez puntos en un array y luego lo hemos mostrado conshow(); esto es así porque normalmente solemos hacer varios cambios en la gráfica, mostrán-dolos todos juntos. Sin embargo, cuando trabajamos interactivamente, por ejemplo con la consolaipython podemos activar el modo interactivo para que cada cambio que se haga en la gráfica

91

Page 98: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

se muestre en el momento, mediante la función ion(), de esta manera no hace falta poner show()para mostrar la gráfica cada vez que se haga plot():

In [1]: ion() # Activo el modo interactivoIn [2]: plot(x) # Hago un plot que se muestra sin hacer

→˓show()Out[2]: [<matplotlib.lines.Line2D object at 0x9ffde8c>]

Recuerden que este modo interactivo sólo está disponible en la consola avanzada ipython perono lo está en la consola estándar de Python. Otra posibilidad es iniciar ipython en modo pylab,haciendo ipython -pylab, de esta manera se carga automáticamente pylab, se activa el mo-do interactivo, y además se importa el módulo numpy y todas sus funciones.

Fíjense cómo el comando plot() que hemos usado hasta ahora devuelve una lista de instanciasde cada dibujo. Una instancia es una referencia a un elemento que creamos, en este caso la línea engráfica. En este caso es una lista con un sólo elemento, una instancia Line2D. Podemos guardaresta instancia para referirnos a este dibujo (a la línea en concreto) más adelante haciendo:

In [3]: mi_dibujo, = plot(x)

Ahora la variable mi_dibujo es una instancia o “referencia” a la línea del dibujo, que podremosmanipular posteriormente con métodos que se aplican a esa instancia dibujo. Nótese que despuésde mi_dibujo hay una coma; esto es para indicar que mi_dibujo debe tomar el valor delprimer (y en este caso el único) elemento de la lista y no la lista en sí, que es lo que habría ocurridode haber hecho mi_dibujo = plot(x) (erróneamente). Esto es habitual al trabajar con listas,veámoslo con un ejemplo:

a = [3, 5]# Así ``a`` es una lista, que contiene dos valores

a, b = [3, 5]# Así *desempaquetamos* los elementos de la lista y a=3 y b=5# Esto funciona porque pusimos tantas variables como elementos en la

→˓lista

Pero si la lista sólo tiene un elemento ¿cómo desempaquetamos ese elemento?. Veamos:

a = [3] # Así, ``a`` es una lista y no el número 3

a, = [3] # Si añadimos una coma indicamos que queremos meter ese único# elemento en una variable, en lugar de usar la lista

Y esto es justo lo que hicimos con mi_dibujo,= plot(x), para hacer que mi_dibujo con-tenga una instancia y no una lista de instancias, que es lo que devuelve plot().

La sintaxis básica de plot() es simplemente plot(x,y), pero si no se incluye la lista x, éstase reemplaza por el número de elementos o índice de la lista y, por lo que es equivalente a hacerplot(range(len(y)),y). En la gráfica del ejemplo anterior no se ven diez puntos, sino una

92 Capítulo 10. Representación gráfica de funciones y datos

Page 99: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

línea contínua uniendo esos puntos, que es como se dibuja por defecto. Si queremos pintar lospuntos debemos hacerlo con un parámetro adicional, por ejemplo:

In [4]: plot(x,'o') # pinta 10 puntos como oOut[4]: [<matplotlib.lines.Line2D object at 0x8dd3cec>]

In [5]: plot(x,'o-') # igual que antes pero ahora los une con una→˓linea continua

Out[5]: [<matplotlib.lines.Line2D object at 0x8dd9e0c>]

En este caso el ‘o’ se usa para dibujar puntos gruesos y si se añade ‘-‘ también dibuja la líneacontínua. En realidad, lo que ha sucedido es que se dibujaron dos gráficos uno encima del otro;si queremos que se cree un nuevo gráfico cada vez que hacemos plot(), debemos añadir elparámetro hold=False a plot():

mi_dibujo, = plot(x*2,'o', hold=False)

El tercer parámetro de la función plot() (o segundo, si no se incluye la variable x) se usa paraindicar el símbolo y el color del marcador. Admite distintas letras que representan de manera únicael color, el símbolo o la línea que une los puntos; por ejemplo, si hacemos plot(x,'bx-')pintará los puntos con marcas “x”, de color azul (“b”) y los unirá además con líneas contínuas delmismo color. A continuación se indican otras opciones posibles:

Colores

93

Page 100: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

Símbolo Color‘b’ Azul‘g’ Verde‘r’ Rojo‘c’ Cian‘m’ Magenta‘y’ Amarillo‘k’ Negro‘w’ Blanco

Marcas y líneas

Símbolo Descripción‘-‘ Línea continua‘–‘ Línea a trazos‘-.’ Línea a puntos y rayas‘:’ Línea punteada‘.’ Símbolo punto‘,’ Símbolo pixel‘o’ Símbolo círculo relleno‘v’ Símbolo triángulo hacia abajo‘^’ Símbolo triángulo hacia arriba‘<’ Símbolo triángulo hacia la izquierda‘>’ Símbolo triángulo hacia la derecha‘s’ Símbolo cuadrado‘p’ Símbolo pentágono‘*’ Símbolo estrella‘+’ Símbolo cruz‘x’ Símbolo X‘D’ Símbolo diamante‘d’ Símbolo diamante delgado

Para borrar toda la figura se puede usar la función clf(), mientras que cla() sólo borra lo quehay dibujado dentro de los ejes y no los ejes en si.

Se pueden representar varias parejas de datos con sus respectivos símbolos en una misma figura,aunque para ello siempre es obligatorio incluir el valor del eje x:

In [8]: clf() # Limpiamos toda la figura

In [9]: x2=x**2 # definimos el array x2

In [10]: x3=x**3 # definimos el array x3

In [11]: # dibujamos tres curvas en el mismo gráfico y figuraIn [12]: plot(x, x,'b.', x, x2,'rd', x, x3,'g^')Out[13]:

94 Capítulo 10. Representación gráfica de funciones y datos

Page 101: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

[<matplotlib.lines.Line2D object at 0x8e959cc>,<matplotlib.lines.Line2D object at 0x8eb75cc>,<matplotlib.lines.Line2D object at 0x8eb788c>]

Esta lista de salida de plot() contiene 3 instancias que se refieren a 3 elementos diferentes de lagráfica.

Es posible cambiar el intervalo mostrado en los ejes con xlim() e ylim() :

In [12]: xlim(-1,11) #nuevos límites para el eje OXOut[12]: (-1, 11)

In [13]: ylim(-50,850) #nuevos límites para el eje OYOut[13]: (-50, 850)

Además del marcador y el color indicado de la manera anterior, se pueden cambiar muchas otraspropiedades de la gráfica como parámetros de plot() independientes como los de la tabla adjun-ta:

95

Page 102: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

Parámetro Significado y valoresalpha grado de transparencia, float (0.0=transparente a 1.0=opaco)color o c Color de matplotliblabel Etiqueta con cadena de texto, stringmarkeredge-color omec

Color del borde del símbolo

markeredge-width omew

Ancho del borde del símbolo, float (en número de puntos)

markerface-color omfc

Color del símbolo

markersize oms

Tamaño del símbolo, float (en número de puntos)

linestyle o ls Tipo de línea, ‘-‘ ‘–‘ ‘-.’ ‘:’ ‘None’linewidth olw

Ancho de la línea, float (en número de puntos)

marker Tipo de símbolo,’+’ ‘*’ ‘,’ ‘.’ ‘1’ ‘2’ ‘3’ ‘4’ ‘<’ ‘>’ ‘D’ ‘H’ ‘^’ ‘_’ ‘d’ ‘h’ ‘o’‘p’ ‘s’ ‘v’ ‘x’ ‘|’ TICKUP TICKDOWN TICKLEFT TICKRIGHT

Un ejemplo usando más opciones sería este:

In [15]: plot(x, lw=5, c='y', marker='o', ms=10, mfc='red')Out[15]: [<matplotlib.lines.Line2D object at 0x8f0d14c>]

También es posible cambiar las propiedades de la gráfica una vez creada, para ello debemos captu-rar las instancias de cada dibujo en una variable y cambiar sus parámetros. En este caso a menudohay que usar draw() para actualizar el gráfico,

96 Capítulo 10. Representación gráfica de funciones y datos

Page 103: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

>>> # Hago tres dibujos, capturando sus instancias>>> # en las variables p1, p2 y p3>>> p1, p2, p3 = plot(x, x,'b.',x, x2, 'rd', x, x3, 'g^')

>>> show() # Muestro en dibujo por pantalla>>> p1.set_marker('o') # Cambio el símbolo de la gráfica 1>>> p3.set_color('y') # Cambio el color de la gráfica 3>>> draw() # Hacer los cambios

usando instancias similares poder cambiar prácticamente todas las propiedades de nuestro gráficosin tener que rehacerlo. Por tanto es buena costumbre guardar las instancias en variables cuandotrabajemos interactivamente.

10.1 Trabajando con texto dentro del gráfico

Exiten funciones para añadir texto (etiquetas) a los ejes de la gráfica y a la gráfica en sí; éstos sonlos más importantes:

In [9]: x = arange(0, 5, 0.05)

In [10]: p, = plot(x,log10(x)*sin(x**2))

In [12]: xlabel('Eje X') # Etiqueta del eje OXOut[12]: <matplotlib.text.Text object at 0x99112cc>

In [13]: ylabel('Eje Y') # Etiqueta del eje OYOut[13]: <matplotlib.text.Text object at 0x99303cc>

In [14]: title('Mi grafica') # Título del gráficoOut[14]: <matplotlib.text.Text object at 0x993802c>

In [15]: text(1, -0.4, 'Nota') # Texto en coodenadas (1, -0.4)

10.1. Trabajando con texto dentro del gráfico 97

Page 104: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

En este ejemplo, se usó la función text() para añadir un texto arbitrario en la gráfica, cuyaposición se debe dar en las unidades de la gráfica. Cuando se utilizan textos también es posibleusar fórmulas con formato LaTeX. Veamos un ejemplo,:

In [27]: clf() #limpio la figura

In [27]: from math import *

In [27]: from numpy import *

In [29]: x = arange(0.1, 6*pi,0.1)

In [30]: y1 = sin(x)/x

In [31]: y2 = sin(x)*exp(-x)

In [32]: p1, p2 = plot(x, y1, x, y2)

In [33]: texto1 = text(2, 0.6, r'$\frac\sin(x)x$', fontsize=20)

In [34]: texto2 = text(13, 0.2, r'$\sin(x) \cdot e^-x$', fontsize=16)

In [35]: grid() # Añado una malla al gráfico

In [36]: title('Representacion de dos funciones')Out[36]: <matplotlib.text.Text object at 0x99fb78c>

In [37]: xlabel('Tiempo / s')

98 Capítulo 10. Representación gráfica de funciones y datos

Page 105: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

Out[37]: <matplotlib.text.Text object at 0x94f172c>

In [38]: ylabel('Amplitud / cm')Out[38]: <matplotlib.text.Text object at 0x94f20ec>

Aquí hemos usado código LaTeX para escribir fórmulas matemáticas, para lo que siempre hay queescribir entre r'$ formula $' y he usado un tamaño de letra mayor con el parámetro fontsize.En la última línea hemos añadido una malla con la función grid().

Nota: LaTeX es un sistema de escritura orientado a contenidos matemáticos muy popular enciencia e ingeniería. Puedes ver una buena introducción a LaTeX en esta dirección (pdf): http://www.ctan.org/tex-archive/info/lshort/spanish.

10.2 Representación gráfica de funciones

Visto el ejemplo anterior, vemos que en Python es muy fácil representar gráficamente una fun-ción matemática. Para ello, debemos definir la función y luego generar un array con el intervalode valores de la variable independiente que se quiere representar. Definamos algunas funcionestrigonométricas y luego representémoslas gráficamente:

>>> def f1(x):.....: y = sin(x).....: return y

10.2. Representación gráfica de funciones 99

Page 106: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

.....:

>>> def f2(x):.....: y = sin(x)+sin(5.0*x).....: return y.....:

>>> def f3(x):.....: y = sin(x)*exp(-x/10.).....: return y.....:

>>> # array de valores que quiero representar>>> x = arange(0, 10*pi, 0.1)

>>> p1, p2, p3 = plot(x, f1(x), x, f2(x), x, f3(x))

>>> # Añado leyenda, tamaño de letra 10, en esquina superior derecha>>> legend(('Funcion 1', 'Funcion 2', 'Funcion 3'),

prop = 'size':10, loc = 'upper right')>>> <matplotlib.legend.Legend object at 0xbb4b0ac>

>>> xlabel('Tiempo / s')>>> <matplotlib.text.Text object at 0xa06764c>

>>> ylabel('Amplitud / cm')>>> <matplotlib.text.Text object at 0xa0c32cc>

>>> title('Representacion de tres funciones')>>> <matplotlib.text.Text object at 0xa0c3e8c>

100 Capítulo 10. Representación gráfica de funciones y datos

Page 107: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

Nótese que hemos añadido una leyenda con la función legend() que admite como entrada unatupla con strings que corresponden consecutivamente a cada una de las curvas del gráfico.

10.3 Histogramas

Cuando tenemos un conjunto de datos numéricos, por ejemplo como consecuencia de la medidade una cierta magnitud y queremos representarlos gráficamente para ver la distribución subyacentede los mismos se suelen usar los gráficos llamados histogramas. Los histogramas representan elnúmero de veces que los valores del conjunto caen dentro de un intervalo dado, frente a los di-ferentes intervalos en los que queramos dividir el conjunto de valores. En Python podemos hacerhistogramas muy fácilmente con la función hist() indicando como parámetro un array con losnúmeros del conjunto. Si no se indica nada más, se generará un histograma con 10 intervalos (lla-mados bins, en inglés) en los que se divide la diferencia entre el máximo y el mínimo valor delconjunto. Veamos un ejemplo:

>>> # Importo el módulo de numeros aleatorios de scipy>>> from scipy import random>>> # utilizo la función randn() del modulo random para generar>>> # un array de números aleatorios con distribución normal>>> nums = random.randn(200) # array con 200 números aleatorios>>> # Genero el histograma>>> hist(nums)>>>(array([ 2, 10, 11, 28, 40, 49, 37, 12, 6, 5]),array([-2.98768497, -2.41750815, -1.84733134, -1.27715452, -0.70697771,

10.3. Histogramas 101

Page 108: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

-0.13680089, 0.43337593, 1.00355274, 1.57372956, 2.→˓14390637,

2.71408319]),<a list of 10 Patch objects>)

Si no se le proporciona ningún otro argumento a randn() produce floats alrededor de 0 y conuna varianza = 1.

Vemos que los números del array se dividieron automáticamente en 10 intervalos (o bins) y cadabarra representa para cada una de ellos el número de valores que caen dentro. Si en lugar de usarsólo 10 divisiones queremos usar 20 por ejemplo, debemos indicarlo como un segundo parámetro:

>>> hist(nums, bins=20)

El la figura de abajo se muestra el resultado de superponer ambos histogramas. Nótese que lafunción hist() devuelve una tupla con tres elementos, que son un array con el número elementosen cada intervalo, un array con el punto del eje OX donde empieza cada intervalo y una listacon referencias a cada una de las barras para modificar sus propiedades (consulten el manual dematplotlib para encontrar más información y mayores posibilidades de uso).

10.4 Figuras diferentes

Se pueden hacer cuantas figuras independientes (en ventanas distintas) queramos con la funciónfigure(n) donde n es el número de la figura. Cuando se crea una figura al hacer plot() sehace automáticamente figure(1), como aparece en el título de la ventana. Podríamos crear

102 Capítulo 10. Representación gráfica de funciones y datos

Page 109: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

una nueva figura independiente escribiendo figure(2), en ese momento todos los comandos deaplican a figura activa, la figura 2. Podemos regresar a la primera escribiendo figure(1) paratrabajar nuevamente en ella, por ejemplo:

>>> p1, = plot(sin(x)) # Crea una figura en una ventana (Figure 1)>>> figure(2) # Crea una nueva figura vacía en otra ventana

→˓(Figure 2)>>> p2, = plot(cos(x)) # Dibuja el gráfico en la figura 2>>> title('Funcion coseno') # Añade un título a la figura 2>>> figure(1) # Activo la figura 1>>> title('Funcion seno') # Añade un título a la figura 2

10.5 Varios gráficos en una misma figura

En ocasiones nos interesa mostrar varios gráficos diferentes en una misma figura o ventana. Paraello podemos usar la función subplot(), indicando entre paréntesis un número con tres dígitos.El primer dígito indica el número de filas en los que se dividirá la figura, el segundo el númerode columnas y el tercero se refiere al gráfico con el que estamos trabajando en ese momento. Porejemplo, si quisiéramos representar las tres funciones anteriores usando tres gráficas en la mismafigura, una al lado de la otra y por lo tanto con una fila y tres columnas, haríamos lo siguiente:

>>> # Figura con una fila y tres columnas, activo primer subgráfico>>> subplot(131)>>> p1, = plot(x,f1(x),'r-')>>> # Etiqueta del eje Y, que es común para todas>>> ylabel('Amplitud / cm')>>> title('Funcion 1')

>>> # Figura con una fila y tres columnas, activo segundo subgráfico>>> subplot(132)>>> p2, = plot(x,f2(x),'b-')>>> # Etiqueta del eje X, que es común para todas>>> xlabel('Tiempo / s')>>> title('Funcion 2')

>>> # Figura con una fila y tres columnas, activo tercer subgráfico>>> subplot(133)>>> p3, = plot(x, f3(x),'g-')>>> title('Funcion 3')

10.5. Varios gráficos en una misma figura 103

Page 110: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

Al igual que con varias figuras, para dibujar en un gráfico hay que activarlo. De esta forma, siacabamos de dibujar el segundo gráfico escribiendo antes subplot(132) y queremos cambiaralgo del primero, debemos activarlo con subplot(131) y en ese momento todas funciones degráficas que hagamos se aplicarán a él.

10.6 Representando datos experimentales

Cuando estamos en el laboratorio (u observatorio) haciendo un experimiento y midiendo algúnparámetro físico solemos obtener un conjunto de números que normalmente guardaremos en unfichero de texto en cualquier ordenador. Representar datos leídos de un fichero en lugar de gene-rarlos directamente como hemos hecho hasta ahora, es tan sencillo como leer los datos y pasarlos aarrays de numpy. Una vez hecho, se representan gráficamente como ya hemos visto. Supongamosque tenemos los resultados de un experimento en una tabla de dos columnas almacenada en elfichero “datos_2col.txt”, para poder dibujarlos en un gráfico hacemos,:

>>> # Leemos el fichero de dos columnas de datos, pasándolo a un array>>> datos = loadtxt('datos_2col.txt')>>> datos.shape>>> (100, 2)>>> # es decir, 100 filas, 2 columnas

>>> col2, = plot(datos[:,1], 'b.') # Segunda columna, puntos azules→˓(b)

>>> col1, = plot(datos[:,0], 'r.') # Primera columna, puntos rojos→˓(r)

>>> # Trazo una línea horizontal en la coordenada y=4 color verde (g)>>> axhline(4, color='g')>>> <matplotlib.lines.Line2D object at 0x169c6d8c>

>>> # Trazo una línea vertical en la coordenada x=20 color verde (g)>>> axvline(20, color='g')

104 Capítulo 10. Representación gráfica de funciones y datos

Page 111: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

>>> <matplotlib.lines.Line2D object at 0xac5986c>

>>> # Dibujo una banda horizontal de y=0 a y=2 de color azul>>> # y 30% de transparencia (alpha=0.3)>>> axhspan(0, 2, alpha=0.3, color='b')>>> <matplotlib.patches.Polygon object at 0xac59c4c>

>>> # Dibujo una banda vertical de x=60 a x=80 de color verde>>> # y 30% de transparencia>>> axvspan(60, 80, alpha=0.3, color='g')>>> <matplotlib.patches.Polygon object at 0xac59a0c>

>>> # Etiqueto los ejes>>> xlabel('Eje X')>>> <matplotlib.text.Text object at 0xad043ac>>>> ylabel('Eje Y')>>> <matplotlib.text.Text object at 0xad0b52c>

En este caso hemos usado además algunas funciones para crear líneas y bandas horizontales yverticales.

10.7 Datos experimentales con barras de error

Cuando se trabaja con datos de laboratorio es muy habitual tener errores asociados a los datos quese van tomando; al representarlos gráficamente después es muy conveniente dibujar también las

10.7. Datos experimentales con barras de error 105

Page 112: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

barras de error de cada dato tomado. En Python esto se puede hacer fácilmente usando la funciónerrorbar() en lugar de plot() o junto con ella. A la hora de usarla hay que incluir en susintaxis los errores como parámetros usando floats si son errores iguales para todos los puntos obien un array representando el error de cada punto. Veamos un ejemplo:

>>> # Datos de x e y>>> x = array([ 0.1, 0.6, 1.1, 1.6, 2.1, 2.6, 3.1, 3.6, 4.1,

→˓4.6])>>> y = array([ 0.90, 0.54, 0.33, 0.20, 0.12,

0.07, 0.04 , 0.02, 0.01, 0.01])

>>> # Error fijo en x e y>>> err_x = 0.1>>> err_y = 0.2

>>> errorbar(x, y, xerr=err_x, yerr=err_y)

>>> # Si los errores de x e y son distintos en cada punto,>>> # se ponen en un array. Supongamos que sean:>>> err_y = array([ 0.12, 0.10, 0.14, 0.11, 0.18,

0.18, 0.17, 0.11, 0.18, 0.19])>>> err_x = array([ 0.07, 0.12, 0.06, 0.11, 0.09,

0.12, 0.06, 0.05, 0.05, 0.14])

>>> # Gráfico con la barra de error en x e y, usando>>> # línea continua y puntos (fmt='-o')>>> errorbar(x, y, xerr=err_x, yerr=err_y, fmt='-o')

106 Capítulo 10. Representación gráfica de funciones y datos

Page 113: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

Hay veces que para algunos tipos de datos, conviene representar alguno de los ejes o ambos enescala logarítmica para apreciar mejor la evolución de la gráfica. Podemos usar las funcionessemilogx(), semilogy() o loglog() para hacer un gráfico en escala logarítmica en eleje x, en el eje y o en ambos, respectivamente. Por ejemplo, para representar el gráfico anterior conel eje y en escala logarítmica, podemos hacer lo siguiente:

>>> # Eje y en escala logarítmica>>> p1, = semilogy(x, y,'rs-')

>>> grid()>>> xlabel('Eje X')>>> ylabel('Eje Y')>>> title('Representacion en escala logaritmica del eje Y')

10.8 Representación de datos bidimensionales

Los datos bidimensionales como su nombre indica son valores de una magnitud física representadapor una función que tiene dos variables independientes, normalmente x e y; se trata pues de repre-sentar funciones del tipo z=z(x,y), donde z puede representar flujo luminoso, presión atmosférica,altura del terreno, etc... Hay varias formas de representar estos datos bidimensionales (como podríaser una imagen), una de ellas es usar escalas de colores para representar los diferentes valores de zpara pares de valores (x,y). En Python lo hacemos usando la función imshow():

>>> # Creo un array 1D 100x100 de valores de 0.0 a 99999.0>>> datos1D = arange(10000.) # array unidimensional con 10000

→˓elementos>>> # Ahora cambio la forma (reshape) del array redistribuyendo sus

→˓elementos,

10.8. Representación de datos bidimensionales 107

Page 114: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

>>> # de 10000 en 1D a un array de 100 filas y 100 columnas en 2D,>>> # como si fuese una imagen.>>> datos2D = datos1D.reshape(100,100)>>> datos2D.shape>>> (100, 100)

>>> # Representamos gráficamente el array bidimensional>>> imshow(datos2D)>>> # Añadimos una paleta (barra de color) para indicar la equivalencia>>> # de los colores con los valores de la función>>> colorbar()>>> # Cambio a la paleta de colores gray() (por defecto es jet())>>> gray()

Vamos a representar una imagen en color con formato png, nebulosa.png, que está en nuestrodirectorio de trabajo.:

>>> foto = imread("nebulosa.png")>>> imshow(foto)

108 Capítulo 10. Representación gráfica de funciones y datos

Page 115: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

Las imágenes en color tienen 3 canales RGB, podemos limitarnos a tomar uno haciendo:

>>> foto1 = foto[:,:,0]

Podemos ahora cambiar la paleta o la escala de colores con la que queremos ver la imagen, para loque variamos el argumento cmap. Si queremos mostrarla en blanco y negro usamos gray():

>>> imshow(foto1, cmap = gray())

Otras paletas disponibles son jet(), hot() o spectral().

10.9 Guardando las figuras creadas

Después de crear una figura con cualquiera de los procedimientos descritos hasta ahora podemosguardarla con la función savefig() poniendo como parámetro el nombre del fichero con su ex-tensión. El formato de grabado se toma automáticamente de la extensión del nombre. Los formatosdisponibles en Python son los más usuales: png, pdf, ps, eps y svg. Por ejemplo:

>>> savefig("mi_primera_grafica.eps") # Guardo la figura en formato→˓eps

>>> savefig("mi_primera_grafica.png") # Guardo la figura en formato→˓png

Si el gráfico se va usar para imprimir, por ejemplo en una publicación científica o en un informe, esrecomendable usar un formato vectorial como Postscript (ps) o Postscript encapsulado (eps), pero

10.9. Guardando las figuras creadas 109

Page 116: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

si es para mostrar por pantalla o en una web, el más adecuado es un formato de mapa de bits comopng o jpg.

Consulta la web de matplotlib (http://matplotlib.sourceforge.net/) para ver muchas más pro-piedades y ejemplos de esta librería.

10.10 Ejercicios

1. La curva plana llamada trocoide, una generalización de la cicloide, es la curva descrita por unpunto P situado a una distancia b del centro de una circunferencia de radio a, a medida querueda (sin deslizar) por una superficie horizontal. Tiene por coordenadas (x,y) las siguientes:

𝑥 = 𝑎 𝜑− 𝑏 𝑠𝑒𝑛𝜑 , 𝑦 = 𝑎− 𝑏 𝑐𝑜𝑠𝜑

Escribir un programa que dibuje tres curvas (contínuas y sin símbolos), en el mismo gráficocartesiano (OX,OY), para un intervalo 𝜑 = [0.0, 18.0] (en radianes) y para los valores dea=5.0 y b=2.0, 5.0 y 8.0 . Rotular apropiadamente los ejes e incluir una leyenda con los tresvalores de que distinguen las tres curvas.

2. Dibujar las diferentes trayectorias de los proyectiles disparados por un cañón situado en unterreno horizontal para diferentes ángulos de elevación (inclinación respecto de la horizontal)en un intervalo de tiempo de 0 a 60 s. El cañón proporciona una velocidad inicial de 300 m/s.Dibujarlas para los ángulos de elevación siguientes: 20, 30, 40, 50, 60 y 70 grados y suponerque el cañón está situado en el origen de coordenadas. Rotular apropiadamente los ejes einsertar una leyenda que identifique las diferentes trayectorias. Recordar que el proyectil nopuede penetrar en el suelo de forma que hay que establecer los límites apropiados para eldibujo.

3. Cuando una fuente de luz coherente atraviesa una rendija delgada, se produce difracción dela luz, cuyo patrón de intensidad en la aproximación de Fraunhofer está dado por:

𝐼(𝜃) = 𝐼0(𝑠𝑒𝑛𝛽

𝛽)2 𝛽 =

𝜋𝑎𝑠𝑒𝑛𝜃

𝜆

donde a es el ancho de la rendija, 𝜆 la longitud de onda de la luz, 𝐼0 la intensidad en eleje y 𝜃 el ángulo de la posición medida con el eje de la rendija (ver dibujo). Representargráficamente la intensidad del patrón de difracción para 𝜆 = 400nm, 𝜆 = 650nm y 𝜆 = 800nmusando 𝐼0 = 1 y a = 0.04mm en el intervalo −𝜋/20 < 𝜃 < +𝜋/20. Comprobar cual es elefecto del patrón de difracción al duplicar el ancho de la rendija.

110 Capítulo 10. Representación gráfica de funciones y datos

Page 117: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

1. La variación de temperatura de un objeto a temperatura 𝑇0 en un ambiente a 𝑇𝑠 cambia de lasiguiente manera:

𝑇 = 𝑇𝑠 + (𝑇0 − 𝑇𝑠)𝑒−𝑘𝑡

con 𝑡 en horas y k un parámetro que depende del objeto. a) Representar gráficamente lavariación de la temperatura con el tiempo, partiendo de una 𝑇0 = 5∘𝐶 a lo largo de 24horas suponiendo k=0.45 y temperatura ambiente de 40ºC. b) Superponer sobre esta curvalas curvas correspondientes a otros objetos con k=0.3 y k=0.6 con distinto color y trazado,identificándolas con una leyenda.

2. Representen nuevamente la curva del apartado a) del ejercicio anterior superponiendoademás las curvas correspondientes a temperaturas iniciales distintas, de 𝑇0 = −5∘𝐶 y𝑇0 = 15∘𝐶. Para 𝑇0 = 5∘𝐶 representen en una figura aparte cómo cambian las curvas contemperaturas ambiente de 20ºC y 50ºC, además de la de 40ºC. Identifiquen cada curva yetiqueta correctamente los ejes en todas las gráficas.

3. Representar gráficamente las siguientes funciones:

f(x) = a e^-frac(x-x_0)^22c^2

g(x) = fracb(x-x_0)^2+b^2

usando los valores a=2.0, 𝑥0 = 10.0, c=5.0 y b=0.5, en el intervalo de x [-50,+50]. Com-prueba cómo afecta a las gráficas distintos valores de los parámetros c y b.

4. Con la serie de Gregory-Leibnitz para el cálculo de 𝜋 usada anteriormente en el problema5.5:

4𝑛∑

𝑘=1

(−1)𝑘+1

2𝑘 − 1

el valor obtenido de 𝜋 se acerca lentamenta al verdadero con cada término que se añada.Calculen todos los valores que va tomando 𝜋 con cada término añadido y representen en una

10.10. Ejercicios 111

Page 118: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

figura con dos gráficas (usando subplot()) los primeros 300 valores que toma 𝜋 frente alnúmero de términos usados en una de ellas y el valor absoluto de la diferencia entre el valorcalculado y el real frente al número de elementos en la otra.

5. El fichero medidas_I131.txt (directorio de datos en el aula virtual) contiene medidas demasa de yodo 131 radioactivo hechas diariamente para medir su coeficiente de desinte-gración. La primera columna es la masa residual en gramos y la segunda es el error dela medida. Representen gráficamente las medidas de masa frente al tiempo incluyendo ba-rras de error usando puntos sin unir con líneas y etiquetando los ejes apropiadamente. Alleer el fichero saltar las primeras cuatro líneas que no contienen datos. Esto se hace coninput.readlines()[4:].

6. El movimiento de un oscilador amortiguado se puede expresar de la siguiente manera:

𝑥 = 𝐴0𝑒−𝑘𝜔𝑡 cos (𝜔𝑡 + 𝛿)

Siendo 𝐴0 la amplitud inicial, 𝜔 la fecuencia angular de oscilación y k el factor de amortigua-miento. Representar gráficamente el movimiento de un oscilador amortiguado de amplitudinicial de 10 cm y frecuencia de 10 ciclos/s y 𝛿 = 𝜋/8 con factores de amortiguamiento de0.1, 0.4, 0.9 y 1.1 durante 10 s. Incluya una leyenda identificativa de las curvas dibujadas.

Para el gráfico correspondiente a k=0.1 unir con líneas a trazos los valores máximos por unlado y los valores mínimos por otro del movimiento oscilatorio. Nótese que corresponden alas curvas para las que 𝑥 = 𝐴0𝑒

−𝑘𝜔𝑡 y 𝑥 = −𝐴0𝑒−𝑘𝜔𝑡.

7. La curva plana llamada epicicloide, tiene por coordenadas cartesianas (x,y) las siguientes:

𝑥 = (𝑎 + 𝑏) cos𝜑− 𝑏 cos(𝑎

𝑏+ 1)𝜑 , 𝑦 = (𝑎 + 𝑏) sin𝜑− 𝑏 sin(

𝑎

𝑏+ 1)𝜑

Escribir un programa en el que se dibuje la curva (contínua y sin símbolo) para un intervalo𝜑 = [0, 6𝜋] y para los valores de a= 1/3 y b= 1/8. Rotular apropiadamente los ejes e incluiren el título los valores de a, b y el intervalo de valores de 𝜑 utilizado.

8. En un experimento de laboratorio se tiene un circuito eléctrico al que vamos variando elvoltaje de la fuente de alimentación desde 0.05 V hasta 15.00 V, a intervalos de 0.01 V y semide la intensidad de corriente que circula por él con un amperímetro. Se repite el experi-mento cinco veces, de forma que para cada voltaje V aplicado se obtienen cinco medidas deI (en amperios) que se almacenan en una tabla que contiene el fichero datos_intensidad.txt.Dibujar un histograma y calcular el valor medio y la desviación estándar de las cinco seriesde medidas de la intensidad para cada voltaje aplicado al circuito.

112 Capítulo 10. Representación gráfica de funciones y datos

Page 119: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

CAPÍTULO 11

Ajuste de datos experimentales: el método de mínimoscuadrados

Un trabajo habitual en el laboratorio es la creación de un modelo matemático de un fenómenofísico determinado que explique su comportamiento. Obviamente, este modelo deberá predecirtambién los datos experimentales que se obtengan de su recreación en el laboratorio. Por ejemplo,si se toman medidas de la amplitud de las oscilaciones de un péndulo, es posible obtener unafunción oscilatoria analítica que describa ese movimiento con la frecuencia y amplitud adecuadaspara cualquier instante de tiempo.

11.1 Formulación general

El principio de mínimos cuadrados fue formulado por primera vez por Legendre de la siguienteforma: “El valor más probable de una cantidad observada es tal que la suma de los cuadradosde las desviaciones de las observaciones respecto de este valor es mínimo”; y se utiliza extensiva-mente en el problema de la optimización de funciones o en el ajuste de funciones a datos obtenidosde la observación de fenómenos naturales o experimento de laboratorio.

Puede formularse sucintamente así: si tenemos un conjunto de observaciones de una cantidadcualquiera 𝑥𝑖 con 𝑖 = 1, 2, ..., 𝑛, el valor más probable de esta cantidad es 𝑋 si verifica que la∑𝑖=𝑛

𝑖=1 (𝑥𝑖 −𝑋)2 es mínima.

Es útil comprobar que en este caso el valor más probable coincide con el valor medio del conjun-to de observaciones. En efecto, para comprobarlo no tenemos mas que calcular el mínimo de lafunción anterior, es decir:

𝑑

𝑑𝑋

(𝑖=𝑛∑𝑖=1

(𝑥𝑖 −𝑋)2

)= 0 ⇒ −2

𝑖=𝑛∑𝑖=1

(𝑥𝑖 −𝑋) = 0 ⇒ 𝑋 =

∑𝑥𝑖

𝑛= 𝑥

Nótese que cuando esta función es mínima lo es también la varianza, 𝜎2 del conjunto de observa-ciones 𝑥𝑖.

113

Page 120: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

11.2 Aplicación al ajuste de funciones a datos experimen-tales

El problema al que vamos aplicar este principio de mínimos cuadrados es el siguiente:

Supongamos que 𝑦𝑖 son 𝑛 medidas de una cantidad 𝑦 (o una combinación de ellas) que se co-rresponde con otras 𝑛 medidas 𝑥𝑖 de otra cantidad 𝑥. Podemos pensar que existe una relaciónentre ellas, por ejemplo 𝑦 = 𝑓(𝑥), y queremos determinar precisamente cuál es esta función 𝑓 querelaciona ambas cantidades.

Aplicando el principio de mínimos cuadrados podemos decir que la función más probable querelaciona ambas cantidades será aquella que haga que la función:(

𝑖=𝑛∑𝑖=1

(𝑓(𝑥𝑖) − 𝑦𝑖)2

)sea mínima.

11.2.1 El caso en que la función es una recta (polinomio de orden 1)

Supongamos que la función que relaciona 𝑥 con 𝑦 es: 𝑦 = 𝑓(𝑥) = 𝑎𝑥 + 𝑏, por lo tanto la rectamás probable que relaciona el conjunto de observaciones 𝑥𝑖 con el de 𝑦𝑖 será la que minimice lafunción:

𝑀 =

(𝑖=𝑛∑𝑖=1

(𝑎𝑥𝑖 + 𝑏− 𝑦𝑖)2

)

Para calcular los valores de a y b que definen la recta en cuestión, planteamos el problema deoptimización de funciones y obtenemos las ecuaciones que verifican

𝜕𝑀

𝜕𝑎= 0 = 2

(𝑖=𝑛∑𝑖=1

𝑥𝑖 (𝑎𝑥𝑖 + 𝑏− 𝑦𝑖)

)

𝜕𝑀

𝜕𝑏= 0 = 2

(𝑖=𝑛∑𝑖=1

(𝑎𝑥𝑖 + 𝑏− 𝑦𝑖)

)

es decir,

𝑎∑

𝑥2𝑖 + 𝑏

∑𝑥𝑖 =

∑𝑥𝑖𝑦𝑖

𝑎∑

𝑥𝑖 + 𝑏𝑛 =∑

𝑦𝑖

114Capítulo 11. Ajuste de datos experimentales: el método de mínimos cuadrados

Page 121: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

y resolviendo este sistema lineal de dos ecuaciones con dos incógnitas (a y b) nos queda:

𝑎 =𝑛∑

𝑥𝑖𝑦𝑖 −∑

𝑥𝑖

∑𝑦𝑖

𝑛∑

𝑥2𝑖 − (

∑𝑥𝑖)2

𝑏 =

∑𝑦𝑖∑

𝑥2𝑖 −

∑𝑥𝑖

∑𝑥𝑖𝑦𝑖

𝑛∑

𝑥2𝑖 − (

∑𝑥𝑖)2

con lo que queda resuelto el problema.

Conviene fijarse en algunas características de este problema como las siguientes:

1. Si 𝑏 = 0 entonces 𝑦 = 𝑎𝑥, donde 𝑎 =∑

𝑥𝑖𝑦𝑖/∑

𝑥2𝑖 .

2. Pueden comprobar que la recta obtenida pasa por el punto (𝑥, 𝑦).

3. Se definen los llamados residuos del ajuste como 𝑑𝑖 = 𝑎𝑥𝑖 + 𝑏− 𝑦𝑖.

4. Pueden comprobar que la varianza del conjunto de 𝑑𝑖 será 𝛼2 =∑

𝑑2𝑖 /(𝑛− 2), donde 𝑛− 2es el llamado número de grados de libertad del sistema.

5. La varianza es precisamente la cantidad que se minimiza en el método de mínimos cuadra-dos.

6. Se define el coeficiente de correlación r para evaluar el grado de dependencia de las dosseries de observaciones, que va desde 0 (no correlación) a 1 (correlación perfecta), de laforma siguiente:

𝑟2 =(∑

(𝑥− 𝑥)(𝑦 − 𝑦))2∑(𝑥− 𝑥)2

∑(𝑦 − 𝑦)2

11.2.2 Aplicación al caso de polinomios de cualquier orden

En el caso de ajustes a polinomios de cualquier orden (𝑚), es decir∑𝑘=𝑚

𝑘=0 𝑎𝑘𝑥𝑘, el método funciona

de igual modo. Lo único que sucede es que, al tener que determinar 𝑚 + 1 parámetros, el sistemade ecuaciones lineales que aparece es precisamente de orden 𝑚 + 1 complicando algebraicamentela solución pero no conceptualmente. Veámoslo a título informativo.

Supongamos que tenemos una serie de medidas (𝑥1, 𝑦1), (𝑥2, 𝑦2), (𝑥3, 𝑦3), . . . , (𝑥𝑛, 𝑦𝑛), siendo xla variable independiente e y la dependiente. Para un modelo 𝑓(𝑥) de estos datos, hay un error rpara cada medida de 𝑟1 = 𝑦1 − 𝑓(𝑥1), 𝑟2 = 𝑦2 − 𝑓(𝑥2), . . . , 𝑟𝑛 = 𝑦𝑛 − 𝑓(𝑥𝑛). Según el método demínimos cuadrados, la mejor función de ajuste f(x) es aquella en la que

𝑅 = 𝑑21 + 𝑑22 + · · · + 𝑑2𝑛 =𝑛∑

𝑖=1

𝑑2𝑖 =𝑛∑

𝑖=1

|𝑦𝑖 − 𝑓(𝑥𝑖)|2

es minimo. La forma canónica de este problema es

𝑋𝑎 = 𝑌

11.2. Aplicación al ajuste de funciones a datos experimentales 115

Page 122: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

en la que X es una matriz MxN para M medidas experimentales y N grados de libertad y el objetivoes minimizar |𝐴𝑥−𝑦|. En el caso del ajuste a un polinomio de grado N, el modelo sería de la forma

𝑦(𝑥) = 𝑎𝑁𝑥𝑁 + · · · + 𝑎2𝑥

2 + 𝑎1𝑥 + 𝑎0

para el que habría que escojer la combinación de parámetros 𝑎𝑖 que mejor se ajusten a los datos.Así, la matriz A, llamada matriz de Vandermonde tiene esta forma:⎡⎢⎢⎢⎣

𝑥𝑁1 · · · 𝑥2

1 𝑥1 1𝑥𝑁2 · · · 𝑥2

2 𝑥2 1...

𝑥𝑁𝑀 · · · 𝑥2

𝑀 𝑥𝑀 1

⎤⎥⎥⎥⎦en ella, cada fila corresponde a una medida experimental 𝐴𝑥 = 𝑦𝑖.

11.3 Ajuste a polinomios con Python

La función polyfit() de numpy permite ajuste de datos experimentales a polinomios de cual-quier orden. La sintaxis básica es:

parametros = polyfit(x, y, n)

en donde x e y son los datos experimentales y n grado del polinomio a ajustar. El resultado es unalista con los parámetros del polinomio. Si a polyfit() se le incluye la opción full=True, ademásde los parámetros devuelve los residuos y otros datos (ver ayuda de polyfit() para detalles).

Consideremos el siguiente ajuste a una recta de una serie de datos x e y:

# Importo todas las funciones de numpy, si no lo he hechofrom numpy import *

# Datos experimentalesx = array([ 0., 1., 2., 3., 4.])y = array([ 10.2 , 12.1, 15.5 , 18.3, 20.6 ])

# Ajuste a una recta (polinomio de grado 1)p = polyfit(x, y, 1)

print(p)# imprime [ 2.7 9.94]

en este ejemplo polyfit() devuelve la lista de parámetros p de la recta, por lo que el modelolineal 𝑓(𝑥) = 𝑎𝑥 + 𝑏 de nuestros datos será:

𝑦(𝑥) = 𝑝0𝑥 + 𝑝1 = 2.7𝑥 + 9.94

Ahora podemos dibujar los datos experimentales y la recta ajustada:

116Capítulo 11. Ajuste de datos experimentales: el método de mínimos cuadrados

Page 123: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

# Valores de y calculados del ajustey_ajuste = p[0]*x + p[1]

# Dibujamos los datos experimentalesp_datos, = plot(x, y, 'b.')# Dibujamos la recta de ajustep_ajuste, = plot(x, y_ajuste, 'r-')

title('Ajuste lineal por minimos cuadrados')

xlabel('Eje x')ylabel('Eje y')

legend(('Datos experimentales', 'Ajuste lineal'), loc="upper left")

Como se ve en este ejemplo, la salida por defecto de polyfit() es un array con los parámetrosdel ajuste. Sin embargo, si se pide una salida detalla con el parámetro full=True (por defectofull=False), el resultado es una tupla con el array de parámetros, el residuo, el rango, los valoressingulares y la condición relativa. Nos interesa especialmente el residuo del ajuste, que es la sumacuadrática de todos los resíduos

∑𝑛𝑖=1|𝑦𝑖−𝑓(𝑥𝑖)|2. Para el ejemplo anterior tendríamos lo siguiente:

# Ajuste a una recta, con salida completaresultado = polyfit(x, y, 1, full=True)

11.3. Ajuste a polinomios con Python 117

Page 124: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

print(resultado)""" Imprime tupla(array([ 2.7 , 9.94]), # Parámetros del ajustearray([ 0.472]), # Suma de residuos2, # Rango de la matriz del→˓sistemaarray([ 2.52697826, 0.69955764]), # Valores singulares1.1102230246251565e-15) # rcond"""

Si estamos trabajando con polinomios, puede que nos interese usar las funciones polyval() opoly1d() de numpy. Se utilizan para evaluar y generar funciones polinómicas respectivamente,a partir de una lista o array o lista de parámetros. Por ejemplo, si del ejemplo anterior tenemos unarray p con los parámetros del ajuste lineal:

# Evaluo el polinomio en x=5.4print polyval(p, 5.4)# Imprime 24.520000000000003

# Creo una funcion polinomica de parametros pmi_recta = poly1d(p)

# Ahora mi_recta() es una funcion que puedo evaluar

# Evaluo la fucion en x=5.4print mi_recta(5.4)# imprime 24.520000000000003

Como es de esperar, polyfit() sólo puede ajustar polinomios a datos experimentales, pero aveces nos gustaría ajustar otras funciones. En muchos casos, sin embargo, es posible linealizar lafunción con un cambio de variable adecuado y ajustar esta última. Por ejemplo la función

𝑦 =𝑏

𝑥 + 𝑎

se puede linealizar a 𝑦′(𝑥) = 𝑎′𝑥 + 𝑏′ haciendo el cambio

𝑦′ =1

𝑦𝑎 =

𝑎′

𝑏′𝑏 =

1

𝑎′.

ahora basta con ajustar la recta 𝑦′(𝑥) = 𝑎′𝑥+𝑏′ y recuperar los parámetros a y b de la recta original.

En otros casos en los que no es posible linealizar la función o modelo, se tendrá que emplear unmétodo de optimización por mínimos cuadrados más general.

118Capítulo 11. Ajuste de datos experimentales: el método de mínimos cuadrados

Page 125: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

11.4 Ajuste de funciones no lineales

El submódulo optimize de scipy posee varios métodos optimización (búsqueda de máximosy mínimos) incluyendo una función para ajuste por mínimos cuadrados para una función genérica,llamada leastsq(). El método se basa en definir una función de error que es la diferencia entreel modelo y los datos, siendo esta la función que se va a minimizar. En este caso es necesario queel investigador proporcione unos parámetros iniciales aproximados de la función modelo con losque empezar. Veamos un ejemplo sencillo para el ajuste de una recta.

from pylab import *from scipy.optimize import leastsq

# Datos de laboratoriodatos_y = array([ 2.9, 6.1, 10.9, 12.8, 19.2])datos_x = array([ 1.0, 2.0, 3.0, 4.0, 5.0])

# Función para calcular los residuos, donde# se calcula (datos - modelo)def residuos(p, y, x):

error = y - (p[0]*x + p[1])return error

# Parámetros iniciales estimados# y = p0[0]*x + p0[0]

p0 = [2.0, 0.0]

# Hacemos el ajuste por minimos cuadrados con leastsq(). El primer→˓parámetro

# es la funcion de residuos, luego los parámetro iniciales y una tupla→˓con los

# argumentos de la funcion de residuos, en este caso, datos_y y datos_→˓x en

# ese orden, porque así se definió la función de errorajuste = leastsq(residuos, p0, args=(datos_y, datos_x))

# El resultado es una lista, cuyo primer elemento es otra# lista con los parámetros del ajusteprint ajuste[0]# array([ 3.93, -1.41])

Naturalmente, para un simple ajuste lineal bien podemos usar polyfit(), de hecho podemoscomprobar que da lo mismo.

params = polyfit(datos_x, datos_y, 1)print params

11.4. Ajuste de funciones no lineales 119

Page 126: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

# array([ 3.93, -1.41])

Pero leastq() se hace indispensable con una función no lineal ni linealizable. Veamos otroejemplo con una función seno.

from pylab import *from scipy.optimize import leastsqfrom scipy import random

# Generamos unos datos artificiales para hacer el ejemplo# A datos_y se le añade "ruido" que simula error de# medida, añadiendole un valor aleatoriodatos_x = arange(0, 0.1, 0.003)A, k, theta = 10.0, 33.3, pi/5.0y_real = A*sin(2*pi*k*datos_x + theta)datos_y = y_real + 2*random.randn(len(datos_x))

# Ahora se trata de ajustar estos datos una función# modelo tipo senoidal A*sin(2*pi*k*x+theta)

# Defino la funcion de residuosdef residuos(p, y, x):

A, k, theta = perror = y - A*sin(2*pi*k*x + theta)return error

# Parámetros iniciales# y = p[0]*sin(2*pi*p[1]*x + p[2])# Si estos se alejan mucho del valor real# la solución no convergeráp0 = [8.0, 40.0, pi/3]

# hacemos el ajuste por minimos cuadradosajuste = leastsq(residuos, p0, args=(datos_y, datos_x))

# El resultado es una lista, cuyo primer elemento es otra# lista con los parámetros del ajuste.print ajuste[0]

# Ahora muestro los datos y el ajuste gráficamente

plot(datos_x, datos_y, 'o') # datos

# Defino la funcion modelo, para representarla gráficamentedef funcion(p, x):

return p[0]*sin(2*pi*p[1]*x + p[2])

120Capítulo 11. Ajuste de datos experimentales: el método de mínimos cuadrados

Page 127: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

# genero datos a partir del modelo para representarlox1 = arange(0, datos_x.max(), 0.001) # array con muchos puntos de xy1 = funcion(ajuste[0], x1) # valor de la funcion modelo en

→˓los x

plot(x1, y1, 'r-')xlabel('Eje X')ylabel('Eje Y')title('Ajuste de funcion seno con leastsq')legend(('Datos', 'Ajuste lineal'))show()

Aunque es algo más laborioso, leastsq() nos permite en principio ajustar a cualquier funciónajustable. El módulo optimize posee otros métodos de optimización/minimización y desde laversión 0.8 de scipy posee la función curve_fit(), que básicamente es una manera simplifi-cada y más práctica de usar leastsq() para ajuste de curvas.

11.4. Ajuste de funciones no lineales 121

Page 128: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

11.5 Ejercicios

1. Representar gráficamente los siguientes datos y hacer un ajuste por mínimos cuadrados a unpolinomio de grado tres de los datos representando la curva resultante.

x = 3.1 6.3 9.9 12.6 21.4

y = 50.1 190.2 499.0 720.8 1130.0

Superponer los dibujos de las funciones que resultarían de ajustes a polinomios de orden 1 yde orden 2.

2. El fichero de texto medidas_PT_H.txt (archivos Tema 7) posee medidas de presión y tempe-ratura para 10 mol de hidrógeno, que se someten a distintas temperaturas a volumen constan-te. Este experimento se realiza en tres envases con volúmenes distintos. Suponiendo que elgas se comporta idealmente y por tanto que se verifica que PV=nRT, representar los datos yrealizar un ajuste lineal P(T) para cada volumen. ¿Cuánto vale la constante de gases idealessegún cada realización del experimento?

3. El fichero de texto medidas_PV_He.txt (archivos Tema 7) posee medidas de presión y vo-lumen para 0.1 mol de helio, que se comprime sistemáticamente a temperatura constante.Este experimento se realiza a tres temperaturas distintas. Suponiendo que el gas se compor-ta idealmente y por tanto que se verifica que PV=nRT, representar los datos y realizar unajuste lineal P(V) para cada temperatura. ¿Cuánto vale la constante de gases ideales según elexperimento?

4. Se mide el movimiento unidimensional de una partícula sometida una fuerza a lo lar-go de 50 segundos; las medidas de posición y tiempo se encuentran en el fichero medi-das_movimiento_acelerado.txt. Hacer un ajuste a los datos de un movimiento uniforme-mente acelerado y deducir la aceleración y la velocidad y posición iniciales de la partícula.Representar gráficamente los datos con puntos y la curva de ajuste, con el etiquetado de ejesy leyenda.

5. Un isótopo radioactivo sigue una ley de desintegración exponencial de la forma 𝑁(𝑡) =𝑁0𝑒

−𝑘𝑡, donde 𝑁(𝑡) es la cantidad de material que queda en un tiempo t, 𝑁0 la cantidad origi-nal (en t=0) y k es la tasa de decaimiento del isótopo. La semivida de un isótopo es el tiempoque tarda una muestra de ese elemento en disminuir hasta la mitad, es decir 𝑁(𝑇 ) = 𝑁0/2.En un laboratorio se mide cada 12 minutos la masa en gramos de cierto elemento radioactivo.Estos datos se encuentran en el fichero medidas_sustancia_radioactiva.txt (archivos Tema 7).Representar gráficamente las medidas con puntos y hacer un ajuste por mínimos cuadradosdel modelo teórico de desintegración radioactiva para conocer la tasa de decaimiento delisótopo.

6. Para una muestra que contiene 10g de yodo 131 (semivida de 8 días), se hacen diariamentecinco medidas independientes a lo largo de 60 días. Esas medidas están en el fichero medi-das_decaimiento_yodo131b.txt (archivos Tema 7), donde cada fila corresponde a cada unade las 5 medidas realizadas diariamente en gramos de yodo que queda. Representar en ungráfico con puntos las cinco medidas con colores distintos para cada una y ajustar a cada

122Capítulo 11. Ajuste de datos experimentales: el método de mínimos cuadrados

Page 129: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

una la curva teórica de decaimiento. Imprimir por pantalla los parámetros de cada uno de loscinco ajustes.

7. Cualquier metal de longitud 𝐿0 a temperatura inicial 𝑇0, que es sometido posteriomente a unatemperatura T sufre una dilatación o contracción dada aproximadamente por 𝛿𝐿 = 𝛼∆𝑇 )donde ∆𝑇 es la diferencia de temperaturas y 𝛼 el coeficiente de dilatación característico delmetal. En un laboratorio se mide la dilatación que experimentan cuatro varillas de metal dedistinto material de longitud inicial 𝐿0 = 10𝑐𝑚 al ir aumentando progresivamente su tempe-ratura en un grado; estos datos se encuentran en el fichero medidas_dilatacion_metales.txt.Representar gráficamente las medidas en una única figura con un color distinto para cadametal y calcular el factor de dilatación a para cada uno ajustando el modelo teórico a losdatos experimentales.

11.5. Ejercicios 123

Page 130: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

124Capítulo 11. Ajuste de datos experimentales: el método de mínimos cuadrados

Page 131: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

CAPÍTULO 12

Otras aplicaciones de Cálculo Numérico

Aunque el paquete numpy ofrece ciertas funcionalidades matemáticas además de la manipulaciónbásica de arrays, como el paquete linalg para álgebra lineal y random para números aleatorios,en scipy encontraremos muchas más herramientas matemáticas de análisis científico de las quepodamos necesitar especialmente durante la carrera. scipy es una colección de paquetes de al-goritmos y herramientas matemáticas para distintas tareas de análisis y cálculo que también utilizanumpy. scipy posee varios subpaquetes que deben importarse independientemente cuando sevayan a utilizar; éstos son algunos de ellos:

Subpaquete Descripciónodr Regresión de distancias ortogonales (ODR)misc Funciones varias (lectura de imagenes, factorial, etc.)fftpack Algoritmos para transformada de Fourier discretaio Entrada y salida de datosstats Funciones estadísticas muy variadaslib Envoltorios (wrappers) de Python a librerías externasintegrate Integración o cuadratura numéricandimage Imagenes n-dimensionaleslinalg Álgebra lineal más elaborada que numpyinterpolate Herramientas de interpolación de series numéricasoptimize Herramientas de optimización de funcionessignal Tratamiento de señales o series temporales

Para ver la lista completa de subpaquetes consultar la ayuda de scipy como help(scipy) (ha-ciendo antes import scipy para tener todos los nombres asociados a scipy) y consultar supágina web para ver la documentación completa (www.scipy.org). Una manera práctica de traba-jar es importar el espacio de nombres de scipy, es decir el nombre de sus paquetes y funcionesprincipales y luego importar el o los paquetes que vaya a usar, como en este ejemplo:

>>> from scipy import * # importa el nombre de los subpaquetes→˓únicamente

>>> import optimize, stats # importa los paquete optimize y stats

125

Page 132: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

12.1 La integración o cuadratura numérica

12.1.1 El problema que se quiere resolver

En geometría elemental se aprende a calcular el área de figuras simples como rectángulos, triángu-los, círculos y demás, así como los volúmenes de esferas, cubos, cilindros, conos y otros. Una delas motivaciones principales para el invento del cálculo integral fue el cálculo de áreas y volúmenesde regiones del espacio de forma irregular que además constituye un problema central en mecánicaclásica; por ejemplo, para muchos problemas de dinámica de un cuerpo rígido puede considerarsecomo una masa puntual localizada en su centroide (centro de gravedad).

Supongamos una función 𝑓(𝑥) definida en un intervalo [a,b] , la definición moderna de integral:

𝐼(𝑓) =

∫ 𝑏

𝑎

𝑓(𝑥)𝑑𝑥

se basa en el concepto de las sumas de Riemann de la forma:

𝑅𝑛 =𝑛∑

𝑖=1

(𝑥𝑖+1 − 𝑥𝑖)𝑓(𝜉𝑖)

donde, 𝑎 = 𝑥1 < 𝑥2 < ... < 𝑥𝑛 < 𝑥𝑛+1 = 𝑏 y 𝜉 ∈ [𝑥𝑖, 𝑥𝑖+1], 𝑖 = 1, ..., 𝑛.

Supongamos que ℎ𝑛 = max (𝑥𝑖+1 − 𝑥𝑖) : 𝑖 = 1, ..., 𝑛− 1. Si para cualquier 𝑥𝑖 tal que ℎ𝑛 → 0 ycualquiera que sea 𝜉𝑖 tenemos que el lım𝑛→∞ 𝑅𝑛 = 𝑅 finito, entonces se dice que 𝑓 es integrableen el sentido de Riemann en el intervalo [𝑎, 𝑏] y que el valor de la integral es 𝑅.

Como pueden intuir esta definición enseguida sugiere una forma sencilla de calcular aproximada-mente la integral. Sólo tenemos que usar una suma de Riemann con 𝑛 suficientemente grande paraalcanzar la precisión requerida en el valor de la integral. Esta idea funciona, pero debemos elegirlos valores de 𝑥𝑖 y 𝜉𝑖 apropiadamente para evaluar el integrando el número de veces que haga faltasin que sean demasiadas (aumenta el tiempo de cálculo y la necesidad de memoria) o insuficientes(aumenta la imprecisión en el resultado).

Desgraciadamente, algunas funciones que queremos integrar no tienen primitivas de forma analí-tica y, por lo tanto, no nos quedará más remedio que utilizar métodos numéricos para calcular lasintegrales de forma aproximada. Por otro lado, muchas veces tendremos la función a integrar enforma de serie numérica y no en forma analítica por lo que deberemos utilizar métodos numéricospara calcular la integral. A este proceso se le llama cuadratura numérica.

Existen muchas más aplicaciones de la llamada cuadratura numérica, tanto en matemáticas comoen diferentes partes de la Física, de otras ciencias e ingeniería. Aquí solamente introduciremos losconceptos elementales para el cálculo práctico de las integrales determinadas de funciones de unavariable en un intervalo dado.

126 Capítulo 12. Otras aplicaciones de Cálculo Numérico

Page 133: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

12.1.2 El método de los coeficientes indeterminados

Para el cálculo aproximado de las integrales tomaremos la idea de la suma de Riemann. De hecho,aproximaremos la integral por una suma ponderada de los valores del integrando en un númerofinito de puntos en el intervalo de integración. De forma más precisa, aproximaremos el valor de𝐼(𝑓) por una regla de cuadratura de 𝑛 puntos que tiene la forma de:

𝑄𝑛(𝑓) =𝑛∑

𝑖=1

𝑤𝑖𝑓(𝑥𝑖) , 𝑎 ≤ 𝑥1 < 𝑥2 < ... < 𝑥𝑛 ≤ 𝑏.

A los puntos 𝑥𝑖 se les llama nodos de abcisas o nodos simplemente y a los factores 𝑤𝑖 se lesllama pesos o coeficientes. Una cuadratura se llama abierta si 𝑥 ∈ (𝑎, 𝑏) y cerrada si 𝑥 ∈ [𝑎, 𝑏]. Elprincipal objetivo consiste en elegir los nodos y los pesos de forma apropiada para que podamosobtener el nivel deseado de precisión con un coste computacional aceptable, en memoria y/o enrapidez.

Algunas reglas de cuadratura pueden obtenerse utilizando lo que se conoce como interpolaciónpolinómica. Se trata de una técnica de interpolación de un conjunto de datos o de una funciónpor un polinomio. Es decir, dado cierto número de puntos (obtenidos por muestreo o a partir de unexperimento) se pretende encontrar un polinomio que pase por todos los puntos. Los más conocidosy sencillos los detallamos a continuación.

12.1.3 La cuadratura de Newton-Cotes

La elección más simple de los nodos en una regla de cuadratura es elegirlos igualmente separa-dos en el intervalo de integración [a,b] lo que constituye la propiedad que define las llamadascuadraturas de Newton-Cotes (NC). Una cuadratura NC de n puntos tendrá por nodos:

𝑥𝑖 = 𝑎 + 𝑖𝑏− 𝑎

𝑛 + 1, 𝑖 = 1, ..., 𝑛.

Algunas de las reglas más simples de cuadraturas de NC son las siguientes:

Regla del punto medio. Consiste en evaluar la función en el punto medio del intervalo ysustituir los valores de la función en él por un polinomio de grado 0, es decir una constante;lo que nos da la regla de NC de un punto:

𝑀(𝑓) = ℎ

𝑛−1∑𝑖=1

𝑓(𝑥𝑖 + 𝑥𝑖+1

2) ℎ = 𝑥𝑖+1 − 𝑥𝑖 ∀𝑖.

Regla del trapecio: Consiste en evaluar la función en ambos extremos del intervalo y sus-tituir los valores de la función en él por un polinomio de grado 1, es decir una recta; lo quenos da la regla de NC de 2 puntos:

𝑇 (𝑓) = ℎ𝑛−1∑𝑖=1

𝑓(𝑥𝑖) + 𝑓(𝑥𝑖+1)

2ℎ = 𝑥𝑖+1 − 𝑥𝑖 ∀𝑖.

12.1. La integración o cuadratura numérica 127

Page 134: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

Regla de Simpson: Se evalúa la función en los extremos del intervalo y en el punto mediodel mismo sustituyendo los valores de la función en él por un polinomio de grado 2, unaparábola; lo que nos da la regla de NC de 3 puntos:

𝑆(𝑓) =ℎ

6

𝑛−1∑𝑖=1

(𝑓(𝑥𝑖) + 4 · 𝑓(

𝑥𝑖 + 𝑥𝑖+1

2) + 𝑓(𝑥𝑖+1)

)ℎ = 𝑥𝑖+1 − 𝑥𝑖 ∀𝑖.

12.1.4 La cuadratura en Scipy de Python

El subpaquete integrate del paquete scipy de Python ofrece varias herramientas de integra-ción numérica con distintos métodos. Podemos ver todos los disponibles consultando su ayuda:

>>> from scipy import *>>> help(integrate)

Integration routines====================

Methods for Integrating Functions given function object.

quad -- General purpose integration.dblquad -- General purpose double integration.tplquad -- General purpose triple integration.fixed_quad -- Integrate func(x) using Gaussian quadrature of order

→˓n.quadrature -- Integrate with given tolerance using Gaussian

→˓quadrature.romberg -- Integrate func using Romberg integration.

Methods for Integrating Functions given fixed samples.

trapz -- Use trapezoidal rule to compute integral from samples.cumtrapz -- Use trapezoidal rule to cumulatively compute integral.simps -- Use Simpson's rule to compute integral from samples.romb -- Use Romberg Integration to compute integral from

(2**k + 1) evenly-spaced samples.

See the special module's orthogonal polynomials (special) for Gaussianquadrature roots and weights for other weighting factors and

→˓regions.

Interface to numerical integrators of ODE systems.

odeint -- General integration of ordinary differential→˓equations.

ode -- Integrate ODE using VODE and ZVODE routines.

128 Capítulo 12. Otras aplicaciones de Cálculo Numérico

Page 135: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

Existen por ejemplo implementaciones del método del trapecio o el método de Simpson, am-bos métodos simples basados en muestras fijas como ya hemos visto. Las funciones trapz()y simps(), que emplean dichos métodos para al cálculo numérico de integrales, admiten comoentrada un array y de valores a integrar y otro array con la variable independiente x; si no se incluyeun segundo parámetro, el espaciado entre los elementos de y es de 1 por defecto, aunque este valorse puede asignar con el parámetro opcional dx=1.

Supongamos que queremos integrar numéricamente la función sin(𝑥) de 0 a 𝜋, cuyo valor exactoes 2. Veamos cómo se puede calcular numéricamente con distinto número de muestras y el gradode precisión que se alcanza:

>>> from scipy import integrate

>>> # Generamos la función seno con 5 nodos, de 0 a pi>>> x = linspace(0, pi, 5)>>> y = sin(x)

>>> # Integramos el array por el método del trapecio>>> integrate.trapz(y,x)>>> 1.8961188979370398

Si aumentamos el número de muestras, la integración se acerca más al valor real

>>> # Generamos la función seno con 5 nodos, de 0 a pi>>> x = linspace(0, pi, 20)>>> y = sin(x)

>>> # Integramos el array por el método del trapecio>>> integrate.trapz(y,x)>>> 1.9954413183201947

>>> # Integramos por el método de Simpson>>> integrate.simps(y,x)>>> 1.999977188106568

12.1. La integración o cuadratura numérica 129

Page 136: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

Como se ve, el método de Simpson nos da un valor más cercano al verdadero (error relativo de1.14e-05), que el del trapecio (error relativo de 2.28e-03), ya que el primero emplea polinomios degrado 2 para la integración. Obsérvese que estos métodos de cálculo nos permiten también obtenerlas integrales de funciones que conozcamos en forma numérica (como sucesión de nímeros).

Por otro lado, si queremos calcular la integral de una función que tenemos en forma analíti-ca también lo podemos hacer utilizando la función de Python de uso general más eficiente esquad(func,a,b), que integra por cuadratura de Clenshaw-Curtis 1 una función de Pythonfunc() entre a y b. Consideremos como ejemplo el cálculo del área una semicircunferenciade radio unidad calculando la integral bajo la curva. Para ello definimos la función e integramosentre -1 y 1:

>>> # Definimos la funcion a integrar>>> def semicirculo(x):

return sqrt(1 - x**2)

# Integramos numéricamente entre -1 y +1>>> intg, err = integrate.quad(semicirculo, -1.0, 1.0)

# Comprobamos que la precisión en el resultado (el correcto es pi/2)>>> print((intg-0.5*pi)/(0.5*pi))6.5872821402755502e-14

La función quad() devuelve por defecto el valor de la integral, que en este caso vale 𝜋2

y unaestimación del error en el proceso de integración numérica. La función quad ofrece como salida,además del valor de la integral, una estimación del error que comete en el cálculo de la integral;este error lo calcula internamente y es debido al proceso empleado para el cálculo de la integralpero no debe confundirse con el cálculo del error relativo que podemos hacer sólo si conocemos elvalor exacto de la integral.

En Python los límites de integración también pueden ser +∞ o −∞ usando los string +Inf o-Inf; por ejemplo podemos calcular la integral (ver figura)

∫ 2

−22𝑒𝑥𝑝−𝑥2

5𝑑𝑥,

>>> def func1(x):return 2.0*exp(-x**2/5.0)

# integración entre -2 y +2>>> int1, err1 = integrate.quad(func1, -2, +2)>>> print(int1,err1)(6.294530963693763, 6.9883332051087914e-14)

Si ahora hacemos la misma integral pero desde −∞ hasta +∞ obtendremos toda el área bajo lacurva definida en el integrando:

# integración entre -infinito y +infinito>>> int2, err2 = integrate.quad(func1, -Inf, +Inf)

1 Para detalles, ver por ejemplo http://en.wikipedia.org/wiki/Clenshaw-Curtis_quadrature

130 Capítulo 12. Otras aplicaciones de Cálculo Numérico

Page 137: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

# y el resultado obtenido es:>>> print(int1,err1)(7.9266545952120211, 7.5246691415403668e-09)

Nótese la diferencia entre el resultado de ambas integrales así como la diferencia entre el errorestimado al calcularlas.

Es posible incluir varios parámetros a la función empleando el parámetro opcional args comouna tupla de parámetros (ver la ayuda de quad()). Por ejemplo, calculemos la integral siguiente:∫ 𝜋

0(𝑎 + 𝑏𝑠𝑒𝑛(𝑥))𝑑𝑥 para valores de a=0.2 y de b=1:

# Definimos la función a integrar, incluyendo parámetrosdef f2(x,a,b):

return a + b*sin(x)

# Definimos unos parámetros de entrada p y q (como a y b)p=0.2;q=1

# Integramos numéricamente, incluyendo parámetrosintegrate.quad(f2, 0, pi, args=(p,q))(2.6283185307179586, 2.9180197488520396e-14)

De esta forma pueden variarse los parámetros p y q de la función a voluntad.

12.2 Álgebra matricial

Los arrays bidimensionales de numpy pueden interpretarse como matrices, aunque en realidad losarrays, cuando se opera algebraicamente con ellos, no funcionan como estamos acostumbradoscon matrices. Por ejemplo el producto de dos arrays bidimensionales NxM se realiza elemento aelemento y no como un producto algebraico de matrices. Veamos unos ejemplos:

12.2. Álgebra matricial 131

Page 138: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

>>> # Dos arrays de 3 x 3>>> A = array([[3, 6, 7], [2, 6, 2], [10, 9, 1]])>>> B = array([[4, 5, 5], [8, 3, 4], [3, 11, 2]])

>>> print(A)[[ 3 6 7][ 2 6 2][10 9 1]]

>>> print(B)[[ 4 5 5][ 8 3 4][ 3 11 2]]

>>> # Producto entre estos arrays>>> print(A*B)[[12 30 35][16 18 8][30 99 2]]

que, como vemos da como resultado otro array con elementos que son el producto elemento aelemento de los arrays factores. Sin embargo numpy permite hacer el producto punto entre estosarrays que es similar (de hecho idéntico) al producto matricial de dos matrices con la funciónfunc:dot:

>>> # Producto entre los arrays como si fueran matrices>>> print(dot(A,B))[[ 81 110 53][ 62 50 38][115 88 88]]

No obstante, si en un problema determinado, se va a operar a menudo con matrices, es convenientedefinirlas como tales. Para ello, se usa el comando mat() de numpy(), que es una abreviaturade matrix. Un elemento matrix es idéntico a un array y se crea de igual manera o a partir dearrays, pero se comporta como una matriz:

>>> # Creación elemento matriz (igual que un array)>>> C = mat([[4, 5, 5], [8, 3, 4], [3, 11, 2]])>>> type(C)>>> <class 'numpy.core.defmatrix.matrix'>

También se pueden convertir arrays en matrices de la forma siguiente:

>>> # Conversión de array a matriz>>> A = mat(A)>>> type(A)>>> <class 'numpy.core.defmatrix.matrix'>

132 Capítulo 12. Otras aplicaciones de Cálculo Numérico

Page 139: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

>>> # Producto matricial>>> print(A*C)[[ 81 110 53][ 62 50 38][115 88 88]]

12.3 Operaciones básicas con matrices

La inversa de una matriz A es una matriz B tal que AB = I donde I es la llamada matrizidentidad que consiste en una matriz en la que los elementos en la diagonal son unos y son cerosen el resto. Normalmente B se denota como B = A−1 . En scipy, la inversa de una matriz de unarray numpy se puede calcular haciendo linalg.inv(A), o usando el método A.I si A es unamatriz. Por ejemplo, consideremos

A =

⎡⎣ 1 3 52 5 12 3 8

⎤⎦entonces:

A−1 =1

25

⎡⎣ −37 9 2214 2 −94 −3 1

⎤⎦ =

⎡⎣ −1.48 0.36 0.880.56 0.08 −0.360.16 −0.12 0.04

⎤⎦ .

este cálculo lo haríamos con scipy de la siguiente manera:

>>> A = mat([[1, 3, 5], [2, 5, 1], [2, 3, 8]])>>> Amatrix([[1, 3, 5],

[2, 5, 1],[2, 3, 8]])

>>> A.Imatrix([[-1.48, 0.36, 0.88],

[ 0.56, 0.08, -0.36],[ 0.16, -0.12, 0.04]])

>>> from scipy import linalg>>> linalg.inv(A)array([[-1.48, 0.36, 0.88],

[ 0.56, 0.08, -0.36],[ 0.16, -0.12, 0.04]])

12.3. Operaciones básicas con matrices 133

Page 140: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

12.4 Resolución de sistemas de ecuaciones lineales

Con Scipy es muy fácil resolver un sistema de ecuaciones empleando la funciónlinalg.solve(). Este comando tiene como parámetros de entrada la matriz y el vector detérminos independientes. Si la matriz es simétrica el proceso de cálculo se puede acelerar si seindica como parámetro. Supongamos que queremos resolver el siguiente sistema de ecuaciones:

𝑥 + 3𝑦 + 5𝑧 = 102𝑥 + 5𝑦 + 𝑧 = 82𝑥 + 3𝑦 + 8𝑧 = 3

Podemos encontrar la solución usando la matriz inversa:⎡⎣ 𝑥𝑦𝑧

⎤⎦ =

⎡⎣ 1 3 52 5 12 3 8

⎤⎦−1 ⎡⎣ 1083

⎤⎦ =1

25

⎡⎣ −23212919

⎤⎦ =

⎡⎣ −9.285.160.76

⎤⎦ .

Sin embargo, es mejor usar el comando linalg.solve ya que es más rápido y numéricamentemás estable, aunque en este caso el resultado es el mismo:

>>> A = mat('[1 3 5; 2 5 1; 2 3 8]') # Las filas se separan con→˓";"

>>> b = mat('[10;8;3]')>>> A.I*b # Usando la matriz inversamatrix([[-9.28],

[ 5.16],[ 0.76]])

>>> # Lo mismo, usando la funcion linalg.solve(A,b)>>> linalg.solve(A,b)

array([[-9.28],[ 5.16],[ 0.76]])

12.4.1 Cálculo del determinante

Supongamos que 𝑎𝑖𝑗 son los elementos de la matriz A y 𝑀𝑖𝑗 = |A𝑖𝑗| será el determinante de lamatriz que se obtiene elimiando la i-esima fila y la j-esima columna de A. Entonces para cualquierfila i:

|A| =∑𝑗

(−1)𝑖+𝑗 𝑎𝑖𝑗𝑀𝑖𝑗.

Con Scipy el determinante se puede calcular con linalg.det. Por ejemplo, el determinante de lamatriz A

A =

⎡⎣ 1 3 52 5 12 3 8

⎤⎦134 Capítulo 12. Otras aplicaciones de Cálculo Numérico

Page 141: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

es

|A| = 1

5 13 8

− 3

2 12 8

+ 5

2 52 3

= 1 (5 · 8 − 3 · 1) − 3 (2 · 8 − 2 · 1) + 5 (2 · 3 − 2 · 5) = −25.

Con scipy se calcula tan fácilmente como:

>>> A = mat([[1, 3, 5], [2, 5, 1], [2, 3, 8]])>>> linalg.det(A)-25.000000000000004

12.5 Ejercicios

1. Calcular numéricamente las siguientes integrales

2𝜋

∫ 1

0

𝑥3√

1 + 9𝑥4 𝑑𝑥

∫ 2𝜋

0

𝑒−𝑥 sin (10𝑥) 𝑑𝑥

2. Comprobar las siguientes integrales calculándolas numéricamente:

∫ 1

0

𝑒−𝑥2

𝑑𝑥 = 0.746

∫ 4

0

𝑑𝑥

1 + 𝑥2= tan−1 (4) = 1.3258

∫ 2𝜋

0

𝑑𝑥

2 + cos 𝑥=

2𝜋√3

= 3.627

3. Calcular numéricamente el área más pequeña comprendida entre un círculo 𝑥2 + 𝑦2 = 25 yla recta x=3.

4. Escribir un programa en el que dibujen la función 𝑙𝑛𝑥1−𝑥

en el intervalo [0,5]. Calcular elárea bajo de la figura formada por los ejes OX, OY y esta curva en el intervalo [0,1]. Suresultado exacto es −𝜋2/6. Calcular los errores absoluto y relativo con el que se ha obtenidoel resultado, dando sólo las cifras significativas.

5. Crear una función que calcule numéricamente la siguiente integral admitiendo parámetrosde entrada m y n:

𝜋

∫ 1

0

𝑥𝑚 − 𝑥𝑛

ln𝑥𝑑𝑥 = ln

𝑚 + 1

𝑛 + 1

6. Las leyes de Kirchhoff de circuitos, indican que la suma de los voltajes en cada malla deun circuito es igual a la suma de las resistencias multiplicadas por la corriente que circulapor ellas, es decir

∑𝑉 =

∑𝑅𝐼 , que no es más que la ley de Ohm generalizada y que las

12.5. Ejercicios 135

Page 142: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

corrientes en los nodos se conserva, es decir,∑

𝐼𝑒𝑛𝑡𝑟𝑎𝑛 =∑

𝐼𝑠𝑎𝑙𝑒𝑛. Utilizando las leyes deKirchhoff crear un sistema de ecuaciones para el siguinte circuito y resolverlo numéricamen-te para conocer cada una de las corrientes que circulan por él.

7. Resolver el sistema AX=B donde:

A =

⎡⎢⎢⎣1 3 5 72 −1 3 50 0 2 5−2 −6 −6 1

⎤⎥⎥⎦ 𝑦 B =

⎡⎢⎢⎣1234

⎤⎥⎥⎦8. Utilice las leyes de Kirchhoff para conocer las corrientes que circulan por este circuito,

sabiendo que V1 = 7.5 V, V2 = 5.4 V y las resistencias valen 6.7, 2.3, 9.0, 1.0 y 5.6 Ω.

136 Capítulo 12. Otras aplicaciones de Cálculo Numérico

Page 143: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

CAPÍTULO 13

Apéndice A: Recursos informáticos para el curso

13.1 El sistema operativo

Cualquier sistema operativo se puede utilizar para el análisis de datos y computación científica engeneral, aunque en ambientes científicos y técnicos GNU/Linux es muy empleado y será nuestrosistema operativo de referencia. En las aulas de informática de la facultad utilizamos Bardinux, ladistribución Linux de la Universidad de la Laguna, que junto con Ubuntu, una de las distribucionesLinux más populares, son las que recomendamos y se pueden descargar gratuitamente de sus sitiosweb.

Si utilizas MS Windows en cualquier versión, puedes crear una partición en tu ordenador para queéste tenga ambos sistemas operativos, aunque hay que recordar que no es indispensable usar Linux.Esta opción no es posible para los usuarios de Mac, aunque el MacOS es un sistema operativosimilar a Linux por lo que no aportaría tanto.

Existe la opción de usar una máquina virtual para instalar en Windows o Mac una distribución deLinux, pero no es recomendable porque se hace muy pesado para el ordenador y la idea es tenerun sistema en que trabajar habitualmente.

13.2 El lenguaje de programación

Existen literalmente cientos de lenguajes de programación, pero sólo algunos son adecuados para elanálisis interactivo de datos. En los últimos años, los más usados son Matlab, IDL o Mathematica,que son programas con licencia privada (o sea que hay que comprar) pensados para uso científico yen ingeniería. Por otro lado, Python es un lenguaje interactivo de uso general publicado en códigoabierto (open source, compatible con licencia GPL) que es muy usado en ciencia y tecnología,siendo una alternativa más flexible y completa que los anteriores lenguajes.

Ventajas de Python

Lenguaje de código abierto y gratuito para todos los sistemas operativos.

137

Page 144: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

Es de uso general, no solo científico.

Fácil de usar y con una enorme comunidad de usuarios.

Desventajas de Python

Módulos (funcionalidades) específicos a instalar por separado.

Existen varios módulos para hacer lo mismo.

La documentación está dispersa.

Python es hoy en día uno de los cinco lenguajes de programación más usados, muy fácil de apren-der y muy polivalente, ya que tiene amplio uso en prácticamente todos los campos de ciencia,ingeniería e informática.

13.3 Python y módulos científicos para Python

Ya que Python es un lenguaje de uso general, existen funcionalidades para prácticamente cualquierproyecto o actividad. Aunque la instalación de Python ya viene con gran cantidad de funcionali-dades o módulos, para trabajos específicos como el análisis científico de datos, son necesariosmódulos adicionales. Para este curso usaremos los módulos científicos en Python más populares,que es necesario instalar además del propio Python.

Los módulos básicos que usaremos son los siguientes:

Scipy/Numpy - Paquete científico y numérico básico.

Matplotlib - Librería gráfica para gráficos 2D.

ipython - No es un módulo de Python, sino una consola avanzada, que usaremos en lugar dela de estándar de Python

13.3.1 Python para Linux

Si usas Linux, Python ya viene instalado y sólo tienes que instalar los módulos adicionales usandoel administrador de paquetes de tu distribución. La manera más fácil instalar software en Linuxes usar la consola de comandos. Para distribuciones basadas en Debian como Ubuntu o Bardinux,basta ejecutar lo siguiente en una consola:

japp@paquito:~$ sudo apt-get install python-scipyjapp@paquito:~$ sudo apt-get install python-matplotlibjapp@paquito:~$ sudo apt-get install ipython

El comando sudo te permite ejecutar un comando como superusuario o administrador del orde-nador (necesario para instalar), por lo que te pedirá la contraseña de administrador e instalará los

138 Capítulo 13. Apéndice A: Recursos informáticos para el curso

Page 145: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

paquetes de Python, scipy (y numpy, porque lo necesita) y matplotlib y la consola avanzadaipython.

Otra opción para instalar en Ubuntu o Bardinux es usar el instalardor gráfico, que sueler estar enla opción Sistema del menú de inicio. Ahí basta con buscar los paquetes necesarios e instalarlos.

13.3.2 Python en Windows o Mac

Tanto en Windows como en Mac es posible instalar Python y luego instalar los módulos científicosnecesarios, aunque hay varios proyectos que hacen esto por nosotros, es decir, instalar Python ytodos los módulos científicos en un paso. El proyecto más completo y recomendado es Anaconda ,un software que reúne Python y gran cantidad de módulos. Basta descargar la versión de Anaconda- Python 2.7 para el sistema operativo que usemos y seguir las instrucciones.

Veremos que tenemos la opción de usar dos versiones distintas, Python 2.7 o Python 3.5, y aunquepodemos emplear cualquiera y no hay gran diferencia entre ambas, es recomendable usar por ahoraPython 2.7 ya que es el que viene por defecto en Linux y Mac y de esta manera todos usaremos lamisma versión.

13.4 Editores de texto

Además del uso de Python interactivamente por terminal de comandos, también necesitaremoshacer programas ejecutables, por lo que necesitaremos un editor de texto/código adecuado. Existenmuchas opciones para todos los sistemas operativos y suelen todos venir con alguno útil, aunque anosotros nos interesa un editor sencillo que de destaque con colores el código y ayude a la edición.

13.4.1 Editores para Linux

Gedit: Editor por defecto para escritorios Gnome (como Ubuntu). Simple pero muy funcio-nal.

Kedit: Editor por defecto para escritorios KDE (como Bardinux). Muy similar a Gedit.

Kate: Pensado para programadores, muy completo y con muchas herramientas para la edi-ción de código.

Spyder: Entorno de desarrollo y análisis de datos. Ideal para manipular datos de manerainteractiva y pensado para científicos, aunque algo complejo para nuestro curso.

Si usas Linux, probablemente ya tengas instalado alguno de estos editores, si no, utiliza el admi-nistrador de paquetes de tu distribución. También puedes instalar programas usando la terminal decomandos de Linux:

13.4. Editores de texto 139

Page 146: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

sudo apt-get install kate # Si usas Ubuntu, Kubuntu o Bardinux→˓(te pregunta contraseña de administrador)

yum install kate # Si usas Fedora. Debes hacerlo como→˓root.

13.4.2 Editores para Mac

En Mac existen varias buenas opciones también. Mac OSX incluye por defecto un editor de texto,llamado TextEdit.app que se puede utilizar para editar código, aunque es muy limitado. Reco-mendamos alguna de las siguientes opciones:

Spyder. Entorno de desarrollo y análisis de datos. Ideal para manipular datos de manerainteractiva y pensado para científicos. Está incluído en Python-Anaconda.

TextWrangler. Editor de texto sencillo de caracter general.

13.4.3 Editores para Windows

Windows incluye por defecto dos editores de texto, el Notepad y Wordpad o similares. El primeroes demasiado sencillo y el segundo está más orientado a escribir documentos en lugar de progra-mas, por lo que no recomendamos usar ninguno de los dos. En su lugar existen buenas opciones:

Spyder.: Entorno de desarrollo y análisis de datos con Python. Ideal para manipular datos demanera interactiva y pensado para científicos. Está incluído en Python-Anaconda.

Notepad++. Editor muy completo y para muchos lenguajes de programación.

13.5 Más documentación y bibliografía

Python es un lenguaje de programación muy completo y con extensa documentación, pero convie-ne tener a mano algunas guías:

Python Scientific Lecture Notes. Completo curso de Python científico; Incluye algunos temasavanzados. En inglés.

Introducción a la programación con Python, Andrés Marzal, Isabel Gracia y Pedro GarcíaSevilla, Universitat Jaume I (2014). Guía de programación muy completa y detallada, aunqueorientada a estudiantes de informática.

Python para todos, Raúl González Duque. Buen libro de introducción de Python, aunque noincluye paquetes científicos.

140 Capítulo 13. Apéndice A: Recursos informáticos para el curso

Page 147: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

Think Python - How to Think Like a Computer Scientist, Allen Downey – Otra buena guíade introducción a Python. En inglés.

Documentación oficial (sólo de consulta)

Tutorial oficial de Python - http://docs.python.org/tutorial/

Documentación de Scipy y Numpy - http://docs.scipy.org/doc/

Documentación de Matplotlib - http://matplotlib.sourceforge.net/contents.html

Documentación de Ipython - http://ipython.scipy.org/doc/stable/html/

13.5. Más documentación y bibliografía 141

Page 148: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

142 Capítulo 13. Apéndice A: Recursos informáticos para el curso

Page 149: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

CAPÍTULO 14

Apéndice B: El sistema operativo GNU/Linux

El sistema operativo es el programa principal de un ordenador y se emplea para ofrecer al usuariofuncionalidades básicas para interactuar con él. Además de controlar los dispositivos de entraday salida como teclado, monitor, etc. en el sistema operativo, se ejecutan otros programas paratareas más específicas como procesadores de texto, hojas de cálculo o navegadores para Internet.Aunque el mercado de ordenadores personales está dominado principalmente por el sistema ope-rativo Windows, existen otros que se emplean en campos específicos. En ciencia e ingeniería, seemplea tradicionalmente el sistema UNIX y existe mucho software científico y técnico para estaplataforma y sus variantes. El los últimos años, ha ganado popularidad el sistema GNU/Linux (osimplemente Linux), que se originó a finales de los años ochenta y principios de los noventa comoun sistema operativo libre y de código abierto inspirado en UNIX y muy similar a éste. Actual-mente, Linux [#linux_] se usa ampliamente en ambientes académicos y técnicos, y su licencia decódigo abierto facilita su uso libre para estudiantes e investigadores.

GNU/Linux es un proyecto en el que participan voluntarios y empresas de todo el mundo y comocualquiera puede participar en él, es muy amplio y configurable. En realidad, lo que habitualmen-te se conoce como Linux es su kernel o núcleo con funcionalidades principales y junto con élfuncionan gran variedad de programas complementarios como interfases gráficos, utilidades pa-ra administrar el sistema y programas en general. Esta variedad de opciones hace que no existaun único Linux, sino varias distribuciones con distintas características, generalmente similares.Aunque existen decenas de distribuciones, hay algunas especialmente populares, como Ubuntu,Fedora o SuSE. Para este curso usaremos la distribución de Linux de la Universidad de La Laguna,Bardinux, que se basa a su vez en la distribución Kubuntu.

14.1 Empezando con Linux: el escritorio de trabajo

Linux es un sistema multiusuario, por lo que requiere una cuenta de usuario y su contraseña paraentrar en el sistema y en él cada usuario posee una zona de trabajo reservada con una configuraciónpropia única. Para empezar, entra en el sistema escribiendo tu nombre de usuario y contraseña. Unavez dentro, verás un escritorio de trabajo similar al de la Figura 1, en el que se reconocen variaszonas.

143

Page 150: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

Figura 14.1: Escritorio de Bardinux 3.2.

La barra horizontal inferior es la barra de tareas y aplicaciones, desde donde se accede a los pro-gramas presionando el botón de la esquina inferior izquierda (menú de aplicaciones). Desde elmenú de aplicaciones podemos ver los programas disponibles en el ordenador, organizados porcategorías. Para este curso, utilizaremos básicamente el navegador Firefox, que se encuentra en lacategoría Internet y también un editor de texto (no procesador de textos gráfico) como Kate. Enla pestaña “Máquina” al lado de Aplicaciones hay un icono de acceso al directorio personal denuestro usuario. En general, lo más práctico es buscar el programa deseado en el buscador, en laparte superior del menú.

14.2 Trabajando con la consola de Linux. Directorios yFicheros.

Aunque gracias al interfaz gráfico de Linux (el que usa Bardinux se llama KDE) podemos hacerprácticamente cualquier operación con el ordenador de manera gráfica como con Windows o Mac,para muchos trabajos conviene saber cómo hacerlos manualmente en lugar de usar la interfazgráfico. Para ello usaremos la terminal de comandos, que no es más que un programa en el queescribimos órdenes o comandos al ordenador. Aunque esto puede parecer anticuado, en cuantose conoce un poco cómo funciona a menudo se trabaja de forma más rápida y directa con ellay además es indispensable para ciertos trabajos. Para iniciar una terminal, hay que ir al menú deaplicaciones en la sección Sistema, donde está la aplicación Konsole (o buscarlo en el buscador);al ejecutarlo aparecerá una ventana como la de la Figura 3.

144 Capítulo 14. Apéndice B: El sistema operativo GNU/Linux

Page 151: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

Figura 14.2: Pantalla de la teminal de comandos Konsole.

Una vez lanzada la terminal de comandos, ésta está lista para recibir instrucciones. En ella veremosuna pantalla en negro (u otro color, según la configuración). La única línea que aparece en ella esla línea de comandos o “Prompt” en inglés, que indica el nombre del usuario y el de la máquina,separados por una arroba. En el ejemplo anterior vemos:

japp@paquito:~$

lo que el usuario es “japp” trabajando en el ordenador paquito. Al iniciar la terminal, el lugar detrabajo por defecto es nuestro directorio personal, normalmente llamado home, que es lo que indicael símbolo “~” a la derecha del indicador, antes del signo de dólar ($). Podemos comprobar queestamos ahí ejecutando el comando pwd, que nos indica nuestro lugar de trabajo:

japp@paquito:~$ pwd/home/jappjapp@paquito:~$

Vemos que nos devuelve una línea con nuestro directorio de trabajo actual /home/japp, y regresaal prompt. Podemos ver el contenido de nuestro directorio y cualquier otro usado el comando ls:

Figura 14.3: Listado del contenido de un directorio en la terminal de comandos usando ls.

14.2. Trabajando con la consola de Linux. Directorios y Ficheros. 145

Page 152: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

Generalmente los comandos de Linux tienen varias opciones que cambian su funcionalidad; porejemplo, para ver un listado más completo del directorio, usamos la opción -l del comando ls:

Figura 14.4: Listado detallado del contenido de un directorio en la terminal de comandos usandols -l.

Ahora vemos un fichero o directorio por línea, cuyo nombre aparece a la derecha de todo. A laizquierda aparecen unos caracteres del tipo “drwxr-xr-x” que se refieren a los permisos de accesoal fichero, que veremos más adelante. Después se muestra el usuario y grupo al que pertenecen losficheros, que en el ejemplo de arriba es “japp” para ambos. La siguiente columna indica el tamañoen bytes del fichero y finalmente se muestra la fecha y hora de su creación.

Desde la terminal podemos crear un fichero o ejecutar cualquier programa. Podemos, por ejemplo,lanzar el editor de texto kwrite o cualquier otro (kate, p.e.) y crear un fichero de texto. :

japp@paquito:~$ kate prueba.txt &

Vemos que ahora aparece el nuevo fichero de texto, con un tamaño y fecha de creación distintos.Nótese que el primer carácter de la tabla de permisos de cada fichero es “d”, excepto para prue-ba.txt. La “d” indica que es un directorio y por tanto todos los documentos en el listado anteriorson directorios, excepto el fichero de texto que acabamos de crear.

Podemos crear nuestro propio directorio usando el comando mkdir:

japp@paquito:~$ mkdir practicas_16-septiembre-2011

y entramos en él cambiando de directorio con el comando cd:

japp@paquito:~$ cd practicas_16-septiembre-2011japp@paquito:~/practicas_16-septiembre-2011$ pwd/home/japp/practicas_16-septiembre-2011japp@paquito:~$

Fíjate que el prompt ha cambiado y ahora muestra el nuevo directorio; comprobamos que esta-mos en él usado pwd nuevamente. Para regresar al directorio anterior, podemos hacerlo con cd/home/japp o bien bajando un nivel de directorio con cd ... Aquí ”..” (dos puntos seguidos)es una abreviatura que se refiere al directorio anterior. Igualmente, como el símbolo “~” es unaabreviatura de nuestro home, podemos ir a él estemos donde estemos escribiendo cd ~ o inclusocd solamente.

146 Capítulo 14. Apéndice B: El sistema operativo GNU/Linux

Page 153: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

Linux tiene una estructura de directorio cuyo raíz o directorio base es */* y en él están otros di-rectorios del sistema, como el home. Podemos ver su contenido haciendo ls -l / en la terminal.Verás que el propietario de todos los ficheros del directorio raíz o del sistema es el usuario root.El usuario root es el administrador del sistema y tiene privilegios especiales en el ordenador y sususuarios; un usuario normal no puede por tanto alterar estos ficheros ni instalar nuevos programas,sólo el usuario root puede hacerlo.

14.3 Copiando, moviendo y renombrando ficheros

Cualquier fichero o directorio se puede copiar con el comando cp, indicando las rutas de los fiche-ros de origen y destino:

japp@paquito:~$ cp prueba.txt prueba2.txtjapp@paquito:~$ cp /home/japp/prueba.txt /home/japp/Documentos/prueba.

→˓txt

En el primer ejemplo se hace una copia del mismo fichero en el mismo directorio con otro nombrey en el segundo se copia el fichero a otro directorio con el mismo nombre. Como es habitual, sepuede indicar la ruta (o path, en inglés) como en el segundo ejemplo o usar direcciones relativascomo en el primero. En caso de querer cambiar el nombre de un fichero o su localización, seemplea el comando mv, cuyo uso es idéntico a cp, sólo que mv reemplaza un fichero o directoriopor otro en lugar de copiarlo:

japp@paquito:~$ mv prueba.txt prueba2.txtjapp@paquito:~$ mv /home/japp/prueba.txt /home/japp/Documentos/prueba.

→˓txt

en el primer ejemplo se cambia el nombre del fichero prueba.txt por prueba2.txt, en el segun-do se mueve el prueba.txt del home al directorio Documentos/, conservando el mismo nombre.Fíjate que “cambiar de nombre” y “mover” son exactamente lo mismo. En realidad, para Linuxel nombre de un fichero es su ruta completa. Por ejemplo, nuestro fichero prueba.txt, para Li-nux en realidad se llama /home/japp/prueba.txt y al “moverlo” realmente lo renombramos a /ho-me/japp/Documentos/prueba.txt y de ahí la equivalencia entre mover y renombrar.

Para eliminar un fichero, puedes hacerlo con rm, pero debes usarlo con precaución, porque no hayvuelta atrás y el borrado es permanente. Para borrar un directorio vacío, se puede hacer con rmdir,pero daría un error si éste no está vacío. Si queremos borrar un directorio no vacío, podemos usarel comando rm de manera recursiva con la opción -r:

Si no recuerdas cómo se usa un comando o las opciones que tiene, recuerda que para cualquiercomando de Linux tienes acceso a ayuda escribiendo comando correspondiente con la opción--help. Para una descripción más detallada, se puede acceder a su manual escribiendo man<comando>:

14.3. Copiando, moviendo y renombrando ficheros 147

Page 154: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

japp@paquito:~$ cp --help # Ayuda breve del comando cpjapp@paquito:~$ man cp # Manual del comando cp

14.4 Caracteres comodín

Para muchos comandos de la terminal que implican tratar con ficheros de nombre similar, podemosutilizar caracteres comodín “*”, ”?” y “[ ]”. El * reemplaza a cualquier cadena de caracteres, porejemplo:

japp@paquito:~$ ls pr*

listará todos los ficheros que empiezan por “pr”. El ”?” reemplaza cualquier carácter, pero única-mente uno, por ejemplo:

japp@paquito:~$ ls prueba?.txt

listaría prueba1.txt, prueba2.txt, pruebaA.txt de haberlos, pero no prueba1.mp3 ni prueba.txt. Fi-nalmente se pueden poner caracteres en corchetes para cubrir un rango de caracteres:

japp@paquito:~$ ls prueba[2-4].txt

que listaría ficheros prueba2.txt, prueba3.txt y prueba4.txt si existiesen.

14.5 Trabajando con ficheros de texto

La terminal de Linux tiene muchos comandos y utilidades para trabajar con ficheros de texto nor-males. Por ejemplo, aunque habitualmente el resultado de un comando cualquiera se muestra porpantalla, como un listado con ls, podemos pasar este resultado a un fichero de texto en lugar de lapantalla poniendo “> nombre_del_fichero.txt” después del comando:

japp@paquito:~$ ls /usr/* > listado_usr.txt

el comando anterior lista todos los ficheros que hay en el directorio del sistema /usr, pero en lugarde mostrar el listado por pantalla lo copia a un fichero llamado “listado_usr.txt”. La extensión.txt que indica que es un fichero de texto no es obligatoria, pero sí muy recomendable. El ficheroresultante es un fichero de texto normal que podemos abrir por ejemplo con kwrite o kate, que soneditores de texto. Podemos echar un vistazo rápido a un fichero de texto como este con el comandocat que nos muestra contenido del fichero en la pantalla. Como vemos que se trata de un ficherobastante largo y difícil manipular, podemos usar el comando more que nos muestra su contenidopasando pantallas con la barra espaciadora y del que podemos salir con la letra “q”. Un comandomás completo es less que nos muestra el contenido como more pero permitiéndonos avanzar yretroceder en el fichero usando las flechas de dirección del teclado:

148 Capítulo 14. Apéndice B: El sistema operativo GNU/Linux

Page 155: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

recuerda que puedes ver más opciones de los comando con la opción --help.

Como curiosidad útil, podemos encadenar varios comandos con una “tubería” o “pipeline” usan-do el carácter “|” entre comandos. Por ejemplo, si queremos ver las diez primeras líneas del direc-torio /usr/ sin grabarlo a un fichero, basta con hacer:

japp@paquito:~$ ls /usr/* | head

aquí lo primero que hace la terminal es crear el listado como antes, pero en lugar de mostrarlo porpantalla, envía el resultado al comando head, que lo procesa y nos muestra el resultado. Podemosusar el comando wc para contar las líneas, palabras y caracteres de un fichero:

japp@paquito:~$ wc listado_usr.txt5987 5973 77062 listado_usr.txt

los números que aparecen como resultado indican el número de líneas (5987), palabras (5973) ycaracteres (77062) del fichero. Si queremos buscar un fichero en un directorio o en todo el disco,usamos find con la notación siguiente:

find /home/japp -name "*.txt"---------- ----------

| || |V V

ruta patrón de búsqueda

este ejemplo busca todos los ficheros de extensión “txt” en /home/japp. Para buscar en todos losdirectorios:

japp@paquito:~$ find * -name "*.txt"

Al igual que ficheros sueltos, podemos buscar dentro de ficheros de texto. Eso lo podemos hacercon “grep <cadena de búsqueda> <fichero>”. Por ejemplo, el comando:

japp@paquito:~$ grep ark listado_usr.txt

busca dentro de listado_usr.txt todas las cadenas “ark” que hay e imprime por pantalla la línea enla que está.

14.6 El sistema de usuarios y permisos de Linux

Puesto que Linux es un sistema multiusuario con usuarios independientes, los ficheros que crea ensu home son suyos y únicamente suyos. El usuario puede administrar el acceso a sus documentoscambiando su tabla de permisos, que se muestra cuando se hace un listado largo. Por ejemplo, parael fichero de texto que creamos:

14.6. El sistema de usuarios y permisos de Linux 149

Page 156: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

japp@paquito:~$ ls -l prueba.txtjapp@paquito:~$ -rw-r--r-- 1 japp japp 0 2009-09-14 19:47 prueba.txt

como dijimos, el primer carácter es “d” si es un directorio y “-” si no lo es, el resto se agrupan entres grupos de caracteres “rwx” que se refieren al dueño del fichero, su grupo y a todos los demás ylas letras rwx indican permisos de lectura (r), escritura (w) y ejecución (x). Esto se entiende mejorcon unos ejemplos:

-rw-r--r-- El dueño tiene permisos para leer y escribir elfichero, el resto solo para ver.

-rw-rw-r-- El dueño y su grupo tienen permisos para leer yescribir, el resto solo para ver.

-r-------- El dueño sólo puede leer el fichero, el restono pueden verlo ni modificarlo.

Por defecto, los ficheros se crean con permisos -rw-r–r–, y estos se pueden modificar con el co-mando chmod. Su modo de empleo es chmod <XXX> <nombre del fichero> en el que <XXX>son tres números de 0 a 7 que son los permisos para el usuario, grupo y el resto. Cada valor de Xes la suma cada permiso: X=Lectura+Escritura+Ejecución; los valores de los permisos se asignande la siguiente manera:

0 ningún permiso1 permiso de ejecución2 permiso de escritura3 permisos de escritura y ejecución4 permiso de lectura5 permisos de lectura y de ejecución6 permisos de lectura y de escritura7 todos los permisos

mejor vemos esto con unos ejemplos:

# Permiso de lectura y escritura para el usuario y de lectura para los→˓demás

japp@paquito:~$ chmod 644 prueba.txt# Todos los permisos para el usuario, ninguno para el restojapp@paquito:~$ chmod 700 prueba.txt# El usuario y su grupo pueden leerlo, el resto no tiene ningún permisojapp@paquito:~$ chmod 440 prueba.txt

Una manera alternativa de cambiar permisos es asignarlos por tipo de categoría de usuario (usuario,grupo o resto) usando esta notación:

chmod [ugoa][+-][rwx] <fichero>

donde [ugoa] se refiere a al usuario (u), grupo (g), otros (o) o todos (a), el [+-] para dar (+) o quitar(-) el permiso y [rwx] y indica qué permiso cambiar. Aquí van unos ejemplos:

150 Capítulo 14. Apéndice B: El sistema operativo GNU/Linux

Page 157: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

# Da al usuario permiso de escriturajapp@paquito:~$ chmod u+w prueba.txt# Da a todos permisos de lecturajapp@paquito:~$ chmod a+r prueba.txt# Quita al resto de usuarios permisos de ejecuciónjapp@paquito:~$ chmod o-x prueba.txt

Si se desea cambiar los permisos a un directorio completo, debe incluirse la opción -R (recursivo)después del comando. Por ejemplo, el comando:

japp@paquito:~$ chmod -R a+r Documentos/

da permisos de lectura al directorio Documentos y a todo su contenido. Estas combinaciones sonmás que suficientes para desenvolverse con permisos de archivos.

14.7 Empaquetando y comprimiendo ficheros

A menudo tenemos que guardar y transportar ficheros de un ordenador a otro o como copias deseguridad y en ocasiones los ficheros pueden ser muchos o muy grandes. Se puede comprimir unfichero con el comando gzip y descomprimirlo con gunzip:

japp@paquito:~$ gzip listado_usr.txt # Comprime listado_usr.txt a→˓listado_usr.txt.gz

japp@paquito:~$ gunzip listado_usr.txt # Descomprime listado_usr.txt.→˓gz

Fíjate que gzip sólo comprime ficheros sueltos. Si queremos comprimir varios ficheros o un direc-torio, debemos empaquetar los ficheros antes con el comando tar:

# Empaqueta el directorio Documentos/ y su contenido al fichero→˓Documentos.tar

japp@paquito:~$ tar -cf Documentos.tar Documentos/

# Comprime el fichero Documentos.tar a Documentos.tar.gzjapp@paquito:~$ gzip Documentos.tar

En realidad la operación anterior se puede hacer en una sola línea con tar y las opciones adecua-das:

# Empaqueta y comprime el directorio Documentos/ al fichero Documentos.→˓tar.gz

japp@paquito:~$ tar -czf Documentos.tar.gz Documentos/# Descomprime y extrae Documentos.tar.gzjapp@paquito:~$ tar -xzf Documentos.tar.gz

14.7. Empaquetando y comprimiendo ficheros 151

Page 158: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

Hay que notar que aquí usamos -c para empaquetar y -x para desempaquetar; la z se refiere aque el tar debe comprimirse con gzip y la f indica que después viene el nombre del fichero conel que empaquetará.

Otro comando similar que empaqueta y comprime al mismo tiempo es zip:

japp@paquito:~$ zip -r Documentos/ Documentos.zipjapp@paquito:~$ unzip Documentos.zip

en donde hemos comprimido el directorio Documentos con todo su contenido (opción -r) en unarchivo llamado Documentos.zip. Para recuperarlo usamos el comando unzip.

14.8 Ejercicios

1. Genere un listado de todos los archivos que se encuentren en el directorio /usr/bin que em-piecen con “a” y que en algún lugar tengan una “o”.

2. ¿Qué comando usaría para borrar todos los ficheros que empiecen por un número y quetengan extensión mp3 que estén en el directorio Música/ del home?

3. Lista el contenido del home ordenado por fecha de creación (averigua la opción adecuada).

4. ¿Cómo listaría el contenido de /usr/* que se muestre página a página como hace el comandomore?

5. En el directorio /bin del sistema hay programas ejecutables ¿cómo contaría cuántos hay?

6. En el home hay un fichero oculto llamado konqueror, que utiliza el administrador gráfico dearchivos. Encuentre la ruta o path de ese fichero. Los ficheros ocultos tienen un ”.” delantedel nombre.

7. ¿Cual es la diferencia entre intentar borrar un fichero 700 y otro 400, siendo ambos delpropietario? Comprobarlo en la terminal.

8. Cambie los permisos a prueba.txt de manera que absolutamente todos puedan leerlo y mo-dificarlo.

9. El fichero anterior, prueba.txt, tiene ahora permisos de lectura y escritura para todos. Hacambiado de opinión y ahora quiere que el resto (el grupo y otros) sólo pueda leerlo sinmodificarlo, ¿cómo les quitaría esos permisos?

10. El fichero del sistema /proc/meminfo, es un fichero de texto que contiene información sobrela memoria del ordenador. La memoria total está indicada dentro del fichero con la pala-bra MemTotal (fíjese en las mayúsculas). ¿Cómo buscarías esa cadena de texto o palabra?¿Cuánta memoria tiene el ordenador en kB?

11. El comando “ps -ux” muestra una lista larga de procesos que se están ejecutando en el orde-nador. Muestra sólo los 10 últimos.

152 Capítulo 14. Apéndice B: El sistema operativo GNU/Linux

Page 159: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

12. El comando “history” muestra por pantalla todos los comandos ejecutados en la consola; sipones “history 25”, muestra los últimos 25, etc. En lugar de mostrarlos por pantalla, pásalosa un fichero llamado comandos_[tu_nombre].txt en el home.

13. Empaqueta y comprime todos los ficheros de texto en tu directorio de trabajo (con extensióntxt), incluyendo el fichero de textos con la lista de comandos, en un fichero tar.gz.

14.8. Ejercicios 153

Page 160: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

154 Capítulo 14. Apéndice B: El sistema operativo GNU/Linux

Page 161: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

CAPÍTULO 15

Apéndice C: La distribución Gaussiana

La distribución gaussiana puede considerarse como el límite de una distribución binomial cuando elnúmero posible de resultados es infinitamente grande, tan grande que podemos hablar del continuo(números reales). Es decir, la variable en una distribución gaussiana puede tomar valores entre −∞y +∞, contrariamente a lo que sucedía con las distribuciones anteriores. No obstante, en la prácticael número de realizaciones de cualquier suceso es siempre limitado y es importante saber si esteconjunto finito de realizaciones (la distribución subyacente) se puede aproximar a (o representarpor) una distribución gaussiana. En estos casos podemos utilizar sus propiedades para analizar ladistribución subyacente de nuestro conjunto limitado de datos

Tiene multitud de aplicaciones en todos los campos puesto que parece que sea la preferida por lanaturaleza como modelo para los experimentos y observaciones, de tal suerte que suele llamár-sela también distribución normal. Aunque fue obtenida primero por Demoivre en 1733 cuandoestudiaba un problema de lanzamiento de monedas, fue más tarde obtenida independientementepor Laplace y por Gauss; de ahí lo de distribución gaussiana, que fue aplicada inicialmente a loserrores accidentales (o aleatorios) en medidas astronómicas y de otros experimentos científicos.

La forma de una distribución gaussiana (la famosa “Campana de Gauss”) es la siguiente:

℘𝐺(𝑥, 𝑥, 𝜎) =1√2𝜋𝜎

exp[−(𝑥− 𝑥)2

2𝜎2]

y al ser una función continua consideramos esta función como una densidad de probabilidad; esdecir que la probabilidad de que una observación se encuentre entre 𝑥 y 𝑥+𝑑𝑥 será ℘𝐺(𝑥, 𝑥, 𝜎)𝑑𝑥.Nótese que 𝑥 es la media y 𝜎 es la desviación estándar de la distribución.

15.1 Propiedades, media y varianza

En el caso de la distribución normal la media y la desviación estándar entran directamente en sudefinición. Podemos fijarnos y comprobar que entre las propiedades de la distribución normal estánlas siguientes:

155

Page 162: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

∫∞−∞ ℘𝐺(𝑥, 𝑥, 𝜎)𝑑𝑥 = 1; esto correspondería a la probabilidad de obtener una observación

cualquiera,

la probabilidad de que una observación esté comprendida en el intervalo [𝑥1, 𝑥2] se calcularíahaciendo

∫ 𝑥2

𝑥1℘𝐺(𝑥, 𝑥, 𝜎) 𝑑𝑥,

la función es simétrica respecto de 𝑥, la media,

℘𝐺(𝑥± 𝜎) = 𝑒−1/2√2𝜋𝜎

, donde 𝜎 es la desviación estándar,

la probabilidad de que una observación caiga dentro del rango 𝑥 ± 𝜎 es de 0.6827 y dentrode 𝑥± 3𝜎 es de 0.9973.

15.2 Población, Muestra y Error estándar de la media

Es bastante usual ver a un conjunto de observaciones o resultados de experimentos como unamuestra finita del conjunto infinito, o mucho más grande que podríamos obtener, que se conocecomo población. La cuestión es si esta muestra finita, de (𝑛) datos, se puede representar por unadistribución normal. Si es así, deberíamos ser capaces de encontrar los parámetros de la distribu-ción normal (media y distribución estándar de la muestra) que ajustan mejor al conjunto de datos.Estos parámetros encontrados mediante en la muestra o conjunto, ¿serán la media y la desviaciónestándar de toda la población?. La respuesta es que, en general, no coincidirán exactamente, aun-que si 𝑛 es lo suficientemente grande se aproximarán mucho. Visto desde otro ángulo: si tenemosotro conjunto de datos (otra muestra) del mismo experimento u observación con el mismo númerode elementos (𝑛), su media y desviación estándar, ¿serán iguales a la primera?. En principio no,aunque se parecerán cada vez más a medida que 𝑛 crezca.

Puede demostrarse matemáticamente que la distribución de medias y la de desviaciones estándarque obtendríamos al repetir el experimento muchas veces (con lo que tendríamos muchas muestras)es que también es una distribución gaussiana. Su media es igual a la media verdadera de toda lapoblación mientras que su desviación estándar es 𝜎/

√𝑛 donde 𝑛 es el número de datos de cada

muestra y 𝜎 la desviación estándar de toda la población.

Por lo tanto, cuando trabajamos con un conjunto de datos cuya distribución subyacente es unadistribución normal de media 𝑥 es apropiado escribir la media encontrada como: 𝑥±𝜎/

√𝑛, donde

lo escrito detrás del símbolo ± es el llamado error estándar de la media. De forma similar, elerror estándar de la desviación estándar es 𝜎/

√2𝑛, de forma que la desviación estándar la podemos

escribir como: 𝜎(1 ± 1/√

2𝑛).

15.3 La media pesada y su error estándar

Supongamos que tenemos una muestra de 𝑛 medidas obtenidas de un experimento u observación decualquier fenómeno físico 𝑥𝑖 cuya distribución subyacente es una distribución normal. Además,supongamos que algunas medidas se han obtenido con mejores precisiones 𝜎𝑖 que otras. Puede

156 Capítulo 15. Apéndice C: La distribución Gaussiana

Page 163: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

mostrarse (Gauss fue quien primero lo demostró) que la media ponderada con los pesos 𝑤𝑖 = 1/𝜎2𝑖

es el valor más probable de la medida que buscamos (de la distribución subyacente).

Es decir, como se dice en [6.1]:

𝑥 =

∑𝑖 𝑥𝑖/𝜎

2𝑖∑

𝑖 1/𝜎2𝑖

(15.1)

y de [6.2] la desviación estándar de la distribución alrededor de esta media será:

𝜎2 =

∑𝑖(𝑥𝑖 − 𝑥)2/𝜎2

𝑖∑𝑖 1/𝜎2

𝑖

(15.2)

y de la sección anterior podemos concluir que el error asociado al valor medio será:

𝜖 =

√∑𝑖(𝑥𝑖 − 𝑥)2/𝜎2

𝑖

(𝑛− 1)∑

𝑖 1/𝜎2𝑖

(15.3)

Démonos cuenta que si todas las medidas están tomadas con igual precisión esta definición sereduce a:

𝜖 =

√∑𝑖(𝑥𝑖 − 𝑥)2

𝑛(𝑛− 1)(15.4)

15.4 Consistencia interna y externa de un conjunto demedidas

Acabamos de ver que si el peso 𝑤𝑖 asignado a una medida 𝑥𝑖 es igual (o proporcional) a 1/𝜖2𝑖 ,donde 𝜖𝑖 es el error estándar de 𝑥𝑖, entonces el error estándar de la media pesada 𝑥 podemoscalcularlo como en la ecuación (15.3). A esta forma de obtener el error estándar le llamaremos elerror externo, para distinguirlo de otra forma de calcularlo, el error interno que obtendremos acontinuación.

En efecto, el error estándar de la media pesada también podemos obtenerla de otra forma. En elcapítulo II de esta serie hemos definido como calcular la propagación de errores en una funcióncualquiera:

𝜎2𝑥 =

∑𝑖

[𝜎2𝑖

(𝜕𝑥

𝜕𝑥𝑖

)2]

(15.5)

En este caso si lo aplicamos a la definición de 𝑥 podemos llegar a que el resultado final es:

𝜎2𝑥 =

1∑𝑖 (1/𝜎2

𝑖 )(15.6)

15.4. Consistencia interna y externa de un conjunto de medidas 157

Page 164: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

Las expresiones (15.3) (error externo, 𝜖𝑒𝑥𝑡) y (15.6) (error interno, , 𝜖𝑖𝑛𝑡) de la media son muy dife-rentes aparentemente, pero ambas deberian coincidir. Fijémonos que mientras la segunda expresión((15.6)) depende tan sólo de los errores estándar de cada una de las observaciones o medidas, laprimera expresión ((15.3)) depende también de las diferencias entre ellas y el valor medio.

Su cociente será:

𝑍 =𝜖𝑒𝑥𝑡𝜖𝑖𝑛𝑡

=

[∑𝑖(𝑥𝑖 − 𝑥)2/𝜖2𝑖

(𝑛− 1)

]1/2(15.7)

y debería ser igual a 1. Para muestras de medidas tomadas de una población normal infinita puededemostrarse que 𝜖𝑖𝑛𝑡 y 𝜖𝑒𝑥𝑡 deben coincidir o, mejor dicho, siendo estrictos 𝑍 debe ser 1 con un errorestándar 1/

√2(𝑛− 1). Si esto es así podemos decir que las observaciones pueden considerarse

consistentes. En este caso, lo mejor es considerar el mayor de los dos errores como el error estándarde la media pesada y el resultado de las observaciones podemos tomarlo como 𝑥±𝑚𝑎𝑥(𝜖𝑖𝑛𝑡, 𝜖𝑒𝑥𝑡).

En la práctica, generalmente encontrarán que esto no es así y que 𝑍 no coincidirá con la unidad.Pero esto no debería sorprenderles ya que, por un lado depende fuertemente de los valores de 𝜖𝑖;algunos de ellos pueden ser considerablemente imprecisos o inexactos. Por otro lado, 𝑍 tambiéndepende de lo que se separan las medidas de su valor medio (

∑𝑖(𝑥𝑖 − 𝑥)2) y por lo tanto pueden

estar afectados de errores sistemáticos. Por tanto, el conjunto de observaciones no es consistente.

Si el resultado difiere significativamente de la unidad podemos concluir que tenemos errores siste-máticos presentes en el conjunto de observaciones. Si 𝑍 ≫ 1, podemos tener errores sistemáticosentre las observaciones o podemos haber subestimado los errores en cada observación, o ambos;deberemos repasar el experimento viendo las posibles fuentes de error sistemático que han podidopasar por alto y/o deberemos asignar nuevos errores a cada una de las observaciones. Esto últimoserá más bien arbitrario dependiendo inevitablemente del juicio y conocimiento del científico delas condiciones experimentales. El caso contrario, el de 𝑍 ≪ 1 es mucho menos frecuente y sedebería a una sobreestimación de los errores de cada una de las observaciones.

15.5 Bibliografía

Estas notas se han redactado con ayuda de otros trabajos que merecen ser citados:

1. Topping, J. (1972, 4th ed.). Errors of Observation and their Treatment, Science paperbacks,Chapman & Hall Ed.

2. Fernández Soto, A. (2005). Técnicas experimentales y Análisis de Datos I. Proyecto Docen-te. OA - UVEG

15.6 Ejercicios

1. El control de calidad de una fábrica que produce bombillas eléctricas comprueba 1000, ele-gidas al azar, cada mes. Encuentran que el número de horas de encendido de las bombillas

158 Capítulo 15. Apéndice C: La distribución Gaussiana

Page 165: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

sigue una distribución normal con una vida media de 950 horas de encendido y una des-viación estándar de 150 horas. Se pide que calculen el número de bombillas que podemosesperar que tengan: a) menos de 650 horas de encendido, b) entre 800 y 1100 horas y c) entre1100 y 1250 horas.

2. Los diámetros de las esporas del lycopodium pueden medirse por métodos interferométricos.Los resultados de uno de estos experimentos son los siguientes:

k * diametro (cm) 14 15 16 17 18 19 20 21 22 23numero de esporas 1 1 8 24 48 58 35 16 8 1

donde k=5880. Se pide:

Encuentren el diámetro medio de las esporas y su error estándar y

representen los resultados por un histograma y dibujen encima la correspondiente distribu-ción normal.

1. Los ficheros dssn2002.txt y dssn2007.txt contienen las observaciones del índice 𝐼𝑚 que esproporcional al número de manchas solares en un determinado día del año 2002 o 2007. Lascolumnas de la tabla contienen: 1) el día correspondiente, 2) el día en fracción de año, 3) el𝐼𝑚 en toda la superficie visible solar, 4) el 𝐼𝑚 solo en el hemisferio norte visible y 5) el 𝐼𝑚solo en el hemisferio sur visible. Para uno cualquiera de los dos ficheros, se pide que:

hagan un histograma de estas observaciones (rango de 0 a 180),

calculen el promedio y la desviación éstandar anual, para cada mes, para cada uno de loshemisferios y el global,

ofrezcan, como salida del programa, un fichero con una tabla en la que las columnas sean: 1)mes, 2) promedio, 3) error, 4) desviación éstandar; de la 5) a la 7) lo mismo que las 2), 3) y4) pero sólo para el hemisferio norte; de la 8) a la 10) igual que antes pero para el hemisferiosur. En la últimafila obtengan los valores para todo el año.

1. El experimento MarkI, situado en el Observatorio de El Teide viene observando, desde 1975,la velocidad de la superficie solar respecto del observatorio por un método de dispersiónresonante usando el efecto Doppler. Una de sus medidas consiste en la velocidad hacia elrojo debido a la diferencia entre el campo gravitatorio en el Sol y en el Observatorio. En losficheros file2008.txt y similares, hay tablas en las que se muestran los resultados obtenidosen diferentes días del año. Se pide que:

calculen el promedio de la velocidad y su error así como la varianza, utilizando como pesosestadísticos la inversa del cuadrado del error en cada una de las medidas,

calculen los mismos parámetros pero con igual peso estadístico para todas las medidas,

repitan los cálculos anteriores eliminando del conjunto de medidas aquéllas que difieran dela media en más de tres veces la desviación estándar.

15.6. Ejercicios 159

Page 166: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

160 Capítulo 15. Apéndice C: La distribución Gaussiana

Page 167: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

CAPÍTULO 16

Apéndice D: Cálculo Simbólico

En el capítulo anterior vimos cómo es posible usar técnicas numéricas para resolver problemas ma-temáticos complejos, como integrales, sistemas de ecuaciones, etc. En Física e ingeniería es prác-ticamente más habitual resolver ciertos problemas numéricamente debido a la dificultad o inclusoimposibilidad de hacerlo analíticamente. Sin embargo, a menudo necesitamos resolver problemasmetemáticos de manera analítica necesariamente, en ocasiones pueden ser problemas complejos.Por ejemplo, es posible que para obtener la primitiva cierta integral recorramos a técnicas de subs-titución, integración por partes, etc. o bien tengremos que consultar un libro de tablas de integrales.

Afortunadamente, los ordenadores también nos pueden ayudar al cálculo analítico y Python poseepara ello módulo Sympy. Sympy es una librería de cálculo simbólico que permite resolver analí-ticamente múltiples problemas matemáticos, entre ellos derivadas, integrales, series numéricas olímites. Veamos algunas posibilidades de esta librería.

16.1 Introducción a Sympy

Al igual que en Python existen varios tipos de datos numéricos como enteros (int), decimales (float)o booleanos (bool: True, False, etc.), Sympy posee tres tipos de datos propios: Real, Rational e In-teger, es decir, números reales, racionales y enteros. Esto quiere decir que Rational(1,2) representa1/2, Rational(5,2) a 5/2, etc. y no 0.5 o 2.5.

>>> from sympy import *>>> a = Rational(1,2)

>>> a1/2

>>> a*21

>>> Rational(2)**50/Rational(10)**501/88817841970012523233890533447265625

161

Page 168: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

También existen algunas constantes especiales, como el número e o 𝜋, si embargo éstos se tratancon símbolos y no tienen un valor númerico determinado. Eso quiere decir que no se puede obtenerun valor numérico de una operación usando el pi de Sympy, como (1+pi), como lo haríamos conel de Numpy, que es numérico:

>>> pi**2pi**2

>>> pi.evalf()3.14159265358979

>>> (pi+exp(1)).evalf()5.85987448204884

como se ve, sin embargo, se puede usar el método evalf() para evaluar una expresión para tener unvalor en punto flotante (float). Es posible incluso representar matemáticamente el símbolo infinito,mediante oo:

>>> oo > 99999True>>> oo + 1oo

Para hacer operaciones simbólicas hay que definir explícitamente los símbolos que vamos a usar,que serán en general las variables y otros elementos de nuestras ecuaciones:

>>> x = Symbol('x')>>> y = Symbol('y')

Y ahora ya podemos manipularlos como queramos:

>>> x+y+x-y2*x

>>> (x+y)**2(x + y)**2

>>> ((x+y)**2).expand()2*x*y + x**2 + y**2

Es posible hacer una substitución de variables usando subs(viejo,nuevo):

>>> ((x+y)**2).subs(x, 1)(1 + y)**2

162 Capítulo 16. Apéndice D: Cálculo Simbólico

Page 169: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

>>> ((x+y)**2).subs(x, y)4*y**2

16.2 Operaciones algebraicas

Podemos usar apart(expr,x) para hacer una descomposición parcial de fracciones:

>>> 1/( (x+2)*(x+1) )1

---------------(2 + x)*(1 + x)

>>> apart(1/( (x+2)*(x+1) ), x)1 1

------- - --------1 + x 2 + x

>>> (x+1)/(x-1)-(1 + x)---------1 - x

>>> apart((x+1)/(x-1), x)2

1 - ------1 - x

Para unirlas, podemos usar together(expr,x):

>>> together(1/x + 1/y + 1/z)x*y + x*z + y*z---------------

x*y*z

>>> together(apart((x+1)/(x-1), x), x)-1 - x-------1 - x

>>> together(apart(1/( (x+2)*(x+1) ), x), x)1

---------------(2 + x)*(1 + x)

16.2. Operaciones algebraicas 163

Page 170: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

16.3 Cálculo de límites

Sympy puede calcular límites usando la función limit() con la siguientesintaxis: limit(función,variable, punto), lo que calcularía el limite de f(x) cuando variable -> punto::

>>> x = Symbol("x")>>> limit(sin(x)/x, x, 0)1

es posible incluso usar límites infinitos:

>>> limit(x, x, oo)oo

>>> limit(1/x, x, oo)0

>>> limit(x**x, x, 0)1

16.4 Cálculo de derivadas

La función de Sympy para calcular la derivada de cualquier función es diff(func,var). Vea-mos algunos ejemplos:

>>> x = Symbol('x')>>> diff(sin(x), x)cos(x)>>> diff(sin(2*x), x)2*cos(2*x)

>>> diff(tan(x), x)1 + tan(x)**2

Puedes comprobar que es correcto calculando el límite:

>>> limit((tan(x+y)-tan(x))/y, y, 0)1 + tan(x)**2

También se pueden calcular derivadas de orden superior indicando el orden de la derivada comoun tercer parámetro opcional de la función diff():

>>> diff(sin(2*x), x, 1) # Derivada de orden 12*cos(2*x)

164 Capítulo 16. Apéndice D: Cálculo Simbólico

Page 171: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

>>> diff(sin(2*x), x, 2) # Derivada de orden 2-4*sin(2*x)

>>> diff(sin(2*x), x, 3) # Derivada de orden 3-8*cos(2*x)

16.5 Expansión de series

Para la expansión de series se aplica el método .series(var,punto,orden) a la serie quese desea expandir:

>>> cos(x).series(x, 0, 10)1 - x**2/2 + x**4/24 - x**6/720 + x**8/40320 + O(x**10)>>> (1/cos(x)).series(x, 0, 10)1 + x**2/2 + 5*x**4/24 + 61*x**6/720 + 277*x**8/8064 + O(x**10)

e = 1/(x + y)s = e.series(x, 0, 5)

pprint(s)

La función pprint de Sympy imprime el resultado de manera más legible:

4 3 21 x x x x- + -- - -- + -- - -- + O(x**5)y 5 4 3 2

y y y y

16.6 Integración

La integración definida e indefinida de funciones es una de las funcionalidades más interesantes deSympy. Veamos algunos ejemplos:

>>> integrate(6*x**5, x)x**6>>> integrate(sin(x), x)-cos(x)>>> integrate(log(x), x)-x + x*log(x)

16.5. Expansión de series 165

Page 172: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

>>> integrate(2*x + sinh(x), x)cosh(x) + x**2

También con funciones especiales:

>>> integrate(exp(-x**2)*erf(x), x)pi**(1/2)*erf(x)**2/4

También es posible calcular integrales definidas:

>>> integrate(x**3, (x, -1, 1))0>>> integrate(sin(x), (x, 0, pi/2))1>>> integrate(cos(x), (x, -pi/2, pi/2))2

Y también integrales impropias:

>>> integrate(exp(-x), (x, 0, oo))1>>> integrate(log(x), (x, 0, 1))-1

Algunas integrales definidas complejas es necesario definirlas como objeto Integral() y luegoevaluarlas con el método evalf():

>>> integ = Integral(sin(x)**2/x**2, (x, 0, oo))>>> integ.evalf()>>> 1.6

16.7 Ecuaciones algebraicas y álgebra lineal

Otra sorprendente utilidad de Sympy es su capacidad para resolver sistemas de ecuaciones fácil-mente:

>>> # Una ecuación, resolver x>>> solve(x**4 - 1, x)[I, 1, -1, -I]

# Sistema de dos ecuaciones. Resuelve x e y>>> solve([x + 5*y - 2, -3*x + 6*y - 15], [x, y])y: 1, x: -3

166 Capítulo 16. Apéndice D: Cálculo Simbólico

Page 173: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

Sympy tiene su propio tipo de dato Matriz, independiente del de Numpy/Scipy. Con él se puedendefinir matrices numéricas o simbólicas y operar con ellas:

>>> # Matriz identidad 2x2>>> Matrix([[1,0], [0,1]])[1, 0][0, 1]

>>> x = Symbol('x')>>> y = Symbol('y')>>> A = Matrix([[1,x], [y,1]])>>> A[1, x][y, 1]

>>> A**2[1 + x*y, 2*x][ 2*y, 1 + x*y]

Existen otros constructores similares a arrays de Numpy pero para matrices:

>>> # Matrices de unos>>> ones((5,5))[1, 1, 1, 1, 1][1, 1, 1, 1, 1][1, 1, 1, 1, 1][1, 1, 1, 1, 1][1, 1, 1, 1, 1]

>>> # Matriz identidad>>> eye(3)[1, 0, 0][0, 1, 0][0, 0, 1]

Hay que fijarse en que muchas de las funciones anteriores ya existen en Numpy con el mismonombre (ones(), eye(), etc.), por lo que si queremos usar ambas debemos importar los paquetescon otro nombre, Por ejemplo:

>>> import numpy as np>>> from sympy import *

>>> # Funcion eye de Sympy (matriz)>>> eye(3)[1, 0, 0][0, 1, 0][0, 0, 1]

16.7. Ecuaciones algebraicas y álgebra lineal 167

Page 174: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

>>> # Funcion eye de Numpy (array)>>> np.eye(3)array([[ 1., 0., 0.],

[ 0., 1., 0.],[ 0., 0., 1.]])

>>> # Matriz de Numpy>>> np.matrix(np.eye(3))matrix([[ 1., 0., 0.],

[ 0., 1., 0.],[ 0., 0., 1.]])

Es posible operar entre ellas, salvo que las matrices de Numpy no pueden operar con símbolos,algo que se puede hacer con Sympy. La selección de elementos de matrices de Sympy se hace demanera idéntica a los arrays o matrices de Numpy:

>>> # Multiplico la matriz identidad por x>>> x = Symbol('x')>>> M = eye(3) * x>>> M[x, 0, 0][0, x, 0][0, 0, x]

>>> # Substituyo x por 4 en la matriz>>> M.subs(x, 4)[4, 0, 0][0, 4, 0][0, 0, 4]

>>> # Substituyo la variable x por y en la matriz>>> y = Symbol('y')>>> M.subs(x, y)[y, 0, 0][0, y, 0][0, 0, y]

>>> def f(x): return 1.5*x**2....:

>>> eye(3).applyfunc(f)[1.5, 0, 0][ 0, 1.5, 0][ 0, 0, 1.5]

168 Capítulo 16. Apéndice D: Cálculo Simbólico

Page 175: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

>>> M = Matrix(( [1, 2, 3], [3, 6, 2], [2, 0, 1] ))

>>> # Determinante de la matriz>>> M.det()-28# Matriz inversa>>> M.inv()[-3/14, 1/14, 1/2][-1/28, 5/28, -1/4][ 3/7, -1/7, 0]

>>> # Substituyo algunos elementos de la matriz>>> M[1,2] = x>>> M[2,1] = 2*x>>> M[1,1] = sqrt(x)>>> M[1, 2, 3][3, x**(1/2), x][2, 2*x, 1]

Podemos resolver un sistema de ecuaciones por el método LU:

>>> # Matriz 3x3>>> A = Matrix([ [2, 3, 5], [3, 6, 2], [8, 3, 6] ])>>> # Matriz 1x3>>> x = Matrix(3,1,[3,7,5])>>> b = A*x>>> # Resuelvo el sistema por LU>>> soln = A.LUsolve(b)>>> soln[3][7][5]

16.8 Ejercicios

1. Calcular la derivada de 𝑥3 arccos(2𝑥

).

2. Calcular la derivada segunda de 𝑒−𝑥 log (𝑥).

3. Calcular los diez primeros elementos de la serie:∑𝑛=0

1

(1 + 𝑛)5/2.

16.8. Ejercicios 169

Page 176: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

4. Calcular la siguiente integral:

𝑦(𝑥) =

∫cos (𝑥)

sin (𝑥)𝑑𝑥.

Evaluar el resultado para x=0.5.

5. Calcular la integral siguiente y evaluar su valor en x=1.5:

𝑦(𝑥) =

∫1

1 + 𝑒𝑥𝑑𝑥

6. Comprobar las siguientes integrales definidas:∫ 1

0

1√log(1𝑥

)𝑑𝑥 =√𝜋

∫ 1

0

𝑥 log (1 + 𝑥) 𝑑𝑥 =1

4

∫ ∞

0

𝑒−𝑥 sin (𝑥) 𝑑𝑥 =1

2

170 Capítulo 16. Apéndice D: Cálculo Simbólico

Page 177: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

CAPÍTULO 17

Historial de cambios

17.1 Revisión 3.2 - Septiembre 2016

Revisión general de erratas y tipográficos.

Actualización de Apéndice sobre Recursos Informáticos

Capítulo sobre cálculo simbólico movido a apéndice

17.2 Revisión 3.1 - Septiembre 2015

Error en ejercicio control de flujo. Suma = 3/4 en lugar de 1/2

17.3 Versión 3.0 - Septiembre 2014

Revisión general de erratas y tipográficos.

Explicado iterador enumerate() en control de flujo.

Ampliado el apartado Estructura de un programa o script y normas de escritura incluyendonormas de escritura de código en Python en “Programas ejecutables”

Dibujo sobre indices en Python

Añadidas y explicadas funciones insert() y append() de numpy.

Reescrito párrafo de introducción a numpy.

Corrección de errores debido a cambios de versión de Python (help de print) e IPython (runen lugar de -lp).

Actualización del apéndice sobre recursos para el curso, sobre cómo instalar Linux y Python.

171

Page 178: Curso de Computación Científica · 2018-07-11 · Curso de Computación Científica, Publicación 2016-09-15 Curso de Computación del 1º del Grado de Física. Universidad de

Curso de Computación Científica, Publicación 2016-09-15

César Esteban en la lista de autores

17.4 Versión 2.5 - Noviembre 2013

Ampliación de lectura de ficheros con numpy

Revisión capítulo de gráficos

Cambio de orden de ejercicios de capitulo de graficos

Introduccion de capitulo sobre probabilidad y aleatorios

Cambio de orden de numpy y estadística

Capítulo de Distribución normal, como apendice C

172 Capítulo 17. Historial de cambios