Palabras clave: Instrucciones simples, Expresiones, Variables, Declaración de variables, Asignación de valores, Modificación de variables.

Preguntas de repaso
  • ¿Qué es una expresión numérica con funciones anidadas?

  • ¿Qué es un argumento?

  • ¿Qué es un valor literal y un valor calculable?

No sigas si no conoces las respuestas.

1. Variables

En matemáticas se llama variable a cualquier símbolo o palabra que represente a cualquier valor de los comprendidos en un conjunto. Por ejemplo, en la función matemática \(e^x\) la letra \(x\) representa a cualquier número real y recibe el nombre de variable (matemáticamente hablando es una variable independiente).

En programación también existen variables para representar valores, sin embargo su contexto es diferente y aunque en esencia es la misma idea de las variables matemáticas se definen de otra manera.

Una variable está formada por un espacio en el sistema de almacenaje (memoria principal de un ordenador) y un nombre simbólico (un identificador) que está asociado a dicho espacio.

— Wikipedia

No es difícil de entender. Para empezar, la memoria del ordenador tienes que imaginarla como un montón de ortoedros o cubitos (poliedros de 6 caras). Toma como referencia el dibujo de la derecha.

El ordenador utiliza cada uno de estos ortoedros/cubos para guardar la información. Por ejemplo, unos podrían contener números, otros podrían contener letras, etc.

Variable

Cuando queremos controlar el flujo de información que pasa por uno de estos cubos entonces usamos una variable.

Por ejemplo, si queremos controlar la información del ortoedro coloreado entonces podemos identificarlo con un nombre, como por ejemplo miVariable.

Variable

Lee de nuevo la definición de variable y asocia cada una de las dos componentes que aparecen en la definición con los elementos del dibujo superior.

2. Tipos de datos

En el contexto de las matemática existen dos tipos de variables:

  • Las variables numéricas, que son aquellas que representan números y con ellas se pueden realizar operaciones aritméticas. Por ejemplo, número_alumnos puede representar al número de alumnos que hay en un clase o peso puede representar los quilos que pesa una persona.

  • Por contra, están las variables cualitativas, que son aquellas que no representan números. Por ejemplo, estado_civil puede representar las modalidades (o valores) de soltero, casado, etc …​

Es decir, una variable matemática puede representar a un valor numérico o a un valor no numérico.

En matemáticas existen dos grandes tipos de valores (los numéricos y los no numéricos) que definen a su vez dos tipos de variables (numéricas y no numéricas).

Análogamente, en programación también existen varios tipos de valores. También se distinguen dos grandes grupos (pero se clasifican utilizando un criterio diferente al matemático): los valores simples y los valores complejos (o compuestos).

Tipos de valores
  • Los Valores Simples hacen referencia a aquellos valores que responden a uno de estos tipos:

    • Valores numéricos, son los que representan números como los números enteros o los reales.

    • Valor carácter es un elemento de una secuencia de caracteres (o expresión alfanumérica), por ejemplo una letra del abecedario. Se indican con comillas simples para distinguirlos de las secuencias de caracteres (que se indican con dobles comillas).

    • Valores booleanos, son aquellos elementos que se consideran pertenecientes a un conjunto binario como \(\{0,1\}\) o \(\{true,false\}\)

  • Los Valores Complejos hacen referencia a aquellos que están compuestos por un conjunto de valores simples. Por ejemplo, el conjunto \(\{'a','b','c','d'\}\), o la secuencia "abcd" son valores complejos porque están formados por caracteres de las letras del abecedario que son valores simples.

Estos valores (simples o complejos) se guardan en las celdillas de la memoria del ordenador. Aunque podemos guardar muchos valores, no siempre podemos guardar todos los que queramos. Se debe a que el número de celdillas en la memoria (los cubitos) del ordenador es finito y, por tanto, solo puede representar una cantidad limitada de información. En consecuencia, hay que llegar a un compromiso de hasta cuántas celdillas de memoria se está dispuesto a utilizar para codificar un número, una letra, un texto, o cualquier otro tipo de información.

