Buscar en Google

miércoles, 16 de marzo de 2011

Operaciones Logicas Relacionales

Operaciones lógicas.


Además de las operaciones aritméticas que normalmente conocemos (suma, resta, multiplicación, división). En el mundo digital existen otras operaciones que pueden realizarse con los números. Especialmente si vemos a los números como valores expresados como números en binario.

Como los microcontroladores trabajan en un mundo binario, entonces las operaciones lógicas tienen todo su poder aquí en éste campo. Vamos a ver en éste apartado que estas operaciones permiten realizar tareas que serían muy difícil de lograrlas sin ayuda de las operaciones lógicas.

Las operaciones lógicas en los sistemas digitales son las que se conocen en el mundo de los microcontroladores, y la programación como AND, OR, XOR.

A su vez, en C, las operaciones lógicas tienen dos niveles de trabajo. Uno de los niveles es a nivel bit a bit o bitwise en inglés de los valores que participan. O sólo a nivel resultado, donde la operación sólo maneja un valor posible: verdadero o falso. Estas ultimas se las conoce como operaciones relacionales.

Vamos a ir viendo una por una éstas operaciones, voy a explicar en forma detallada como funcionan, y voy a darles ejemplos prácticos para que puedan descubrir parte del potencial que tiene programar en C utilizando éstas operaciones.

Operadores relacionales: Comparaciones


El primer grupo de operaciones lógicas que vamos a ver, son aquellas que se evalúan para obtener uno de los dos resultados posibles: verdadero o falso.

En C, y en la mayoría de los lenguajes de programación existe una instrucción que realiza una comparación entre dos variables o valores.

Por ejemplo, si tenemos un programa que queremos que tome una decisión sobre como continuar ejecutando las tareas cuando alguna variable tome algún valor determinado. Supongamos que retomamos el programa que habíamos hecho del contador. Supongamos que queremos detener el programa cuando la variable llegue a un valor determinado, por ejemplo 100.




Nuestro programa (todavía sin llegar a código 100% en C ) debería ser :

1-           char A;
2-         char B;
            3-         A=1;
4-         B=A+1;
5-         A=B;
6-         Si A>100 terminar programa
7-         sinó, volver al paso 4

Para nuestro caso, veamos que se agregó una línea de código en el programa, en el paso número 6. Donde preguntamos si el valor que posee la variable A es mayor que 100, que termine el programa. Si no vuelve al paso 4. Esto que les acabo de contar, en C es lo que se conoce como la instrucción if. No quiero apurarme todavía, la instrucción if la vamos a ver más adelante. Les adelanto como sería el programa realizado 100% en C.

char A;
char B;
A=1;
while (true)
{
        B=A+1;
        A=B;
        if (A>100) break;
}


Pero no interesa si no lo entienden completamente aún al programa. No es la intención de confundirlos a ésta altura. Lo que quiero que noten es que se utilizó dentro de una instrucción, la operación A>100

Las operaciones de comparación la función que tienen es devolver un valor 1 si el valor de la comparación es verdadero, y un cero si es falso. Estas operaciones deben ser la más utilizadas en todos los programas, donde se consulta si en algún momento alguna variable ha tomado algún valor, para tomar alguna determinación.

Pero, también las operaciones de comparación, pueden ser utilizadas como operaciones matemáticas, o aritméticas. Pueden resolver problemas matemáticos de forma relativamente  sencilla.

Las operaciones de comparación disponibles en C son:

Operación
Ejemplo
Descripción
Mayor
A > 10
Devuelve como resultado final un 1 si el valor a la izquierda del signo  es mayor que el que está a la derecha.
Menor
A < B
Devuelve como resultado final un 1 si el valor que está a la izquierda del signo es menor que el que valor que está a la derecha del signo.
Igual
A == B
Devuelve como resultado un 1 si los dos valores son iguales.
Diferente
A != B
Devuelve como resultado un 1 si los dos valores son diferentes.

Mayor o igual
 A >= B
