Tema 6 - Números reales y enteros. Arrays
Más tipos de datos...
- 6.1 Sufijos para cada tipo de número
- 6.2 DEFINT y DEFREAL
- 6.3 Arrays: Matrices y vectores
- 6.4 READ y DATA
- 6.5 Ejercicio propuesto
- 6.6 Puntualizando...
6.1 Sufijos para cada tipo de número
Por ahora hemos supuesto que teníamos variables en las que podíamos almacenar números y cadenas de texto, y que para distinguir las cadenas de texto les añadíamos un símbolo especial (un sufijo), el símbolo del dólar ($).
Eso no es cierto del todo. Realmente, el Basic de los CPC permite distinguir números reales (con cifras decimales) y números enteros (sin decimales). ¿Por qué? Porque los números reales son mucho más lentos de manipular que los números enteros, así que sería preferible usar números enteros siempre que no necesitemos cifras decimales, y así ganaremos en velocidad para nuestros programas.
Si no indicamos lo contrario, se considera que un número es real. La primera forma de decir que queremos que sea un número entero es usando el sufijo "tanto por ciento" (%):
A% = 5
También podemos decir expresamente que queremos que un número sea real, usando como sufijo un símbolo de admiración (!):
coseno! = COS(45)
6.2 DEFINT y DEFREAL
El problema de usar sufijos es que el programa puede resultar algo más difícil de leer que si las variables tuvieran nombres "normales". Tenemos una alternativa: decir que queremos que una variable sea entera o real usando la orden DEFINT o DEFREAL, por ejemplo con DEFINT A o con DEFREAL COSENO.
Siendo estrictos, cuando usamos DEFINT o DEFREAL, hacemos que sean enteras (o reales) todas las variables que empiezan por la letra (o letras) que indiquemos. Un uso muy frecuente es decir que queremos que todas las variables de nuestro programa sean enteras, haciendo:
DEFINT a-z
También podemos indicar sólo varias iniciales, separadas por comas:
DEFINT i,k
6.3 Arrays: Matrices y vectores
Si tenemos varios datos del mismo tipo (por ejemplo, las edades de 20 personas), podemos usar una estructura de datos que los guarde todos juntos. Este tipo de datos se suele llamar un "vector", y se declara usando la palabra DIM e indicando el número de elementos entre paréntesis:
DIM edad%(20)
En este caso, tenemos un vector llamado "edad", que puede guardar 20 datos enteros. El primer dato será "edad(1)" y el último será "edad(20)". Por ejemplo, podemos dar valores a varios datos y mostrarlos así:
edad%(1)=25
edad%(2)=27
PRINT edad%(1)
(*) Nota: esto no es cierto del todo. Al final del tema tienes más detalles de qué ocurre realmente.
También nos puede interesar tener "más de una dimensión", por ejemplo notas de alumnos, que están agrupados en 4 clases, cada una de ellas con 20 alumnos:
DIM nota(4,20)
Que se usaría de forma similar:
nota(3,5) = 7.4
Esto es lo que se suele llamar una "matriz de 2 dimensiones". En inglés se suele la palabra "array", que es frecuente encontrar sin traducir.
Podemos usar más de dos dimensiones si lo necesitásemos: DIM nombre$(10,5,40)
Si terminamos de usar los datos de un array y nos interesa liberar la memoria que estaba ocupando, lo podemos conseguir con la palabra ERASE:
ERASE nota
6.4 READ y DATA
Si tenemos que dar datos a un array muy grande, es muy incómodo hacerlo uno por uno con
edad(1)=25
edad(2)=27
edad(3)=26
...
Por eso, existe otra alternativa más razonable: con la orden DATA indicamos la serie de datos (en una línea o en varias), y los leeremos con la orden READ, así:
10 DIM edad(12): FOR i = 1 TO 12: READ edad(i): NEXT
20 DATA 25,27,26,25,25,28
30 DATA 24,27,26,26,25,27
Un último detalle: si manejamos varios arrays en nuestro programa, o un array que tenga datos cambiantes, quizá nos interese tener varias zonas de datos distintas, y leer de una u otra según nos apetezca. Eso se puede conseguir con la orden RESTORE, a la que le indicamos a partir de qué linea queremos comenzar a leer (si no indica nada con RESTORE, se comenzará por la primera línea):
10 RESTORE 40
20 DIM edad(6): FOR i = 1 TO 6: READ edad(i): NEXT
30 DATA 25,27,26,25,25,28
40 DATA 24,27,26,26,25,27
(En el ejemplo anterior, los datos de la línea 30 no se leen)
6.5 Ejercicio propuesto
Dibujar cuatro círculos, de cuatro formas distintas, para comprobar velocidades:
- Un círculo punto a punto, como se vio en el apartado anterior.
- Un círculo punto a punto, pero usando números enteros.
- Un círculo hecho con 36 líneas (avanzando 10 grados cada vez).
- Un círculo hecho con 36 líneas, en el que los valores de los senos y los cosenos estén precalculados en una tabla.
Para medir tiempos se puede usar TIME, que dice el tiempo que hace que se encendió el CPC, en unidades de 1/300 de segundo.
La apariencia podría ser como ésta:
Se puede ver que, en mis pruebas, dibujar los 360 puntos lleva más de 12 segundos (3879 unidades de tiempo); si se usa números enteros este programa no mejora sino que empeora ligeramente, porque esos números enteros hay que convertirlos a reales antes de calcular su seno y su coseno (una décima de segundo más, 3908); si avanzamos 10 grados cada vez, el círculo se ve casi idéntico, pero el programa es casi 10 veces más rápido (un segundo y medio, 431); si además tenemos los valores de los senos y cosenos precalculados usando números enteros, el círculo se dibuja otras 5 veces más rápido (83 unidades de tiempo, unas 35 veces más rápido que la rutina original)
6.6 Puntualizando...
Siendo estrictos, lo que hemos dicho de los arrays en los CPC no es totalmente cierto: si declaramos DIM dato(20), le estamos diciendo que queremos reservar espacio hasta el dato número 20... pero realmente se empieza a contar desde 0, luego tenemos "hueco" para guardar 21 datos, que serían dato(0), dato(1), ..., dato(19), dato(20). Aun así, mucha gente prefiere empezar a contar desde 1, para que el fuente sea más fácil de leer.
Otro detalle avanzado es que no hace falta declarar los arrays de 10 elementos o menos: podemos hacer "resultado(4) = 20" sin haber usado ningún DIM previamente. Eso sí, en cuanto hiciéramos algo como "resultado(11) = 30" obtendríamos un error de que estamos usando un "subíndice fuera de rango".