Por ejemplo, para representar un número en el ordenador podemos considerar, una, dos o más celdillas. Cuantas más celdillas usemos para representar un número, mayor será el rango de números que podamos manipular. Si optamos por usar una celdilla podemos representar números entre -128 y 127, pero si consideramos 4 celdillas podemos representar números entre -3.40282347E+38 y 3.40282347E+38. En la práctica, lo usual es que para representar un real no se use más de 8 celdillas.

Una celdilla recibe el nombre de byte, que es la cantidad más pequeña de datos que un ordenador puede "manipular" a la vez. Es la unidad fundamental de datos en los ordenadores personales, un byte son ocho bits contiguos. Un bit almacena un 0 o un 1.
El número de celdillas que se necesitan para almacenar un dato simple lo establece cada lenguaje de programación. En Processing, los valores de tipo carácter y booleano ocupan una sola celdilla de memoria; pero el resto de los tipos de valores ocupan más de una celdilla de memoria.

Como puedes comprobar, en computación, hablar de valores es hablar de memoria y es por ello que en computación no se habla ni de tipo de variable ni de tipo de valor, se habla de tipo de dato.

Un tipo de dato hace referencia a un tipo de valor y a la cantidad de memoria que será utilizada para representar dichos valores. Además cada tipo de dato tiene asociado un conjunto de operadores.

Si bien en todos los lenguajes de programación existe cierto consenso en los tipos de datos simples (los que hacen referencia a valores simples) deberás consultar la documentación del lenguaje de programación que vayas a utilizar para saber cuál es el tipo de dato que más te conviene para hacer tus programas.

Con todo lo expuesto te debe quedar claro que un dato puede ocupar más de una byte (celdilla), aunque sea un dato simple, lo que nos permite definir mejor el concepto de variable:

Una variable está formada por un espacio en la memoria principal de un ordenador - que puede ocupar varios bytes dependiendo del tipo de dato que almacene - y un nombre simbólico (un identificador) que está asociado a dicho espacio.

3. Variables en Processing

3.1. Declaración de variables

Para trabajar con variables deberemos utilizar un identificador (que será el nombre que nosotros queramos) y asociarle a él un tipo de dato. En Processing esto se escribe mediante la siguiente instrucción simple, que recibe el nombre de declaración de variable:

<tipo_de_dato> identificador;

Existen varios tipos de datos en Processing. Los hay simples (p.e. para representar números) y los hay compuestos (p.e. para representar vectores o imágenes). De entre ellos, los que más vamos a utilizar son los siguientes:

Memoriza
int

Será el tipo de dato a usar para representar números enteros.

float

Es uno de los tipos de datos que permite representar números reales.

char

Es el tipo de dato para valores de caracteres.

boolean

El tipo de dato para representar valores booleanos, y que en Processing son {true, false}.

String

Es el tipo de dato para guardar secuencias de caracteres.

int, float, char y boolean son tipos de datos que almacenan valores simples; pero String es un tipo de dato que almacena valores compuestos (en concreto una secuencia de char de la misma forma que una expresión alfanumérica).

Cada tipo de dato tienen asociado un conjunto de operadores. En particular, con los de tipo int y float se pueden realizar todas las operaciones que hemos estudiado de las expresiones numéricas. En temas posteriores se estudiarán las operaciones más relevantes para otros tipos de datos.

Ejemplo 1. Declaración de variables de distinto tipo en la función principal