Devuelve como resultado un 1 si el valor a la izquierda del signo, es mayor o es igual al valor que está a la derecha.
Menor o igual
A <= B
Devuelve como resultado un 1 si el valor a la izquierda del signo, es menor o es igual al valor que está a la derecha.

Supongamos que  tenemos un programita como el siguiente:

char A;
char B;
char C;

A = 10;
B = 20;

C = A > B;

¿Que valor toma la variable “C”?

Analicemos el programa, en la cuarta línea, se carga la variable A con el valor 10. En la quinta línea se carga la variable B con el valor 20. Entonces, en la sexta línea, se carga la variable C con el resultado de la operación de comparación A>B. El microcontrolador cuando llega a ésta línea de código hace la pregunta ¿Es el valor que hay en A mayor que el valor que hay en B? La respuesta es que no, puesto que A vale 10 y B tiene el valor 20, por lo tanto A no es mayor que B. Entonces, la variable C se cargará con el valor 0. Si la línea hubiese sido declarada con el signo menor (C=A<B) , o la posición de las variables a comparar fuera al revés de como estaba declarada en el programita (C=B>A). El resultado de la comparación hubiera sido afirmativo. Por lo tanto, la variable C se cargaría con un 1.

Para complicarles un poco más las cosas: ¿que pasa si tenemos el siguiente programa?:

signed char A;
signed char B;

A=-10;
B=20;

C = A < B > A;

Esto que se ve “raro”, está permitido en C. Como vemos, el C permite muchas cosas. A veces esas cosas las escribimos apropósito. Otras por error en el concepto en la programación, o por error en el tipeo. Cuando lo que escribimos es apropósito, aquí es donde se ve la potencia del C. Cuando fue un error, acá aparece una complicación, puesto que a lo mejor no detectamos fácil cuando hay un problema. No importa si tiene o no sentido el ejemplo. Lo que quiero mostrarles son las posibilidades que permite el lenguaje para hacer este tipo de cosas.

En el ejemplo que les doy: C=A<B>A; veamos que sucede.

Al igual que las operaciones aritméticas, en las operaciones de comparación y las operaciones lógicas hay prioridades de procesamiento. En éste caso los signos < y > tienen el mismo nivel de prioridad, por lo tanto, no sabemos a ciencia cierta cual de los dos evaluará primero.

Supongamos que el compilador comienza por la primera comparación de la derecha, ésto es A < B. O sea, el compilador preguntará si -10 es menor que 20. El resultado será verdadero. Por lo tanto en el paso siguiente, el compilador preguntará si 1 es mayor que -10. Resultado que también es verdadero. Por lo tanto, la variable C se cargará con el valor 1.

No voy a seguir explayando más con éste ejemplo. No tiene sentido darle más vueltas, sólo mostrarles que existe la posibilidad de este tipo de usos.

Operaciones relacionales  AND &&, OR ||, y NOT !


Ahora bien, supongamos que tenemos que realizar dos comparaciones. Por ejemplo, para ejecutar una condición, tenemos que saber si una variable es mayor a cierto valor, pero además otra variable es mayor a otro valor.

Para ello, existen las operaciones lógicas AND, OR, y NOT. Recordar que estamos hablando en éste capítulo de las operaciones lógicas a nivel de resultado, y no bitwise que la veremos en un próximo apartado.

La operación lógica AND significa lo que en español conocemos como la conjunción “y”. Cuando tenemos que realizar dos comparaciones de dos valores, y queremos que ambas comparaciones sean afirmativas, recién ahí evaluamos el resultado como afirmativo. En C la operación lógica AND se representa por dos signos ámpersan (&&) consecutivos. Donde evalúa si ambos valores que están a la derecha e izquierda de los signos && son diferentes de cero, entonces colocará como resultado un 1. En cambio, si cualquiera de los valores a la derecha del signo es igual a cero, entonces el resultado de la operación será cero.

Por ejemplo, la siguiente operación:

