La sola idea de ser posesionario de algo que tiempo atrás se cotizaba en el orden de los millones de dólares hizo que hubiera una gran demanda para tales productos, la cual disminuyó con la introducción de las computadoras IBM y sus clones compatibles de bajo costo. En esas máquinas que operaban con sistemas operativos MS-DOS que estaban basadas en una “ventana de comandos”, Microsoft incluía como cortesía su propia versión del lenguaje BASIC (algo que eventualmente dejaría de hacer al migrar del entorno de las ventanas de comandos al entorno puramente gráfico de las ventanas Windows).
La introducción que será dada aquí recurrirá al conjunto de instrucciones más “universal” que pueda haber para el lenguaje BASIC. Esto trae la ventaja de que el lector, si así lo desea, puede llevar a cabo prácticas y pruebas con lo que se proporciona aquí recurriendo a uno de los muchos emuladores del lenguaje BASIC disponibles gratuitamente en Internet, ya sea descargando un programa ejecutable que sirva para elaborar programas en BASIC, o entrando en sitios que proporcionan emuladores que se pueden usar en la máquina mientras la máquina esté conectada a Internet.
En una computadora como la Tandy Color Computer que desde el momento en que se enciende está disponible para trabajar con un BASIC interactivo, después del mensaje típico de bienvenida se imprime en la primera línea el texto “OK” (que en inglés significa “Okey”, todo listo). Se agregará antes de continuar que existen disponibles en Internet varios emuladores de la Tandy Color Computer a los que podemos recurrir para estas prácticas. Si escribimos algo como lo siguiente (es importante que las dobles comillas aparezcan tal y como se muestran):
PRINT "HOLA, ME LLAMO ARMANDO"
y oprimimos la tecla de entrada [Enter], entonces la computadora responderá imprimiendo en una nueva línea:
HOLA, ME LLAMO ARMANDO
tras lo cual el cursor parpadeante será movido a la siguiente línea imprimiendo de nueva cuenta “OK” poniéndose a la espera de una nueva orden del usuario. En la pantalla del televisor, se ve algo como lo siguiente:
Tal y como lo especificamos, la computadora siguió nuestras instrucciones. Le dijimos con la orden de impresión PRINT que imprimera un mensaje específico en la pantalla, y eso fue lo que hizo.
Obsérvese que al usar el comando PRINT imprime todo lo que encuentra a su derecha entre las comillas dobles, incluídos los espacios en blanco. Es la única instancia en la cual los espacios en blanco no son ignorados por BASIC, en otros comandos de BASIC los espacios en blanco (e inclusive las líneas en blanco) son ignoradas y podemos meter cuantos espacios (y líneas) en blanco para darle mayor legibilidad a un programa.
Para experimentar con algo diferente, podemos escribir:
PRINT 2
y oprimir la tecla [Enter]. Tras esto, la pantalla tendrá el siguiente aspecto:
Obsérvese la diferencia. Cuando se le dió a la computadora la instrucción de “imprimir” el número 2, no se incluyeron las dobles comillas alrededor del número. Obsérvese también que todos los comandos en BASIC son especificados con letras mayúsculas, no hay letras minúsculas ni combinaciones de mayúsculas y minúsculas. Sin embargo, muchas versiones de BASIC permiten las letras minúsculas cuando son especificadas entre las dobles comillas de algo que será enviado a una impresora.
El lenguaje BASIC ve todo lo que escribimos como hileras de texto o como una expresión numérica (un número). Si lo que escribimos lo ponemos entre dobles comillas, es un texto, y la computadora lo imprime tal y como lo ve.
Podemos usar al BASIC en la computadora como una calculadora. Póngase y hágase lo siguiente:
PRINT 2 + 2 [Enter]
Tras esto, la pantalla tendrá el siguiente aspecto:
Procurando alguna versión de BASIC en Internet (hay muchas disponibles en la actualidad), el lector puede probar suerte con los siguientes ejemplos:
PRINT 10 - 5 [Enter]
5
OK
PRINT 10 * 10 [Enter]
100
OK
PRINT 100/10 [Enter]
10
OK
Los ejemplos que hemos visto llevan a cabo un procesamiento “inmediato”, el cual especifica que cualquier instrucción dada sea ejecutada “aquí mismo” sin ser almacenada para su uso posterior. Pero cualquier computadora puede hacer más que esto, puede recordar y reusar instrucciones, en lo que vienen siendo los “programas”. En rigor de verdad, la computadora no recuerda la instrucción, sino el lugar en el cual la instrucción es almacenada, y esto lo hacemos en BASIC con los “números de línea”. Un número de línea puede ser cualquier número entero positivo que no exceda el tope límite impuesto por el sistema (el cual puede ser, por ejemplo, 63999, ello depende de la máquina y el tipo de BASIC que se tenga instalado). Las siguientes líneas:
1 A$ = "LINEAS DE PROGRAMA"
100 PRINT A$
63999 PRINT "EL FINAL"
son todas líneas válidas.
Para quienes hayan leído las entradas previas relacionadas con programas ensambladores, los números de línea usados por los ensambladores podrían parecer tener cierta similitud con los números de línea usados por el lenguaje BASIC. Sin embargo, se trata de cosas muy diferentes. Mientras que en los programas ensambladores los números de línea son mera conveniencia puesta inclusive de manera automática por el mismo ensamblador, en BASIC los números de línea son imperativos y de hecho son indispensables para llevar a cabo las instrucciones de “salto”, y en este respecto los números de línea usados en BASIC tendrían un mayor parecido (funcionalmente hablando) con las “etiquetas” que corresponden al campo de símbolos que es el primer campo que está más a la izquierda en las convenciones usadas por los ensambladores.
Antes de escribir programas nuevos, se vuelve necesario borrar programas o datos que se tengan en la memoria. Hay tras maneras de lograrlo: (1) salir del programa o inclusive apagar la computadora según sea el caso (al apagar la computadora, todo lo que esté puesto en la memoria RAM se borra), (2) escribiendo otro programa usando los mismos números de línea (una nueva línea 15 reemplazará automáticamente una vieja línea 15, por ejemplo), y (3) usar un comando como NEW de un modo tan simple como:
NEW [Enter]
Estamos listos para escribir nuestro primer programa en BASIC. Para ello, tendremos que poner un número de línea. Escríbase y hágase primero lo siguiente:
10 PRINT "ESTE ES MI PRIMER PROGRAMA" [Enter]
Expándase el programa añadiendo una segunda línea al mismo:
20 PRINT "ESTA ES LA SEGUNDA LINEA" [Enter]
Ahora que hemos escrito un programa, ¿qué hacemos con él? Queremos que sea procesado por la computadora, para lo cual usamos un comando como RUN:
RUN [Enter]
Tras hacer esto, la pantalla mostrará lo siguiente:
ESTE ES MI PRIMER PROGRAMA
ESTA ES LA SEGUNDA LINEA
OK
Si queremos correr el programa a partir de cierta línea, simplemente escribimos el número de línea a partir de la cual queremos que corra el programa. En el caso de nuestro primer programa, si hacemos:
RUN 20
la pantalla mostrará:
ESTA ES LA SEGUNDA LINEA
OK
Hemos asentado ya que BASIC puede reconocer dos tipos de datos, datos numéricos y datos de hilera (de texto). Podemos asignar ambos tipos de datos a variables, creando así variables numéricas y variables de hilera. Como ejemplo de una variable numérica, hágase:
A = 5 [Enter]
La computadora “recuerda” esta asignación numérica. Para comprobarlo, trátese de “confundir” a la computadora escribiendo varias cosas tales como las instrucciones que vimos arriba al principio. Tras ello, hágase:
PRINT A [Enter]
La computadora responderá dejándonos lo siguiente en la pantalla:
PRINT A
5
En este ejemplo, A es la variable (porque su valor puede cambiar) y 5 es la constante porque su valor no cambia, es constante.
Para representar variables numéricas en BASIC, podemos usar cualquier combinación dos caracteres siempre y cuando el primer caracter sea una letra. El segundo caracter puede ser una letra o un dígito numérico. Aunque se pueden hacer variables de este modo con más de dos caracteres, muchas versiones de BASIC solo reconocen los primeros dos caracteres. De este modo, las siguientes variables numéricas son legales:
A1
AA
VARIABLE
Z
mientras que las siguientes variables numéricas son ilegales:
1A
80
3
La computadora permite que las variables sean usadas de muchas maneras. Para un ejemplo rápido, pruébese lo siguiente:
A = 5 [Enter]
B = 10 [Enter]
PRINT A + B [Enter]
La computadora responderá con lo siguiente:
15
OK
Podemos asignar datos de hilera a variables de la misma manera en la cual podemos asignar datos numéricos a variables. La única diferencia es que las variables de hilera deben terminar con un símbolo “$”. Por ejemplo:
A$ = "El castillo"
Cuando se hace lo siguiente:
PRINT A$
la computadora responderá imprimiendo:
El castillo
OK
Las variables de hilera pueden ser sumadas en una operación conocida en términos técnicos como concatenación (el encadenamiento de hileras sucesivas de texto). A modo de ejemplo, con el programa:
10 A$ = "El castillo"
20 B$ = "de"
30 C$ = "Chapultepec"
40 PRINT A$ + B$ + C$
se imprimirá lo siguiente cuando se ejecuta con el comando RUN:
El castillo de Chapultepec
Para la asignación de variables, y para darle un poco de mayor legibilidad a un programa, podemos usar el comando optativo LET cuya sintaxis es:
LET variable = constante
en donde variable puede ser una variable numérica o de hilera. De este modo:
LET A = 5
es lo mismo que:
A = 5
y para variables de hilera:
LET A$ = "VARIABLE DE HILERA"
es lo mismo que:
A$ = "VARIABLE DE HILERA"
Al final de un programa, podemos agregar el comando optativo END para dar por terminado el programa. Cuando la computadora encuentra este comando, detiene de inmediato la ejecución. Naturalmente, si no hay más instrucciones al final de un programa, la computadora detendrá de cualquier modo su ejecución, pero las buenas prácticas de programación dictan que los programas siempre sean terminados con el comando END. Cabe notar que en algunas versiones de BASIC se utiliza el comando STOP en lugar de END.
Puesto que en la formación de expresiones aritméticas toda la expresión se tiene que escribir en una línea, se pueden presentar ambigüedades. Para dividir A entre la suma de B y C, podríamos intentar escribir algo como lo siguiente:
A/B + C
Sin embargo, la computadora podría interpretar esto como la suma de A/B y C. Aunque es posible indagar las reglas que usa la computadora para darle sentido a una expresión matemática cuando hay ambigüedades, es mejor usar paréntesis para evitar problemas:
A/(B+C)
Cuando haya duda sobre la manera en la cual una expresión pueda ser interpretada, es mejor usar siempre paréntesis para fijar el orden de las evaluaciones.
La regla anterior no es algo exclusivo de BASIC. Se usa en muchos otros lenguajes de programación para fijar orden de prioridad en las operaciones.
En la mayoría de los sistemas, en la evaluación en BASIC de las expresiones matemáticas se usan las siguientes reglas de precedencia para llevar a cabo una desambigüación:
1) Las expresiones dentro de paréntesis siempre son evaluadas primero.
2) Dentro de un conjunto de paréntesis:
i) Toda exponenciación se ejecuta primero, de izquierda a derecha.
ii) Las multiplicaciones y divisiones se ejecutan después, de izquierda a derecha.
iii) Las sumas y restas se efectúan al final, de izquierda a derecha.
PROBLEMA: Decidir cuáles de las siguientes expresiones son ilegales o ambigüas:
(a) AB/C
(b) A+(B/C)*D
(c) (8+Z2)/-C
(d) 3X/D
(e) (Q+I)W9
(f) 3*(A/+8)
En cada caso se tiene:
(a) La expresión es ilegal si A es el nombre de una variable y B es el nombre de otra variable. Si la intención del programador era decir “multiplíquese A por B y divídase entre C”, debería de haber escrito:
(A*B)/C
(b) La expresión es legal, pero es ambigüa. Para estar seguro de que la computadora hará lo que uno quiere, más vale agregar algunos paréntesis:
(A+(B/C))*D
(c) La expresión puede ser legal o no, dependiendo de la instalación de BASIC que se esté utilizando. La constante numérica 6 precedida con el signo menos que la vuelve un número negativo está en conformidad con las reglas. Sin embargo, el hecho de que el operador de división (el símbolo diagonal) esté a un lado puede ocasionar un mensaje de error, puesto que el signo menos es usado no sólo para la representación de números negativos (representación unaria) sino también para denotar una substracción. Para evitar tal posibilidad, es mejor agregar un conjunto adicional de paréntesis:
(8+Z2)/(-6)
La regla general es evitar situaciones en las que haya dos operadores uno a un lado del otro.
(d) La expresión es ilegal. Si la intención del programador era decir 3 multiplicado por X y dividido entre D, debería de haber escrito:
(3*X)/D
(e) Mismo problema. La multiplicación debe ser indicada explícitamente:
(Q+I)*W9
(f) La expresión puede ser legal o no, dependiendo de la instalación de BASIC que se esté utilizando. La computadora puede ser confundida por el uso de dos operadores adyacentes. Para remediar esto, podemos remover el signo positivo por ser redundante, escribiendo simplemente 3*(A/8).
Podemos meter comentarios en cualquier parte de un programa BASIC precediendo el principio de una línea con el comando REM. En varias versiones de BASIC, el comando puede ser usado en el medio de una línea del programa siempre y cuando sea precedido por un colon “:”, como en el siguiente ejemplo:
10 REM PROGRAMA ARITMETICO
20 PRINT 10 + 5 :REM SUMA
30 PRINT 10 - 5 :REM RESTA
40 PRINT 10 / 5 :REM DIVISION
50 PRINT 10 * 5 :REM MULTIPLICACION
60 END
Otro comando que suele ser útil es el comando de “limpieza” CLS (Clear Screen) usado para borrar todo lo que haya en la imagen en la pantalla del monitor empezando con un espacio limpio.
Los programas dados arriba no son interactivos. Pero habrá ocasiones en las cuales se querrá obtener cierta información del usuario antes de proseguir adelante. Para tales ocasiones usamos el comando INPUT cuya sintaxis es la siguiente:
INPUT "mensaje"; variable
en donde mensaje es el mensaje de requisición “prompt” pidiéndole al usuario cierta información, y variable es una variable usada para almacenar variables de hilera o numéricas. Para ver cómo funciona dicho comando, pruébese el siguiente programa:
10 CLS
20 INPUT "ME DAS TU NOMBRE"; NOMBRE$
30 PRINT "HOLA "; NOMBRE
40 END
Al correr este programa con RUN, la pantalla después de haber sido limpiada con el comando CLS pondrá lo siguiente:
ME DAS TU NOMBRE?
El símbolo de interrogación es añadido automáticamente por la computadora puesto que sabe que INPUT implica una pregunta. Simplemente escribimos el nombre y oprimimos la tecla de entrada, por ejemplo:
ME DAS TU NOMBRE? ARMANDO [Enter]
Al hacer esto, se tendrá lo siguiente:
ME DAS TU NOMBRE? ARMANDO
HOLA ARMANDO
OK
Los números también pueden ser usados con INPUT. Pruébese lo siguiente:
10 CLS
20 INPUT "CUAL ES EL PRIMER NUMERO"; A
30 INPUT "QUE NUMERO LE QUIERES SUMAR"; B
40 C = A + B
50 PRINT "LA RESPUESTA ES "; C
60 END
Cuando se corre este programa, BASIC pide un primer número que tiene que ser proporcionado. Se proporciona el número y se oprime la tecla [Enter]. Hecho esto, la computadora pide un segundo número que se le quiera sumar al primero, repitiéndose el procedimiento, tras lo cual se proporciona la respuesta en la pantalla.
Podemos usar INPUT para formular más de una pregunta, como lo muestra el siguiente programa:
10 CLS
20 INPUT "CUAL ES TU NOMBRE Y TU EDAD (NOMBRE, EDAD)";NOMBRE$,EDAD
25 CLS
30 PRINT NOMBRE$ " TIENE UNA EDAD DE";EDAD
40 END
Cuando la computadora le pregunta al usuario:
CUAL ES TU NOMBRE Y TU EDAD (NOMBRE, EDAD)?
Se escribe algo como lo siguiente:
GABRIELA, 57 [Enter]
con lo cual la computadora responde del siguiente modo:
GABRIELA TIENE UNA EDAD DE 25
Hay dos cosas a resaltar en el programa anterior: (1) las variables de hilera y numéricas pueden ser “mezcladas” en la forma en que se ha mostrado, y (2) podemos usar un número de cosas variables en un enunciado INPUT.
Hasta este punto, hemos visto dos maneras de meter números a un programa:
1) Asignando variables a constantes (como en LET A = 8).
2) Usando el enunciado INPUT (como en INPUT A).
Hay una tercera manera de meter datos: con el enunciado DATA, el cual nos permite almacenar “datos” en un programa. Cuando queremos “leer” los datos que ya han sido almacenados previamente, usamos el enunciado READ. La sintaxis de DATA es la siguiente:
DATA dato, dato, dato, ...
en donde dato puede ser una constante numérica o de hilera. No se permiten expresiones aquí que tengan que ser evaluadas. Si el dato incluye comas o espacios en blanco o algún semicolon, hay que encapsularlos entre las dobles comillas. Cada dato tiene que ser seguido de una coma.
En lo que toca a READ, su sintaxis es la siguiente:
READ variable, variable, variable, ...
Las líneas DATA solo pueden ser leídas por un enunciado READ. Tiene que haber el mismo número de variables siguiendo a READ como datos haya después de DATA. Si hay más variables READ que datos en DATA, BASIC generará un mensaje de error.
Podemos usar DATA y READ no solo para especificar y almacenar constantes numéricas, sino también hileras de texto, como lo muestra el siguiente programa:
10 DATA MANZANAS, NARANJAS, UVAS
20 FOR N = 1 TO 3
30 READ A$
40 PRINT A$
50 NEXT N
60 END
Obsérvese que no es necesario encapsular en dobles comillas las hileras de texto cuando le son dadas a DATA, y que READ opera de modo similar tanto sobre números como sobre hileras de texto.
10 REM EJEMPLO DEL USO DE DATA Y READ
20 READ P
30 READ H
40 LET G = P * H
50 LET W = .85 * G
60 LET N = G - H
70 PRINT P
80 PRINT H
90 PRINT G
100 PRINT W
110 PRINT N
120 GOTO 20
Un conjunto de datos que pueden ir con el programa anterior es el siguiente:
900 DATA 1.35
901 DATA 40
902 DATA 2.00
903 DATA 41
904 DATA 1.79
905 DATA 35
906 DATA 2.10
907 DATA 49
Los datos sobre los que opera un programa consisten en una serie de números. Es útil pensar en tales números como si estuviesen puestos uno encima del otro en una pila de números parecida a las pilas de platos que vemos en los restaurantes. Cuando un número es tomado de la pila, el siguiente número es empujado por la computadora hacia el tope de la pila. Los números son puestos en forma ordenada en la pila de números de las líneas DATA desde antes de que el programa sea ejecutado. En este ejemplo, el número 1.35 es puesto en el tope de la pila, el siguiente número 40 es puesto inmediatamente debajo, y así sucesivamente. Así, estamos en condiciones de poder entender el enunciado puesto en la línea 20 del programa, el cual dice: “Tómese el número que está en el tope de la pila (1.35) y póngase dicho número en la caja cuyo nombre es P, descartando cualquier número que hubiera estado allí previamente”. De este modo, después de que el enunciado en la línea 20 ha sido ejecutado por primera vez, el número 1.35 estará en la “caja” P (y el número 40 estará ahora en el tope de la pila). ¿Y qué sucede cuando la computadora continúa con la ejecución de la línea 30? El número que está puesto en el tope de la pila (40) es puesto en la “caja” H, y el número 2.00 es empujado hacia el tope de la pila. Tras esto, las líneas 40, 50 y 60 son ejecutadas, asignándose valores numéricos a las variables G, W y N, las cuales una vez efectuadas las operaciones matemáticas contendrán (respectivamente) los valores 54, 45.9 y 14. Tras esto, los valores de P, H, G, W y N son imprimidos por la computadora. Es importante darse cuenta de que cada dato en DATA solo puede ser leído una vez en cada ocasión que el programa se ejecuta. La siguiente vez que un enunciado READ pide un dato, leerá el siguiente dato que haya en la línea DATA, o si la línea se ha agotado, se irá a la siguiente línea DATA para continuar leyendo datos con READ.
En la línea 120 del programa encontramos puesto un comando GOTO que ordena lo que se conoce como un salto incondicional. Este comando refleja a alto nivel algo que ocurre en el nivel más bajo (al nivel del lenguaje de máquina). La sintaxis del comando es:
GOTO número de línea
El comando GOTO provoca que el orden de ejecución del programa sea transferido hacia el número de línea puesto inmediatamente después de GOTO, provocándose un mensaje de error cuando no exista tal número de línea dentro del resto del programa. En el programa dado arriba, el salto incondicional es hacia la línea 20, volviéndose a repetir el procedimiento con un conjunto de números nuevos tomados de la pila de números (2.00 y 41 en la segunda ocasión).
Otro ejemplo del comando GOTO en acción es el siguiente:
10 INPUT "CUAL ES TU NOMBRE"; NOMBRE$
20 PRINT "HOLA ";NOMBRE$
30 GOTO 10
Cuando se corre este programa, se le pedirá el nombre al usuario, en la primera línea, se imprimirá de acuerdo a la orden dada en la segunda línea, y se dará un salto a la primera línea. Esto es lo que se conoce como un bucle perpetuo (en inglés esto se conoce como endless loop). No hay salida limpia (programada) del bucle, a menos de que se oprima una tecla de [BREAK] o se interrumpa la ejecución del programa con alguna combinación de teclas que rompa la cadena. Otra manera de crear un bucle perpetuo es dando un salto GOTO a la misma línea como en el siguiente ejemplo:
10 PRINT "OPRIMASE [BREAK] PARA REGRESAR A OK"
20 GOTO 20
En el programa en donde se introdujo el comando DATA, se puso únicamente un valor numérico en cada línea con un enunciado DATA. Pero esto no es necesario. Podemos incluír varios datos numéricos en una misma línea, todo lo que tenemos que hacer es separar los valores numéricos con comas. La pila de números será llenada leyendo el primer enunciado DATA que aparezca, leyendo los valores de izquierda a derecha, hasta que la pila de números en una línea DATA se haya agotado y se tenga que pasar a la lectura de la siguiente línea con un enunciado DATA.
Las líneas DATA que especifican datos pueden ser colocadas en cualquier parte de un programa, aunque por conveniencia y legibilidad se recomienda poner los enunciados DATA ya sea al principio o al final del programa en donde puedan ser encontrados fácilmente. Pero el lugar en donde se pongan es irrelevante. Para comprobarlo, hágase la prueba con el siguiente programa de ejemplo en donde introduciremos los comandos FOR (que se traduce como “para”), TO (que se traduce como “hasta”) y NEXT(que se traduce como “el valor que sigue”) que especifican la acción de un bucle que será repetido cinco veces:
10 DATA 1,2,3,4,5
20 FOR N = 1 TO 5
30 READ A
40 PRINT A;
50 NEXT N
60 END
Cuando se corre este programa con RUN, en la pantalla se pone lo siguiente:
1,2,3,4,5
OK
Obsérvese que los datos de DATA (en la línea 10) están arriba, fuera del bucle. Podemos meter los datos de DATA dentro del bucle borrando la línea 10 y escribiendo el contenido en la línea 25:
25 DATA 1,2,3,4,5
Si se corre de nuevo el programa, se encontrará que no hay diferencia alguna y se obtiene lo mismo. Y si se saca la línea DATA fuera del bucle poniéndola al final, borrando la línea 25 y poniendo el contenido de la misma en la línea 55:
55 DATA 1,2,3,4,5
se encontrará otra vez que no hay diferencia al correr el programa.
Lo que sucede en el programa dado arriba es que BASIC recorre el bucle N veces, leyendo la variable A (que contiene los datos) en cada ocasión. Cada vez que el programa le da la vuelta al bucle, los datos son impresos, pero en cada ocasión el valor de A ha sido incrementado.
Dicho sea de paso, el uso de un semicolon “;” puesto inmediatamente después de lo que será impreso por un comando PRINT ocasionará que el siguiente PRINT se imprima en la misma línea aunque se encuentre en otro número de línea. De este modo, el programa:
10 PRINT "Me llamo ";
20 PRINT "Armando ";
30 PRINT "Martinez"
40 END
imprimirá en la pantalla en una sola línea lo siguiente:
Me llamo Armando Martínez
El problema fundamental con el uso indiscriminado del comando GOTO que produce un salto incondicional es que es muy fácil que se produzcan bucles perpetuos cuando se ordena un salto hacia una línea previa y no hay alguna manera de salir del bucle. El problema se agrava cuando por malas prácticas de programación se usa el comando GOTO para saltar alegremente de un lado a otro enredando tanto el asunto que puede ser extremadamente difícil encontrar el punto exacto en el cual se encuentra atorado un programa dentro de algún bucle que perpetuo que a su vez forma parte de otros bucles perpetuos en lo que se conoce como el síndrome de spaghetti (en alusión al enredamiento que se puede dar entre las hebras de dicha sopa):
Casi por lo general, el error que se comete es apostarle todo a un comando GOTO que eventualmente conducirá hacia la última línea del programa que marca la terminación del mismo con un comando END (o STOP), sin darse cuenta que el enredijo jamás permitirá llegar a ese GOTO final. Para remediar un poco tal situación, se recurre a la pareja de comandos FORy NEXT para fijar un tope límite al número de veces que se puede ejecutar un bucle. La sintaxis de esta pareja inseperable es la siguiente:
FOR contador = valor inicial TO valor final
NEXT contador
En el caso del programa que vimos arriba:
10 DATA 1,2,3,4,5
20 FOR N = 1 TO 5
30 READ A
40 PRINT A;
50 NEXT N
60 END
el conteo del bucle FOR-NEXT empieza con N.=.1, dándose lectura con READ al primer dato (el valor 1) y asignándolo a la variable A, tras lo cual el dato se imprime en la misma línea (este es el propósito del semicolon puesto inmediatamente a la derecha de A), empezando una segunda ejecución con el contador elevado a N.=.1. Obsérvese que la pareja FOR-NEXT va incrementando el contador siempre en pasos unitarios, lo cual en cierto modo refleja lo que ocurre al nivel del lenguaje de máquina con órdenes de incremento que van de uno en uno.
Algunas versiones de BASIC permiten juntar en una sola línea los enunciados FOR y NEXT, usando un colon “:” para separarlos, con el propósito de ayudar a crear un retardo de tiempo que proporciona un retardo en la ejecución de un programa con el objeto de visualizar alguna acción, como lo muestra la siguiente línea:
35 FOR RETARDO = 1 TO 800: NEXT RETARDO
Habrá casos en los cuales querramos que el contador en el bucle FOR-NEXT vaya incrementando no en pasos unitarios sino en cierta cantidad especificada por nosotros mismos. En tales situaciones se recurre a la siguiente versión modificada que agrega al bucle FOR el modificador STEP:
FOR contador = valor de inicial TO valor final STEP incremento
NEXT contador
Al empezar el bucle, la computadora fija el contador al valor inicial, y checa para ver si se ha llegado al valor final, y si así ocurre, transfiere el control a la siguiente instrucción que sigue a NEXT. En caso contrario, las instrucciones situadas dentro del bucle son llevadas a cabo, y cuando se encuentra de nuevo NEXT el incremento en STEP es sumado al valor actual del contador, checándose si se ha llegado al valor final, y si así ocurre, se transfiere el control a la siguiente instrucción que sigue a NEXT. En caso contrario, se ejecutan las instrucciones dentro del bucle. El proceso es repetido hasta que el contador ha alcanzado el valor final, dándose por terminado el bucle y transfiriendo el control a la siguiente instrucción que sigue a NEXT.
Un ejemplo del uso de esto es el siguiente (obsérvese que en la línea 20 se ha puesto un retardo de tiempo):
10 FOR X = 1 TO 100 STEP 5
20 FOR DELAY = 1 to 500: NEXT DELAY
30 PRINT X
40 NEXT X
50 END
Cuando se corre este programa, no se pondrá en la pantalla cada número entre 1 y 100, se pondrá cada quinto número (6, 11, 16, 21, 26, etc.)
El tamaño del paso STEP nunca debe ser cero, porque esto implicaría que queremos que el programa corra por siempre sin detenerse.
La parte STEP no solo puede tomar valores enteros positivos, también puede tomar valores enteros negativos. Un ejemplo práctico de una aplicación de los bucles FOR-NEXT en la que STEP toma un valor entero negativo es el de la evaluación de números factoriales. El factorial de un número se obtiene multiplicando el número por sí mismo menos uno, y después multiplicando este producto por sí mismo menos dos, y así sucesivamente hasta que llegamos a uno:
FACTORIAL = N * (N-1) * (N-2) * (N-3)*...* 1
Muchas instalaciones de BASIC no incluyen una función para la evaluación del factorial de un número, en virtud de que es fácil escribir una porción de código para esta evaluación, como lo siguiente:
10 READ N
20 LET FACT = N
30 FOR M = N - 1 TO 1 STEP -1
40 NEXT M
50 PRINT "FACTORIAL DE ", N, " = ", FACT
60 GOTO 10
10 FOR Z = 1 TO 25 STEP -1
20 PRINT Z
30 NEXT Z
El tamaño del paso STEP es negativo. El bucle se puede dar por terminado en cuanto la variable haya caído por debajo de 25. El problema es que el valor inicial del contador (que es 1) ya está debajo de 25. Por lo tanto, el enunciado PRINT en la línea 20 jamás será ejecutado.
Los bucles pueden ser anidados uno dentro del otro. A continuación se tiene un ejemplo de un anidamiento legal de bucles:
10 FOR I = 1 TO 10
20 FOR J = 1 TO 10
30 ....
40 NEXT J
50 NEXT I
60 END
Los bucles, obviamente, no se pueden “atravesar”. A continuación se tiene un ejemplo de un anidamiento ilegal:
10 FOR I = 1 TO 10
20 FOR J = 1 TO 10
30 ....
40 NEXT I
50 NEXT J
60 END
Otra cosa que también debe llamar la atención es que los valores inicial y final usados en los bucles FOR-STEP-NEXT pueden ser expresiones como en el siguiente caso:
FOR X = A + B TO 3 * X STEP N
Hemos visto arriba cómo con el comando GOTO podemos ordenar que se lleve a cabo un salto incondicional hacia otra línea del programa, lo cual puede producir problemas. Otra manera expedita para poder salir de un bucle es usar las transferencias condicionales, usando un tipo de salto conocido como el salto condicionado, el cual ocurre cuando se cumple cierta condición. La sintaxis para que ocurra un salto condicionado es la siguiente:
IF valor de prueba THEN número de línea
de la cual podemos dar el siguiente ejemplo:
30 IF P = 264 THEN 120
que se puede leer como: “Si la variable numérica P es igual a 264, entonces ir a la línea 120”.
PROBLEMA: Encuéntrense los errores lógicos en el siguiente programa:
10 FOR Z = 1 TO 30
20 IF Z = 5 THEN 10
30 PRINT Z
40 NEXT Z
La primera vez que se ejecuta el bucle, Z será igual a 1, la condición en la línea 20 no se cumplirá, y se imprimirá Z. Hasta aquí todo va bien. La segunda vez que se ejecuta el bucle, Z será igual a 2, y de nuevo no habrá problema alguno. La dificultad ocurre cuando Z adquiere el valor 5 y la condición necesaria para la transferencia condicional se cumple. El salto se dará a la línea 10 y todo volverá a comenzar de nuevo, una y otra vez, sin final. La computadora producirá una serie infinita consistente en los números 1, 2, 3, 4, 1, 2, 3, 4, etc. Presumiblemente, la intención original del programador era que la computadora detuviera su ejecución al llegar Z al valor de 5, en cuyo caso el enunciado correcto debería de haber sido:
IF Z = 5 THEN 40
Algo que le da valor a las transferencias condicionales es que podemos usar varios criterios como valor de prueba para especificar el salto que será dado, de acuerdo a las siguientes convenciones:
Comparación
|
Forma alterna |
Leer como:
|
> | GT | “es mayor que” |
< | LT | “es menor que” |
= | = | “es igual que que” |
>= | GE | “es mayor o igual que” |
<= | LE | “es menor o igual que” |
<> | NE | “es mayor o menor que” “no es igual a” |
A continuación tenemos unos ejemplos del uso de cada una de las condiciones anteriores:
Enunciado
|
Significado
|
IF A = G THEN 250 |
Si el valor actual de A es igual al valor actual de G, ir
al
número de línea 250, de lo contrario ir a la siguiente instrucción |
IF A <> G THEN 135 |
Si el valor actual de A no es igual al valor actual de G, ir
al número de línea 135, de lo contrario ir a la siguiente instrucción |
IF Q > 482 THEN 110 |
Si el valor actual de Q es mayor que 482, ir al número
de línea 110, de lo contrario ir a la siguiente instrucción |
IF M >= 93 THEN 500 |
Si el valor actual de M es mayor o igual que 93, ir al
número de línea 500, de lo contrario ir a la siguiente instrucción |
IF P < 5 THEN 193 |
Si el valor actual de P es menor que 5, ir al número de
línea 193, de lo contrario ir a la siguiente instrucción |
IF W <= H THEN 50 |
Si el valor actual de W es menor o igual que H, ir al
número de línea 50, de lo contrario ir a la siguiente instrucción |
Aunque podemos usar las 26 letras del alfabeto (inglés) como variables, hay ocasiones en las cuales quisiéramos tener más variables disponibles, a veces cientos de ellas. Para este propósito, BASIC permite la creación de arreglos (arrays), a los cuales también se les simboliza con una letra, la cual sin embargo es seguida por un par de paréntesis dentro de los cuales se proporciona el número que identifica a la cantidad como el dato de un arreglo unidimensional que es mejor reconocido como una lista. Si identificamos a una lista con una letra como “A”, tenemos entonces lo que nos distingue el uso de esta letra como una variable numérica y una variable de hilera. De este modo, si hacemos:
A = 25
A$ = "Quijote"
A(1) = 835
y tras esto hacemos:
PRINT A; A$; A(1) [Enter]
la computadora nos responderá con lo siguiente:
25 Quijote 835
De igual manera, podemos intuír que H(3) es el tercer artículo de una lista llamada H y que W(20) es el vigésimo artículo en una lista llamada W.
En el BASIC genérico solo podemos usar una letra para designar una lista. De este modo, el enunciado A9(42) es ilegal. Una vez que nos hemos apropiado de una letra para representar una lista (o una tabla) no debemos usarla para designar otra cosa. Podemos referirnos a una “caja” dentro de la lista explícitamente como en el caso de C(10) y X(55), o hacerlo implícitamente usando alguna expresión como:
T(M)
B(H8)
W(A + (B*D))
La idea detrás de una lista es muy similar al de la variable subscripta usada en matemáticas. Así, mientras que el matemático usa X5 para indicar el quinto valor de una serie de variables llamadas X, nosotros escribiríamos esto como X(5). Por esta razón es común llamar a las listas variables subscriptas.
Suponiendo que tenemos un conjunto de diez valores almacenados bajo un enunciado DATA:
100 DATA 35,238,72,3,642,234,90,634,66,13
los podemos ir metiendo en sus respectivas “cajas” adentro de una lista que llamaremos X de la siguiente manera:
10 FOR I = 1 TO 10
20 READ X(I)
30 NEXT I
Hay ocasiones en las cuales una lista no es suficiente para lo que queremos almacenar y procesar. Supóngase que queremos almacenar las distancias que hay entre diez ciudades distintas. Para tales propósitos necesitamos una tabla, que aquí llamaremos D. De la misma manera en la cual definimos listas, también podemos definir una tabla, que viene siendo un arreglo bidimensional. Especificamos un elemento de una tabla de una manera como la siguiente:
D(5,8)
De este modo, el número puesto en el tercer renglón y la quinta columna de la tabla, el cual representa la distancia entre la tercera ciudad y la quinta ciudad, puede ser descrito simplemente como D(3,5). A continuación se tiene un ejemplo de una tabla llamada T que consta de cinco renglones y siete columnas, con los elementos de cada celda identificados de acuerdo al número de renglón y al número de columna:
T(0,0) | T(0,1) | T(0,2) | T(0,3) | T(0,4) | T(0,5) | T(0,6) |
T(1,0) | T(1,1) | T(1,2) | T(1,3) | T(1,4) | T(1,5) | T(1,6) |
T(2,0) | T(2,1) | T(2,2) | T(2,3) | T(2,4) | T(2,5) | T(2,6) |
T(3,0) | T(3,1) | T(3,2) | T(3,3) | T(3,4) | T(3,5) | T(3,6) |
T(4,0) | T(4,1) | T(4,2) | T(4,3) | T(4,4) | T(4,5) | T(4,6) |
Obsérvese que todas las tablas (al igual que todas las listas) en BASIC incluyen un renglón cero y una columna cero, lo cual podemos especificar. Un ejemplo de la tabla anterior, rellena de datos que son hileras de texto, es el siguiente (obsérvese que la tabla contiene hileras de texto):
ENERO | FEBRERO | MARZO | ABRIL | MAYO |
naranjas | manzanas | uvas | peras | nueces |
tocino | jamon | pescado | pollo | res |
mayonesa | chile | sal de ajo | oregano | pimienta |
budin | gelatina | pastel | trufas | flan |
Podemos meter dentro de una tabla hileras de texto como se aprecia arriba anteponiendo el símbolo “$” inmediatamente después de la letra con la que identificamos la tabla, como lo muestra el siguiente programa:
10 DIM G$(5,8)
20 FOR M = 1 TO 5
30 FOR N = 1 TO 9
40 G$(M,N) = "HILERA"
50 NEXT N
60 NEXT M
70 END
Con este programa, se crea una tabla de cinco renglones y ocho columnas, metiendo con un anidamiento de bucles la misma palabra HILERA dentro de cada celda de la tabla.
D(9,5)
X(I,4)
Q(A+X,7)
M(3,A/B)
H(X+Y,L(N))
Obviamente, puesto que los números usados para identificar un renglón y una columna deben ser números enteros, después de evaluar las expresiones la computadora redondea el resultado al entero más cercano.
¿Y cómo sabe la computadora que hemos decidido usar una letra para representar una tabla? Lo hace viendo al inspeccionar el programa antes de correrlo. Si encuentra una letra seguida de un par de paréntesis con una coma entre los paréntesis, no resulta difícil adivinar lo que el programador tenía en mente.
La computadora reserva espacio automáticamente para listas y tablas. Sin embargo, habrá ocasiones en las cuales antes de comenzar querramos pedirle la reservación de un espacio suficiente para una lista o una tabla, por ejemplo, tal vez queremos que reserve suficiente espacio para una lista de mil elementos, o que reserve suficiente espacio para almacenar todos los elementos de una tabla grande. Para tal propósito, usamos el enunciado de dimensión DIM de la siguiente manera:
10 DIM X(1000)
20 DIM A(8,15)
El enunciado DIM cuando se pone siempre debe ser puesto al principio del programa BASIC. El primer enunciado reserva espacio suficiente para mil artículos a ser puestos en la lista X, mientras que el segundo enunciado reserva espacio suficiente para una tabla A que constará de ocho renglones y quince columnas.
Una buena práctica de programación, si un programa contiene varias listas y tablas, es pedirle a la computadora con el enunciado DIM que reserve espacio especificándolo todo en una sola línea, lo cual requiere que el enunciado DIM solo se tenga que usar una sola ocasión, al principio de la línea, separando las listas y tablas con comas:
DIM X(25), Y(25), R(100), C(25,99), T(100,9)
PROBLEMA: Escribir un programa para inicializar todas las entradas de una tabla W que consta de diez renglones y diez columnas haciendo todos sus elementos iguales a cero.
Una manera de inicializar la tabla W es la siguiente:
10 FOR I = 1 TO 10
20 FOR J = 1 TO 10
30 LET W(I,J) = 0
40 NEXT J
50 NEXT I
En muchas instalaciones de BASIC se tienen funciones para el procesamiento de hileras de texto que pueden ser útiles en programas interactivos. Una de tales funciones es:
INKEY$
la cual es útil para pausar manualmente la ejecución de un programa hasta que una tecla sea oprimida. Muchas computadoras mantienen en un registro una “memoria” de la última tecla que fue oprimida. Si no se ha oprimido tecla alguna, el registro esta vacío. La función INKEY$ nos entrega el valor que se encuentra en este registro, y si no se ha oprimido tecla alguna entonces regresa una “hilera vacía”. Un ejemplo del uso de INKEY$ es el siguiente (es importante que no haya nada entre las dobles comillas, ni siquiera un espacio en blanco):
10 FOR X = 1 TO 20
20 PRINT X
30 A$ = INKEY$ : IF A$ = "" THEN 30
40 NEXT X
50 END
Cuando se corre este programa, imprimirá el primer número y esperará que el usuario oprima cualquier tecla. Si se borra la línea 30, los números se imprimen tan rápidamente que no se podrán leer. La línea 30 trabaja de la siguiente manera: la función INKEY$ es asignada a la variable de hilera A$. La segunda parte de la línea dice que si A$ es una hilera nula, la ejecución se mantenga en la misma línea, siendo en efecto un bucle perpetuo hacia la misma línea (aquí hemos usado la posibilidad de poder poner varias instrucciones en una misma línea siempre y cuando estén separadas por un símbolo “:”). Si se oprime cualquier tecla, entonces A$ toma el valor del caracter, lo cual hace que salgamos del bucle pasando a la línea 40.
Otras función de hileras que resulta útil es la función:
ASC(hilera)
la cual nos regresa (en sistema decimal) el código ASCII del primer caracter de la hilera. De este modo, si hacemos (obsérvese que el argumento que se le entrega a la función tiene que ser puesto entre comillas):
PRINT ASC("A")
obtenemos lo siguiente:
65
La función CHR$ es el inverso de la función ASC cuando le entregamos un código ASCII nos devuelve el caracter que corresponde al código ASCII, de modo tal que:
PRINT CHR$(65)
hace que en la pantalla se imprima:
A
No hay que confundir una constante numérica con la hilera que representa dicha constante numérica, la computadora almacena ambas cosas de modo diferente. El número 5 es almacenado por la computadora como el número binario 00001101, mientras que la hilera 5 es almacenada en la computadora con el código ASCII usado para representar el símbolo “5” (véase en los apéndices “El código ASCII”), cuyo equivalente decimal es 53 (en binario, 00110101). Del mismo modo, mientras que el número 175 es almacenado por la computadora como el número binario 10101111, la hilera 175 es almacenada mediantes tres códigos ASCII, uno para el símbolo “1”, otro para el símbolo “7”, y otro para el símbolo “5”. La falta de precaución en este tipo de detalles es frecuentemente el origen de muchas confusiones en los programadores principiantes. Si por alguna razón queremos convertir una hilera que contiene símbolos numéricos a una constante numérica, usamos la función:
VAL(hilera)
cuyo efecto es el siguiente:
VAL("1.3") = 1.3
VAL("3.1416") = 3.1416
VAL("17.4TDL") = 17.4
VAL("ABC") = 0
En el tercer caso, la función VAL nos regresa un valor de cero puesto que la hilera contiene únicamente letras del alfabeto.
STR$(numero)
la cual convierte un número a una hilera. Usualmente, si se trata de usar una constante numérica como una hilera, BASIC lo rechaza como un error. Pero si se convierte el número a un caracter de hilera, entonces puede ser tomado en la forma en que lo hace en el siguiente programa;
10 INPUT "TECLEA UN NUMERO"; N
20 A$ = STR$(N)
30 PRINT A$; " ES AHORA UNA HILERA"
40 END
La función:
LEN(hilera)
nos proporciona el número de caracteres (letras, números, espacios en blanco) que hay en una hilera. Un ejemplo que nos muestra esta función en acción es el siguiente:
10 INPUT "DAME UNA FRASE"; A$
20 PRINT "LA FRASE CONTIENE "; LEN(A$) ; " LETRAS"
Obsérvese que lo anterior toma en cuenta también los espacios en blanco.
LEFT$(hilera,longitud)
RIGHT$(hilera,longitud)
MID$(hilera,posición,longitud)
La función LEFT$ extrae los caracteres que están en el lado izquierdo de una hilera, extrayendo tantos caracteres como la cantidad indicada con el número puesto en longitud. La función RIGHT$ extrae los caracteres que están en el lado derecho de una hilera, extrayendo tantos caracteres como la cantidad indicada con el número puesto en longitud. Y MID$ extrae una sub-hilera de la hilera de caracteres a partir del número de posición indicado que puede ser cualquier número a partir de 1 (el del primer caracter de la hilera), extrayendo tantos caracteres como lo indique la longitud.
El siguiente programa muestra las tres funciones en acción:
10 INPUT "ESCRIBE UNA PALABRA"; P$
20 PRINT "LA PRIMERA LETRA ES "; LEFT$(P$,1)
30 PRINT "LAS ULTIMAS DOS LETRA SON "; RIGHT$(P$,1)
40 PRINT "LA PARTE MEDIA DE LA PALABRA ES "; MID$(P$,2,2)
Si corremos el programa anterior y le entregamos la palabra DONA, la respuesta dada será:
LA PRIMERA LETRA ES D
LAS ULTIMAS DOS LETRAS SON NA
LA PARTE MEDIA DE LA PALABRA ES ON
Como una aplicación de lo anterior, y usando la función matemática:
INT(número)
que nos regresa la parte entera (integer) de un número real, a continuación se tiene el siguiente programa usado para convertir números en sistema decimal no mayores de 65,535 a su equivalente en sistema hexadecimal:
5 CLS
10 A$ = "0123456789ABCDEF"
20 INPUT "NUMERO"; N
30 H4 = INT(N/4096)
40 H3 = INT((N - H4*4096)/256)
50 H2 = INT((N - ((H4*4096) + (H3*256)))/16)
60 H1 = N - ((H4*4096) + (H3*256) + (H2*16))
70 X4$ = MID$(A$,H4+1,1)
80 X3$ = MID$(A$,H3+1,1)
90 X2$ = MID$(A$,H2+1,1)
100 X1$ = MID$(A$,H1+1,1)
110 PRINT X4$ + X3$ + X2$ + X1$
120 GOTO 20
Dentro de la mayor parte de las versiones de BASIC se encuentran definidas varias funciones matemáticas, tales como la función SQRT para la extracción de raíces cuadradas, cuya sintaxis es:
SQRT(numero)
Si queremos obtener la raíz cuadrada de 100, hacemos lo siguiente:
PRINT SQRT(100)
Para elevar un número a cierto exponente, usamos el símbolo de la flecha “↑” disponible en cualquier teclado. Es posible que por errores de redondeo propios de la computadora al manejar números reales, no obtengamos la respuesta “exacta” que esperaríamos. Por ejemplo, al usar a BASIC como una calculadora interactiva, lo siguiente:
PRINT 77↑3
es posible dependiendo de la calidad del interpretador BASIC que se nos produzca la siguiente respuesta:
456533.002
De cualquier modo, hablando en términos de precisión, la respuesta dada arriba es correcta hasta en ocho cifras significativas, lo cual es suficiente para muchos tipos de cálculos.
Casi todas las instalaciones de BASIC incorporan las siguientes funciones matemáticas:
LOG(numero)
Esta función produce el logaritmo natural de un número mayor que cero.
EXP(numero)
Esta función regresa el exponencial natural de un número, o sea enumero.
La función es el inverso de la función LOG.
ABS(numero)
Esta función nos regresa el valor absoluto de un número.
Si el número es negativo, lo convierte en un número positivo.
SGN(numero)
Esta función nos dice si un número es positivo, negativo, o cero.
Regresa -1 si el número es negativo. regresa 0 si el número es
cero, y regresa 1 si el número es positivo.
SIN(angulo)
Esta función trigonométrica nos regresa el seno de un ángulo
que está expresado en radianes.
COS(angulo)
Esta función trigonométrica nos regresa el coseno de un ángulo
que está expresado en radianes.
TAN(angulo)
Esta función trigonométrica nos regresa la tangente de un
ángulo que está expresado en radianes.
ATAN(numero)
Esta función nos regresa en radianes el ángulo cuya tangente
produc
Si tratamos de elevar diez a la potencia 10, BASIC convertirá automáticamente la respuesta a notación científica al tener la respuesta (10,000,000,000) más de nueve cifras significativas:
PRINT 10↑10 [Enter]
1.0000000E+10
10 LET V = A + LOG(9)
20 LET G7 = A + (15*LOG(3))
30 IF B + LOG(Q) > 50 THEN 260
40 PRINT LOG(M)/LOG(B+12)
Otra enunciado matemático disponible en BASIC (en rigor de verdad, no se le puede llamar función, ya que sólo se le entrega un límite), es RND, cuya sintaxis es:
RND(numero límite)
y la cual genera un número aleatorio comprendido entre cero y el numero límite. Un ejemplo del uso del enunciado RND está en el siguiente programa:
10 FOR I = 1 TO 5
20 LET Z = RND(1)
30 PRINT Z
40 NEXT I
Si corremos lo anterior, se imprimirán los siguientes cinco números aleatorios:
.511318
.012963
.151432
.770312
.901628
Los números aleatorios son usados frecuentemente en análisis estadísticos para llevar a cabo cosas tales como una simulación Monte Carlo que puede ser usada para el estudio de fenómenos de naturaleza aleatoria. Lógicamente, una lista de números aleatorios tiene que pasar ciertas pruebas estadísticas para que sea de utilidad, y una de ellas es que la media aritmética de la lista (por ejemplo de una lista de números aleatorios entre cero y 100) esté cercana a la media aritmética entre cero y el límite máximo de la lista, además de que no debe haber regiones (rangos numéricos) en las cuales haya una mayor densidad de números que en otras. En rigor de verdad, las listas de números aleatorios generados por cualquier computadora no es realmente aleatoria, ya que teniendo toda computadora digital una capacidad limitada de dígitos numéricos, eventualmente se obtendrá un número que ya fue obtenido antes, y siendo la computadora una máquina cien por ciento determinística, la lista de números se volverá a repetir en forma idéntica, perdiéndose la aleatoriedad. Esta es la razón por la que es costumbre referirse a estos generadores de números aleatorios como números pseudo-aleatorios, y es importante no exceder en cualquier simulación estadística la alcance tras el cual la lista de números aleatorios se vuelve a repetir (para cinco cifras de precisión, se supondría que se generarían 99,999 números aleatorios diferentes, pero no hay que confiarse en esto, ya que es posible que la cantidad de números aleatorios generados no llegue ni siquiera a mil).
GOBUB(numero de linea hacia el cual se da el salto)
RETURN
GOSUB es similar a GOTO, la diferencia es que cuando la computadora encuentra:
GOTO 1200
la ejecución del programa se transfiere a la línea 1200, y la computadora “olvida” el lugar en donde se encontraba al momento de efectuar el salto. Pero si se le dice:
GOSUB 1200
entonces la ejecución del programa es transferida a la línea 1200, y la computadora “recuerda” el lugar en donde se encontraba al momento de ocurrir el salto. Después, cuando la computadora encuentra el enunciado RETURN, volverá a la instrucción puesta en el número de línea que está inmediatamente después del número de línea desde el cual se hizo la transferencia.
Hay tres reglas importantes a recordar al usar subrutinas en BASIC:
1) Hay que usar los comandos END (o STOP) y GOTO inmediatamente adelante (antes) de una subrutina para asegurarse de que la computadora solo podrá entrar a una subrutina con GOSUB.
2) Toda subrutina tiene que ser terminada con un RETURN.
3) Hay que abstenerse de meter transferencias condicionales y saltos incondicionales dentro de una subrutina que puedan ocasionar una salida de la subrutina antes de que se haya llegado a RETURN. Esto suele ser una fuente inagotable de errores, y en muchas instalaciones de BASIC es detectado como un error y suele dar lugar a que la ejecución del programa sea rechazada desde antes de empezar.
Un ejemplo de una subrutina está en la definición del factorial de un número para ser usada como subrutina del modo siguiente:
200 LET F = N
210 FOR M = N -1 TO 1 STEP -1
220 LET F = F * M
230 NEXT M
240 RETURN
Ya definida, la subrutina puede ser usada de la siguiente manera:
10 LET N = 12
20 GOSUB 200
30 PRINT F
Una variante de la subrutina es la subrutina condicionada con saltos multi-línea, que se encuentra en muchas instalaciones de BASIC, cuya sintaxis es la siguiente:
ON valor de prueba GOSUB linea, linea, linea, ...
Un ejemplo de esta variante en acción que usa tres subrutinas es el siguiente programa:
10 PRINT "QUE HAY DETRAS DE LA PUERTA?"
20 INPUT "ESCRIBE 1, 2 o 3": N
30 ON N GOSUB 100, 200, 300
40 END
100 PRINT "TE HAS GANADO UN VIAJE A BRASIL"
110 RETURN
200 PRINT "TE HAS GANADO UNA COMPUTADORA"
210 RETURN
300 PRINT "TE HAS GANADO UNA CASA"
310 RETURN
En caso de cometerse errores, algo que ocurre muy frecuentemente al estarse elaborando un programa en cualquier lenguaje de programación, resulta conveniente el poder repasar las líneas en las cuales se sospecha que radica el problema. En el caso de BASIC, en algunas variantes es posible encontrar algunos comandos mediante los cuales podemos obtener un listado parcial de las instrucciones situadas entre cierto rango de números de línea. Un comando típico para ello es el comando de listado LIST, el cual imprime en la pantalla todas las líneas ubicadas dentro de cierto rango, de acuerdo a la siguiente sintaxis:
LIST línea de inicio - linea final
En el siguiente ejemplo:
LIST 10-50 [Enter]
se le está pidiendo al sistema que imprima en la pantalla todas las instrucciones cuyos números de línea están comprendidos entre la línea número 10 y la línea número 50 (inclusive).
Algunas versiones de BASIC tienen disponibles dos comandos extraordinarios que permiten un acceso directo a ciertas áreas de la memoria RAM del sistema, y en algunos casos el acceso está disponible hacia toda la memoria RAM, los cuales son:
PEEK(localidad de la memoria)
POKE localidad de la memoria, byte
El comando PEEK (“vistazo”) nos permite obtener el byte que está almacenado en la localidad de la memoria que queramos inspeccionar, como en el caso de la siguiente instrucción que nos devuelve el byte que está almacenado en el domicilio 32076 (decimal) y el cual es guardado en la variable A:
A = PEEK(32076)
mientras que el comando POKE (“meter”) nos permite meter el byte que nosotros especifiquemos (cualquier valor entre 0 y 255) en una localidad de la memoria. Obviamente, POKE no funcionará en domicilios que no sean áreas de memoria RAM sino que estén ocupados por alguna memoria de lectura únicamente (ROM). La siguiente instrucción mete la palabra binaria 00111000 en la localidad e la memoria 16390 (decimal):
POKE 16390, 56
Un comando como POKE debe ser manejado con sumo cuidado y mucho respeto, porque en caso de un mal uso puede interferir con un programa que se está ejecutando o incluso paralizando por completo a la máquina requiriendo un reencendido de la misma. Un ejemlo del uso de POKE es el siguiente en el cual llenamos cierta porción de la memoria que corresponde a texto puesto en el video de una computadora:
10 CLS
20 FOR X=1280 TO 1535
30 POKE X,249
40 NEXT X
50 GOTO 50
Ahora bien, 500 hexadecimal equivale a 1280 decimal, mientras que 5FF hexadecimal equivale a 1535, y F9 hexadecimal equivale a 249 decimal. No se requiere de mucha imaginación para darse cuenta de que en una computadora Tandy Color Computer este programa BASIC hace exactamente lo mismo que lo que hace el primer programa ensamblador que fue discutido en la entrada “El ensamblador EDTASM para el μP 6809”, o sea llenar la parte inferior con caracteres gráficos especificados por el byte F9. Sin embargo, hay una diferencia importante entre el programa ejecutable que se obtiene con la ayuda del ensamblador EDTASM y el programa BASIC que tenemos arriba. El programa en lenguaje de máquina entregado por el ensamblador EDTASM ocupa únicamente 13 bytes, mientras que lo mismo llevado a cabo en el interpretador BASIC de dicha máquina requiere de 63 bytes para la elaboración del programa BASIC que tenemos arriba (incluyendo espacios en blanco y saltos de línea). Encima de esto, mientra que el programa en lenguaje de máquina se ejecuta en forma directa sin requerir interpretación o compilación alguna, el program BASIC anterior requiere estar interactuando con el interpretador BASIC instalado en la máquina, lo cual consume tiempo adicional así como recursos de memoria. Esto demuestra de manera contundente que para obtener velocidad y eficiencia no hay como recurrir directamente al programa en lenguaje de máquina obtenido con la ayuda de un ensamblador. Y de hecho, para muchos sistemas de medición y control (por ejemplo, en instrumentación industrial y médica) en donde la interacción de la computadora se lleva a cabo “en vivo” y en forma directa en tiempo real, lo que se hace es “quemar” el programa ejecutable en una memoria ROM haciéndolo tomar control completo de la máquina, en cuyo caso más que tener una computadora interactiva multi-propósitos lo que se tiene es unmicrocontrolador dedicado, trabajando en tiempo real.
Todo lo que hemos visto arriba se lleva a cabo desde una ventana de comandos como las que se usaban en los sistemas operativos UNIX y MS-DOS. Sin embargo, en un sistema operativo como Windows basado no en una ventana de comandos sino en una interfaz gráfica, el BASIC que se utiliza es un BASIC completamente diferente, el cual ¡ni siquiera usa números de línea!, y la programación es una programación visual en vez de estar basada en una programación con comandos de texto. Cuando apareció Windows 95, el cual fue el primer sistema operativo basado en ventanas de diálogo y ventanas de ejecución de programas, Microsoft puso a la disposición de los programadores la primera versión de lo que hoy se conoce como Visual Basic. Y aunque mucho de lo que hemos visto arriba se puede seguir usando, en lo que toca a las interacciones y diálogos con el usuario el panorama cambia por completo, y se vuelve necesario adoptar otra actitud en lo que a la programación de la computadora respecta.
Aunque con la introducción de los sistemas operativos basados en interfaces gráficas (Windows) la programación directa en lenguaje BASIC ya no es posible, afortunadamente es posible encontrar en Internet muchos emuladores de BASIC, ya sea descargables como programas ejecutables, o interactivos con sitios Web, con los cuales se puede practicar un poco el arte de programación con los ejemplos que se han dado arriba.
En los tiempos de los sistemas operativos PC-DOS y MS-DOS basados en líneas de comandos, era común incluír como parte de los programas ejecutables el programa GW-BASIC, conocido también como BASICA, el cual era el interpretador del “BASIC clásico” que corría en las máquinas IBM y sus clones compatibles. El interpretador eventualmente fue reemplazado por QuickBASIC, el cual no era un interpretador sino un verdadero compilador, un lenguaje propio para una programación estructurada que prescindía de los números de línea y de los enunciados GOTO y GOSUB causantes de tantos dolores de cabeza. Al mejorar la calidad de los monitores con los monitores monocromáticos siendo desplazados por los monitores a colores y al aumentar la memoria RAM disponible, Microsoft introdujo en 1991 Windows 3.0, con el cual introdujo por separado (para los programadores) el Visual Basic 2.0 en sus versiones Standard y Profesional. Sin embargo, cabe agregar que Windows 3.0 no era un sistema operativo, era un programa ejecutable invocable desde la ventana de líneas de comandos, siendo posible salir del mismo de la manera usual. Fue con Windows 95 que Microsoft lo elevó de la categoría de mero programa ejecutable a la categoría de sistema operativo, relegando la ventana de comandos a la categoría de mero programa ejecutable. Y ya para entonces había una versión Enterprise de Visual Basic disponible para grandes empresas y negocios. Muchas de las innovaciones para la programación gráfica con Visual Basic introducidas en ese entonces fueron incorporadas para ser usadas con Windows 98 introducido en 1998 para dar uso óptimo a los microprocesadores de 32 bits que estaban apareciendo ya, y mucho de lo que vemos hoy en día viene de allí.