Calculadora en RobotC

Calculadora1Una calculadora es un artefacto que se utiliza para realizar cálculos, generalmente de tipo aritméticos. Las calculadoras modernas incorporan a menudo un ordenador de propósito general, que ayuda a realizar otro tipo de funciones, como cálculos avanzados, o una mejor memoria. Hoy vamos a mostrar cómo programar una calculadora en RobotC.

Existen varios tipos de calculadoras, como las calculadoras gráficas especializadas en campos matemáticos gráficos como la trigonometría y la estadística, o calculadoras conversoras de medidas, como calculadoras de cambio de moneda, que se actualizan automáticamente gracias a su capacidad de conectarse online. También suelen ser más portátiles que la mayoría de los computadores, si bien algunas PDAs tienen tamaños similares a los modelos típicos de calculadora.

En el pasado, se utilizaban como apoyo al trabajo numérico ábacos, comptómetros, ábacos neperianos, tablas matemáticas, reglas de cálculo y máquinas de sumar. El término «calculador» se usaba para aludir a la persona que ejercía este trabajo, ayudándose también de papel y lápiz. Este proceso de cálculo semimanual era tedioso y proclive a errores. Actualmente, las calculadoras son electrónicas y son fabricadas por numerosas empresas en tamaños y formas variados. Se pueden encontrar desde modelos muy baratos del tamaño de una tarjeta de crédito hasta otros más costosos con una impresora incorporada.

Calculadora en RobotC:

En este programa vamos a implementar una calculadora básica. Para ello hemos usado manejo de botones (leeros el artículo sobre botones y LCD), así como manejo de LCD, manejo de sensores de contacto (cuyo manejo es parecido al de cualquier sensor, revisar este artículo para ver como se definen), y la estructura switch() de C++, la cuál nos permite elegir que trozo de código queremos ejecutar según el valor de una variable.

IMG_2243

Dicha calculadora nos permitirá sumar, restar, multiplicar, dividir, hallar el resto y calcular la potencia. Puesto que la potencia no existe en RobotC, crearemos nosotros mismos una función que la calcule. Además los cuatro sensores de contactos nos ayudarán para elegir mejor que números vamos a operar. El código es el siguiente (aunque lo haya partido en trozos para explicarlo mejor en el programa va todo seguido):

Definición de los sensores:

#pragma config(Sensor, S1, contacto1, sensorTouch)
#pragma config(Sensor, S2, contacto2, sensorTouch)
#pragma config(Sensor, S3, contacto3, sensorTouch)
#pragma config(Sensor, S4, contacto4, sensorTouch)

Aquí definimos a los nombres y puertos de cada sensor.

Función potencia:

float potencia(int x, int y){
float aux = x;
if (y == 0)
aux = 1;
else
for(int i = 2; i <= y; i++)
aux = aux*x;
return aux;
}

La potencia x elevado a y no es mas que x multiplicado por si mismo y – 1 veces. Si el valor de y es 0, la potencia siempre valdrá 1.

Definición de variables:

#pragma platform(NXT)