Observa el siguiente código:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
void setup() { // Declara variableEntera como una variable entera. int variableEntera; // Declara variableReal como una variable que almacenará reales (en un cierto rango). float variableReal; // Declara variableCaracter como una variable que guardará caracteres. char variableCaracter; // Declara variableBooleana como una variable booleana. boolean variableBooleana; // Declara variableString como una variable String. String variableString; }

En las líneas 3, 6, 9, 12 y 15 se declaran 4 variables pues las instrucciones responden al patrón <tipo_de_dato> identificador;

Declara las variables, utilizando un identificador representativo, para almacenar los siguientes tipos de valores:

  • La altura de una torre en metros.

  • El número de profesores en un instituto.

  • La letra del piso de una vivienda.

  • Indicar si un alumno se ha presentado al examen.

  • Un refrán.

3.2. Asignación y recuperación del valor almacenado en una variable

Cuando se declara una variable se realiza una reserva de memoria de tantas celdillas como sean necesarias para guardar los datos y además nos da el "control" de la información de esas celdillas a través del nombre simbólico asociado. Pero ¿qué significa controlar? Significa que podemos hacer dos cosas:

  1. Por un lado, se puede guardar información acorde al tipo de dato, usando la instrucción de asignación:

    identificador = <valor>;

    donde el valor <valor> puede ser un valor literal o el resultado de una expresión.

    El proceso de asignación siempre es:

    • primero se evalúa el lado derecho de =,

    • para a continuación guardar el resultado en la porción de memoria asociada a identificador.

  2. Por otro lado, se puede recuperar la información mencionando al identificador en una expresión o instrucción. Los lugares de la expresión donde se mencione al identificador quedarán sustituidos por el valor que almacene.

Ejemplo 2. Guardando información

Continuando con el listado anterior, podemos hacer las siguientes asignaciones:

1 2 3 4 5 6 7 8 9 10 11 12 13
void setup() { ... // Ver ejemplo anterior variableEntera = 10; // Asigna un valor entero (no tiene decimales) variableReal = 10.5; // Asigna un valor real (tiene decimales) variableCaracter = 'a'; // Un carácter tiene comillas simples variableBooleana = true; // Sus únicos valores son true o false variableString = "Hola"; // Un String guarda cadenas alfanuméricas. }

Las instrucciones que se muestran asignan valores a las variables.

Observa que la asignación es acorde al tipo de dato: los enteros son números sin decimales, los reales son números con decimales, los caracteres usan comillas simples, un booleano solo toma valores true o false y un string es una secuencia de caracteres entre comillas dobles.

Debes recordar cómo se asignan valores a una variable. Depende del tipo de dato.
Ejemplo 3. Guardando y recuperando información en un variable real

Considera ahora el siguiente programa:

1 2 3 4 5 6 7 8 9 10 11
void setup() { // Declaración de una variable numérica real float calificacion; (1) // Guardando información en la variable calificacion = 8.5; (2) // Recuperando la información de la variable print("Tu nota final es : "); (3) println( calificacion+1.5 ); (4) }
1 Instrucción que declara la variable con nombre simbólico calificacion para almacenar números reales. Con esta instrucción se identifican 4 celdas de memoria con el nombre de calificacion.
2 Instrucción de asignación. Guarda en las celdas de memoria identificadas con calificacion el valor 8.5.
3 Ejecuta la instrucción de imprimir en la consola de texto una cadena de caracteres.
4 Ejecuta la instrucción de imprimir en la consola de texto el resultado de una expresión numérica. Para ello recupera la información almacenada en la porción de memoria asociada a la variable calificacion.

Observa la expresión calificacion+1.5:

  • Es numérica porque consta de dos operandos: uno es el número 1.5 y el otro es la variable calificacion que fue declarada de tipo número real.

  • Al ser una expresión numérica será evaluada de acuerdo al orden de precedencia de sus operadores.

  • Como uno de los operandos menciona al identificador calificacion, entonces se recupera la información y se sustituye el identificador por su valor.

  • Por todo lo anterior, la expresión numérica calificacion+1.5 da el mismo resultado que la expresión 8.5+1.5 (cuyo valor es 10.0).

Processing dispone de dos variables importantes que quedan declaradas e inicializadas en todo sktech.

  • width es una variable entera que almacena el ancho de la ventana gráfica.

  • height es una variable entera que almacena el alto de la ventana gráfica.

Importante

En programación hay una patrón de asignación que se repite muchísimo: la instrucción a = a+b;.

Matemáticamente hablando la expresión anterior es imposible para 2 valores no nulos, pero se debe a que el significado de = en matemáticas no es el de asignar sino el de comparar. En programación, la expresión equivalente a la "expresión matemática" a = a+b es la "expresión informática" a == a+b y esta última expresión, al igual que en matemáticas, es imposible para dos valores no nulos.

Pero volviendo a la instrucción de asignación a = a+b;, supuesto que a almacena el valor 2 y b el valor 5, esta instrucción realiza los siguientes pasos:

  1. Evaluamos la expresión del lado derecho de =

    • En el lado derecho se mencionan a las variables a y b, por lo que se sustituyen los valores que almacenan en dicha expresión.

    • La expresión a+b es equivalente a escribir 2+5

    • El resultado de la expresión numérica es 7.

  2. El resultado del lado derecho se almacena en la variable del lado izquierdo del símbolo =.

    • En a se almacena el valor 7.

En otras palabras, antes de ejecutar la instrucción de asignación, la variable a almacenaba el valor 2; pero tras ejecutar la instrucción de asignación, la variable a "almacena" el valor 7.

Las instrucciones de declaración y asignación se pueden simplicar en una sola línea. Este código

float calificacion;
calificacion = 8.5;

es equivalente a este otro:

float calificacion = 8.5;
  1. Copia el siguiente programa en el editor local de tu PDE. No lo ejecutes.

  2. Predice qué hará el programa comentando después de cada punto y coma qué hace cada instrucción. Indica también qué crees que representa cada variable.

    1 2 3 4 5 6 7 8 9 10 11
    float comida = 130; float impuesto = 0.21; float propina = 5.15; float disponible = 150; comida = comida + comida * impuesto + propina; print("La comida ha costado: "); println(comida); print("Me sobró :"); println(disponible - comida);
  3. Explica claramente qué hará la línea 6.

  4. Ejecuta ahora tu programa en Processing y compáralo con tu resultado teórico.

  5. Cuando tengas tu resultado numérico compáralo con el mio

  6. ¿Qué crees que está pasando para que no coincidan los resultados?

Una pista. Estas páginas HTML usan processingJS que es una lenguaje que coincide con muchísimas de las instrucciones de Processing, pero no son exactamente el mismo lenguaje. Entre otas cosas, hay algunas diferencias entre los tipos de datos de Processing y los de ProcessingJS.

Como has podido ver en la ejecución del programa anterior, al infitrión les faltan euros para pagar la comida. Así que vamos a crear una variable que repsenta lo que aportan los comensales para que no falte dinero. Haz las siguientes modificaciones.

  1. Añade una nueva variable en la línea 5, llamada ayuda, y que represente lo que los invitados aportan a la cantidad disponible del anfitrión (pagador).

  2. Suma su valor en la expresión de la línea 11 para que imprima el valor 0.

  3. Añade al final del programa las líneas necesarias para que se muestre el mensaje "Gracias a la ayuda de xx euros.", siendo xx el valor que deberás asignar a ayuda en la línea 7.

  4. Compara tu resultado con el mío.

4. Constantes

En programación se distingue un tipo particular de variable.

Una constante es una variable para la que solo se puede hacer una única asignación.

Si se quisiera hacer más de una asignación durante la ejecución del programa, el lenguaje de programación nos avisará de que estamos cometiendo un error.

La única diferencia que existe entre una variable y una constante se encuentra en sus declaraciones. En Processing consisten en añadir la palabra final al principio de la instrucción de declaración, siendo el patrón más general el siguiente:

final tipo_de_dato identificador = <valor>;

Además, por convenio, el identificador de una constante consta de todas sus letras en mayúsculas, mientras que el de una variable (no constante) su identificador consta, en principio, de todas las letras en minúsculas. En el caso de que el identificador de la variable quiera representar a varios conceptos/adjetivos/…​ entonces se acuerda en empezar el segundo y sucesivos conceptos/adjetivos/…​ en mayúsculas.

Ejemplo 4. Ejemplo de declaraciones: Constante vs Variable (no constante)
1 2 3
final float PI = 3.1415; // Es una constante porque empieza por 'final'. float radio = 4.5; // Es una variable con asignación de literal. float perimetroCircunferencia = 2*PI*radio; // Variable con asignación del resultado de una expresión.

Processing también tiene sus propias constantes que quedan declaradas e inicializadas en todo sketch.

Algunas de estas constantes son QUARTER_PI, HALF_PI, PI y TWO_PI para representar a los valores \(\pi/4\), \(\pi/2\), \(\pi\) y \(2\pi\) respectivamente.

  • Haz un programa con función principal que calcule el volumen de un cilindro y las superficies del mismo a partir de su radio y altura que son datos guardados en sendas variables.

  • Completa el programa para determinar cuántos metros cuadrados necesitas de hojalata para hacer 100 botes de conserva de 30cm de alto y 10cm de ancho.

Compara tu solución con la mía

5. Depuración de programas

Lo normal es que en un programa se hagan muchísimos cálculos para resolver un problema y para saber si nuestro programa se está ejecutando correctamente necesitamos saber con exactitud cuál es el valor de las variables en cualquier momento. Sacar una foto fija del estado de las variables en una etapa de su ejecución recibe el nombre de estado del programa.

La traza de un programa es la secuencia de estados por los que pasa un programa.
El estado de un programa es la lista de valores que tienen todas las variables del programa en un instante de tiempo.

Para conocer el estado de un programa se utiliza una tabla de seguimiento, que presenta el siguiente aspecto:

Table 1. Aspecto general de una tabla de seguimiento
Nº Línea Var 1 Var 2 …​ Var n

1

…​

2

…​

…​

…​

  • En cada celda de la tabla se colocará el valor de la variable Var i tras haber ejecutado la línea t-ésima.

  • Si la variable no tuviese asignado ningún valor se pondrá una línea horizontal --.

  • Si la variable tuviese asignado un valor pero no sabemos cuál se usará un símbolo diferente a --; p.e. '?', *, …​

  • En su caso se emulará el comportamiento del programa sobre la pantalla gráfica dibujándola en papel.

Para completar la tabla de seguimiento nos puede ayudar la ventana de depuración de Processing. Hay que seleccionar Depuración > Activar depurador (mira el manual para saber cómo se utiliza). Será fundamental que aprendas a usar la ventana de depuración porque es el único modo de saber por qué un programa puede estar dando soluciones erroneas.

También existen herramientas on-line como http://www.pythontutor.com/visualize.html que si bien no nos sirve directamente para Processing, se puede adaptar facilmente el código fuente de Processing al leguaje Java y entonces podremos usar esta herramienta.

Ejemplo 5. Ejemplo de traza de un programa

La traza del programa

1 2 3 4 5
int a; int b; a=1; b=3; a=a+b;

es el siguiente:

Nº Línea

a

b

1

 — 

2

 — 

 — 

3

1

 — 

4

1

3

5

4

3

Realiza la traza del siguiente programa:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
// Fórmula de Heron: // Calcular área a partir de los lados de un triángulo. float a = 3; float b = 4; float c = 5; float semiPerimetro = 1.0/2; float area =1; semiPerimetro = semiPerimetro*(a+b+c); area = area * semiPerimetro ; area = area * (semiPerimetro - a) ; area = area * (semiPerimetro - b) ; area = area * (semiPerimetro - c) ; area = sqrt(area); println("Area : " + area);

Compara tu resultado con el mío.

6. Repasa y memoriza

  • Una variable en programación consta de dos componentes: un identificador y una porción de memoria.

  • Para usar una variable hay que indicar su tipo de dato.

  • Los tipos de datos se clasifican en simples (numéricos, carácter y booleano) y compuestos (formados por agrupación de simples como el tipo String).

  • La instrucción de declaración de variable <tipo_de_dato> identificador; establece:

    • El identificador de la variable.

    • Cuántas porciones de memoria se van a utilizar.

    • Qué tipo de información se guardará: números, caracteres, …​

    • Qué operaciones podré hacer (sumas, multiplicaciones, …​).

  • La instrucción de asignación de valor a una variable identificador = <valor>; siempre evalúa primero la expresión <valor> y después el resultado lo guarda en la variable identificador.

  • La expresión de asignación a = a + b es muy importante en programación y no se puede tener dudas sobre su uso.

    • Primero evalúa la expresión del lado derecho, "extrayendo" de la memoria los valores de las variables a y b para después evaluar la expresión valor_almacenado_en_a + valor_almacenado_en_b,

    • y el resultado se guarda en la porción de memoria resevado a a.

  • En Processing, para saber si un programa está funcionando correctamente hemos de hacer una tabla de seguiemiento utilizando la ventana de depuración.