A = 10;
B = 20;
C=30;
D=40;

R=(A<B) && (C<D);

La primera tarea del microcontrolador será reemplazar las variables por su valor:

R=(10<20) && (30<40)

Ahora, como hay paréntesis en la instrucción. Los paréntesis tienen mayor prioridad que la operación &&. En realidad, los paréntesis siempre tienen máxima prioridad. Por lo tanto se evalúan las comparaciones que están dentro de ambos paréntesis. Como observamos, ambas comparaciones son positivas. Entonces, el microcontrolador reemplaza el resultado de las operaciones de comparación y vuelve a evaluar:

R = 1 && 1

Ahora, como dijimos en la definición de la operación AND, ésta devuelve un 1 cuando ambos valores a la derecha e izquierda son diferentes de cero. Por lo tanto, el resultado será:

R = 1

Recordemos que este tipo de operación AND, cuando se colocan dos signos && consecutivos, es evaluación a nivel de resultado. Va a ser diferente de la operación AND a nivel bit a bit. No perder de vista que el doble signo, sólo devuelve 0 o 1.

También es posible, evaluar en un programa, de manera sencilla cuando hay dos variables que son diferentes de cero:

A=10;
B=20;

C= A && B;

En éste caso, de nuevo la variable C va a ser igual a 1, ya que la variable A es diferente de cero. Y la variable B también es diferente de cero. Por lo tanto el resultado es uno. Si cualquiera de las dos variables es igual a cero, el resultado será cero.

Así como existe la operación AND (&&), existe la operación OR (||) que se representa por dos signos consecutivos conocidos como more, (es el palito vertical que en los teclados españoles está al lado del 1).

La operación OR, significa que devuelve un valor afirmativo o uno, cuando cualquiera de los dos valores a la derecha o izquierda del doble símbolo || es diferente de cero. Si ambos valores están en cero, entonces el resultado será también cero.

La operación NOT, que se representa por el signo “!” ( fin de exclamación). Significa inversión. Y funciona cambiando el resultado. Cuando el valor que está después del signo exclamación es diferente de cero, la operación devuelve un cero. Cuando el valor es igual a cero, la operación devuelve un 1.

En las siguientes tablas se muestran los funcionamientos de las operaciones lógicas que hemos visto hasta ahora:

AND           Símbolo utilizado: &&         Sintaxis:   A && B
Donde A y B pueden ser variables de cualquier tipo, valores, o resultados de comparaciones del tipo nn1>nn2, nn1==nn2.
A
B
Resultado
0
0
0
0
Diferente de cero
0
Diferente de cero
0
0
Diferente de cero
Diferente de cero
1


OR           Símbolo utilizado: ||         Sintaxis:   A || B
Donde A y B pueden ser variables de cualquier tipo, valores, o resultados de comparaciones del tipo nn1>nn2, nn1==nn2.
A
B
Resultado
0
0
0
0
Diferente de cero
1
Diferente de cero
0
1
Diferente de cero
Diferente de cero
1




NOT           Símbolo utilizado: ¡         Sintaxis:   ¡A
Donde A puede ser una variable de cualquier tipo, valor numérico, o resultados de comparaciones del tipo nn1>nn2, nn1==nn2.
A
Resultado
0
1
Diferente de cero
0



Más ejemplos prácticos de como usar estos  operadores lo vamos a ver nuevamente en detalle cuando veamos las instrucciones if, while, y for. Que son instrucciones donde se usan normalmente estas operaciones lógicas. Todavía sin llegar a esas instrucciones, puedo darles un ejemplo práctico para que tengan una idea de como utilizarlas.

Supongamos que tenemos que hacer un programa que haya que implementar un contador en una variable A, tal cual lo hemos visto en ejemplos anteriores. Pero, ahora queremos hacer una variable D, que se ponga en 1 cuando la variable del contador A sea igual a los valores 10, 30, 40, y cuando esté entre los valores 70 y 80.