task main(){
nNxtButtonTask = -2;
bool n1 = false, n2 = false, op = false, positivo = true;
int boton, j = 0, i = 0, opid = 0;
float resultado;

4 – Con este comando decimos al NXT que vamos a usar los botones, de manera que no queremos que enseñe lo que mostraría habitualmente al pulsarlos (como los valores del Bluetooth…). Dependiendo de la versión de RobotC que tengáis esto lo hará automático, o necesitaréis poner esta línea.

5 a 7 – Definimos e inicializamos las variables. Creamos variables booleanas (que pueden tomar valor verdadero (true) o falso (false) para usarlas como condiciones de salida de los bucles.

Elección del primer número:

while(!n1){
if ((boton = nNxtButtonPressed) > 0){
wait1Msec(200);
switch(boton){
case 1: positivo = !positivo;
break;
case 2: positivo = !positivo;
break;
case 3: n1 = true;
break;
}
}
if (SensorValue[contacto1]){
if(positivo)
i++;
else
i--;
wait1Msec(150);
}
if (SensorValue[contacto2]){
if(positivo)
i = i + 10;
else
i = i - 10;
wait1Msec(150);
}
if (SensorValue[contacto3]){
if(positivo)
i = i + 100;
else
i = i - 100;
wait1Msec(150);
}
if (SensorValue[contacto4]){
if(positivo)
i = i + 1000;
else
i = i - 1000;
wait1Msec(150);
}
eraseDisplay();
nxtDisplayCenteredTextLine(2, "Eliga un numero: ");
nxtDisplayCenteredTextLine(4, "%d", i);
if(positivo)
nxtDisplayCenteredTextLine(6, "Modo positivo");
else
nxtDisplayCenteredTextLine(6, "Modo negativo");
wait1Msec(100);
}

2 – Guardamos el identificador del botón que hemos pulsado. El hecho de que tenga que ser mayor que 0 nos libra de que pueda ser un fallo o el botón ESCAPE

3 – Es importante poner un pequeño retardo entre pulsado y pulsado de botón, o cambiaremos varias veces de número ya que el NXT interpretará que hemos apretado el botón muchas veces por haberlo mantenido apretado aunque sea durante muy pocos milisegundos.

4 – Los switch() irán de la siguiente forma: En caso de que apretemos el botón derecho e izquierdo pasaremos a modo positivo o negativo dependiendo del que estemos actualmente, y aprentando el ENTER elegímos el número actual. Por tanto en el case 3: asignamos true a la variable de condición de salida del búcle.

43 – Recordad que %d significa que vamos a escribir un número decimal entero en ese lugar, cuyo valor es el de la siguiente variable que pongamos en esa misma función (en este caso es i).

13, 20, 27 y 34 – Dependiendo de que botón de contacto apretemos aumentaremos (en modo positivo), o disminuiremos (en modo negativo) de más en más el número que estamos eligiendo actualmente.

Elección de la operación:

wait1Msec(300);
eraseDisplay();
nxtDisplayCenteredTextLine(1, "Eliga la ");
nxtDisplayCenteredTextLine(3, "Operacion :");
nxtDisplayCenteredTextLine(5, "Suma");
while(!op){
if ((boton = nNxtButtonPressed) > 0){
wait1Msec(300);
switch(boton){
case 1: if(opid < 5){
opid++;
}else{
opid = 0;
}
break;
case 2: if(opid > 0){
opid--;
}else{
opid = 5;
}
break;
case 3: op = true;
break;
}
eraseDisplay();
nxtDisplayCenteredTextLine(1, "Eliga la ");
nxtDisplayCenteredTextLine(3, "Operacion :");
switch(opid){
case 0: nxtDisplayCenteredTextLine(5, "Suma");
break;
case 1: nxtDisplayCenteredTextLine(5, "Resta");
break;
case 2: nxtDisplayCenteredTextLine(5, "Multiplicacion");
break;
case 3: nxtDisplayCenteredTextLine(5, "Division");
break;
case 4: nxtDisplayCenteredTextLine(5, "Resto");
break;
case 5: nxtDisplayCenteredTextLine(5, "Potencia");
break;
}
}
}

1 – Es también importante poner un pequeño retardo entre selección de número y operación u otro número, ya que si mantenemos el botón ENTER apretado aunque sea por poco tiempo podríamos seleccionar sin querer Suma como la operación deseada.

9 – Como en este switch() queremos que opid valga 0, 1, 2, 3, 4 o 5 si tocamos el botón derecho cuando opid es igual a 5 lo cambiaremos a 0, y si le damos al izquierdo cuando vale 0 lo cambiaremos a 5.

Elección del segundo número:

wait1Msec(300);
while(!n2){
if ((boton = nNxtButtonPressed) > 0){
wait1Msec(200);
switch(boton){
case 1: positivo = !positivo;
break;
case 2: positivo = !positivo;
break;
case 3: n2 = true;
break;
}
}
if (SensorValue[contacto1]){
if(positivo)
j++;
else
j--;
wait1Msec(150);
}
if (SensorValue[contacto2]){
if(positivo)
j = j + 10;
else
j = j - 10;
wait1Msec(150);
}
if (SensorValue[contacto3]){
if(positivo)
j = j + 100;
else
j = j - 100;
wait1Msec(150);
}
if (SensorValue[contacto4]){
if(positivo)
j = j + 1000;
else
j = j - 1000;
wait1Msec(150);
}
eraseDisplay();
nxtDisplayCenteredTextLine(2, "Eliga un numero: ");
nxtDisplayCenteredTextLine(4, "%d", j);
if(positivo)
nxtDisplayCenteredTextLine(6, "Modo positivo");
else
nxtDisplayCenteredTextLine(6, "Modo negativo");
wait1Msec(100);
}

Prácticamente simétrico a la elección del primer número. Se le ha añadido un retardo delante por la misma razón que a la elección de operación.

Cálculo del resultado:

wait1Msec(300);
switch(opid){
case 0: resultado = i + j;
break;
case 1: resultado = i - j;
break;
case 2: resultado = i * j;
break;
case 3: resultado = (float)i / (float)j;
break;
case 4: resultado = i % j;
break;
case 5: resultado = potencia(i,j);
break;
}
eraseDisplay();
nxtDisplayCenteredTextLine(1, "El resultado de ");
nxtDisplayCenteredTextLine(3, "operar %d y %d es: ",i , j);
nxtDisplayCenteredTextLine(5, "%6.2f", resultado);
wait1Msec(5000);
}

En esta última parte calculamos y mostramos el resultado.

9 – Para que el resultado de la división sea con decimales es importante hacer un casting(conversión) a tipo float de los dos valores, ya que los int son números enteros. Para hacer un casting se pone delante de la variable que deseamos convertir el tipo a la que queremos convertirlo entre paréntesis.

13 – Aquí es donde llamamos a la función potencia que nos creamos al principio.

18 – Como veis es posible añadir varios decimales a una línea de texto. El orden será el mismo que el indicado en la parte de texto.

19 – En este caso utilizamos %6.número_decimalesf, que es el símbolo para representar tipos float. Número decimales indica la cantidad de decimales que se mostrarán por pantalla (dos en este caso).

Por ultimo añadir que lo importante de este programa es el uso de los búcles y de las sentencias switch(). Ante cualquier duda podéis escribir en el foro, como siempre.

Comments are closed.