Veamos como se puede solucionar éste problema, con sólo una línea de programa. El programa que realizaría dicha tarea puede ser:

char A;
char B;
char D;

A=1;
                                                           Paso 5:
B=A+1;
A=B;
D=(A==10) || (A==30) || (A==40) || ( (A>=70) && (A<=80));

Volver al paso 5;

Analicemos el programa que les acabo de mostrar. Hasta la línea 7, el programa no presenta dificultades, es el mismo contador que hablamos ya un par de veces anteriormente. Pero aparece esta línea nueva, que es la que evalúa y coloca valores en la variable D:

D=(A==10) || (A==30) || (A==40) || ( (A>=70) && (A<=80));

Veamos, cuando la variable A, no es igual a ninguno de los valores en la comparación: 10,30, 40 los 3 primeros términos que están en las 3 primeras comparaciones, serán igual a cero, puesto que ninguna de las comparaciones será verdadera. Como la operación entre ellas, está vinculada como una OR, entonces, el resultado seguirá siendo cero.

Veamos la segunda parte de la comparación: ( (A>=70) && (A<=80))

Supongamos que la variable A valga en un determinado momento el valor 5. Entonces, tenemos la primera comparación que tiene como resultado falso, puesto que A no es mayor que 70. La segunda comparación tiene como resultado verdadero, puesto que A si es menor que 80. Sin embargo, las dos comparaciones A>=70 y A<=80 están vinculadas por una operación lógica AND. Como uno de los dos términos está dando falso en su comparación, la función AND pondrá un cero a su salida, porque para que de verdadero, tienen que estar los dos términos dando también verdadero, o un valor distinto de cero.

Por lo tanto, para cualquier valor de A, que no sea: 10, 30, 40, y que no esté entre 70 y 80, el resultado en la variable D será un cero.

Ahora, cuando A sea igual a 10, o 30, o 40. Una de las comparaciones A==10, A==30, A==40 se hará verdadera, por lo tanto, a su salida colocará un uno. Como la vinculación entre las comparaciones se hace por una operación OR, el resultado será un 1.

Cuando A sea mayor o igual que 70 y también menor o igual que 80. Las dos comparaciones que están como último término en la instrucción se harán verdaderas. Por lo tanto, el resultado de la operación AND será verdadero, y a su salida colocará un uno. Dicho uno, está a su vez vinculado con otra operación OR, por lo tanto, no importa en que valores están las otras comparaciones. El resultado será un uno.

Como podemos ver, en una sola instrucción, pudimos hacer lo que se llama una función matemática, discreta, que toma valores en puntos exactos.

Además, es posible combinar operaciones matemáticas con operaciones lógicas, para así lograr infinitas combinaciones. El C es muy flexible, nos permite por ejemplo reescribir en el mismo programa una línea como la siguiente:

D=(A==10) + 2* (A==30) + 3*  (A==40) + 4 * ( (A>=70) && (A<=80));

Veamos que hace ésta línea:

-       Cuando A no vale 10, 30, 40 ni está entre 70 y 80, todas las comparaciones valen cero. Multiplicadas por cualquier cosa, sigue siendo cero. Por lo tanto la suma tiene como resultado el valor cero.
-       Cuando A vale 10, el único termino que vale 1 es el primero, los demás valen cero. Un 1 sumado con ceros, da como resultado 1. Por lo tanto, cuando A es igual a 10, D =1
-       Cuando A vale 30, el término A==30 vale 1, 1 multiplicado por 2 es igual a 2. Los otros términos se evalúan y dan cero como resultado. Entonces, cuando A = 30, D =2
-       Cuando A vale 40, el termino A==40 es el único verdadero, que a su salida se multiplica por 3, por lo tanto, D=3
-       Finalmente, cuando A vale un valor entre 70 y 80, el último término es verdadero, como su resultado es 1, y se multiplica por 4. El resultado entonces será 4.

A
D
10
1
30
2
40
3
70 hasta 80
4
otro valor
0

No hay comentarios:

Publicar un comentario