Anuncios Google

Ayuda con los operadores de bits y los operadores lógicos en C

Hola veréis lo que ocurre es que no entiendo en los operadores de bits a que se refiere a que si el bit 0 es 0 y el bit 1 es 1 el resultado sea uno osea que no entiendo las tablas.

Y en los operadores lógicos si entiendo la sintaxis y todo pero no se para que se podrían utilizar y tampoco entiendo para que se podrían utilizar los operadores de bits.

Agradezco mucho vuestra ayuda.

Saludos.


Anuncios Google

Opciones de visualización de comentarios

Seleccione la forma que prefiera para mostrar los comentarios y haga clic en «Guardar las opciones» para activar los cambios.
Imagen de los2345

Muchisimas gracias!!!!!!!!!!!!!!

Lo he entendido todo, mil gracias almamu. Ahora a practicar lo aprendido antes de seguir  leyendo el  libro.

Saludos.

Imagen de Almamu

De nada

De nada

Imagen de Almamu

Antes de empezar supongo que

Antes de empezar supongo que sabrás que todo número es visto por el ordenador como un conjunto de bits. Un char tiene 8 bits, un short 16, un int 32 y un long 64.

Los operadores de bits son usados para tratar directamente con esos bits que componen un número. Puede parecer algo estúpido, pero conforme vas programando te percatarás de que son más útiles de lo que parece.

Supon que tenemos estos dos números: 230 (1110 0110) y 56 (0011 1000) ambos de 8bits (un char).

Con estos dos números se pueden hacer estas operaciones: AND, OR, XOR y NOR (NOR sólo necesita de un número, más adelante verás porqué).

AND (&)

Es la operación más sencilla de entender, es comparable a la comparación, pero tambien se puede usar para una operación parecida a la resta. Si hacemos un AND con los dos números que he nombrado antes:

1110 0110 = 230

0011 1000 = 56

------------------------ AND (&)

0010 0000 = 32

La forma en la que se calcula el resultado es la siguiente: el ordenador empieza a comparar los bits desde el primero (empezando por la derecha). El ordenador mirará el primer bit del 230 y el 56 y los comparará, si ambos son 1 el ordenador pondrá un 1 en el resultado, en la misma posición; si no pondrá un 0. Esa operación se repite con TODOS los bits que forman ambos números y devolverá el resultado adecuado. Si te fijas en el ejemplo, justo el bit 6 es 1 en ambos números, por lo que el resultado será 32 (0010 0000). Puede parecer dificil de entender, pero es más sencillo de lo que parece.

Aunque este funcionamiento puede parecer estúpido es más util de lo que parece, sobre todo en aplicaciones para dispositivos embedded (con poca memoria). Un ejemplo es, supon que tienes un jugador que puede tener varios estados: Envenenamiento, Paralizado, Durmiendo y Confuso. Para esto lo más lógico para usar sería un bool para saber si está envenendado, paralizado, dormido y/o confuso. Obviamente esto en un PC con tantos gigas de RAM no es una gran pérdida de memoria, pero en un sistema con 4MB (por poner un ejemplo) de RAM o incluso unos pocos KBs, es un gran malgasto, tendrías 4 variables diferentes. Aquí es donde entran los operadores de bits. En una misma variable podrías tener almacenados todos los estados y los podrías comprobar con un operando AND al igual que podrías quitar un estado usando el mismo operando. De esta forma pasas de tener 4 a tener una sola variable y aparte tener espacio para otros cuatro estados más si por alguna razón los necesitases o para cualquier otra cosa. (Todo esto teniendo en cuenta que el estado se almacena en un número de 8bits, la unidad mínima).

 

OR (|)

Es "comparable" a la suma, pero no igual al 100%.

1110 0110 = 230

0011 1000 = 56

------------------------ OR (|)

1111 1110 = 254

Vale, ese número es algo puñetero, xD. De todas formas, esta operacion lo que hace es simple, coje los dos números y empieza a mirar en ambos desde la derecha, si en uno de los dos bits en la misma posición hay un 1 en el resultado tambien habrá un 1. Por eso, como puedes ver al comparar el último bit (por poner un ejemplo) el resultado tiene también el 1. Siguiendo con el ejemplo de los estados se podría decir que serviría para poner a 1 uno o más bits en concreto.

 

XOR (^)

Esta es algo más dificil de entender y yo apenas la he usado, también es dificil dar un ejemplo que se aplique a los estados...

1110 0110 = 230

0011 1000 = 56

------------------------ XOR (^)

1101 1110 = 222

Como todas las anteriores operaciones de bits, el ordenador empieza a comparar desde el primer bit (de la derecha) ambos números. Si en la misma posicion en los dos números está el mismo bit (vamos, que en ambos es 1 o 0) el resultado de ese bit en concreto será 0, en cambio si en un número hay un 0 y en el otro hay un 1 el resultado será 1 para esa posición concreta. Por poner un ejemplo con los estados: en mitad de un combate dos personajes se fusionan en uno solo, si los dos están envenenados actuaría como antídoto (suponiendo obviamente que las reglas del juego sean esas) y el resultado de la fusión dejaría de estar envenenado pero manteniendo los estados anteriores.

 

NOT (~)

1110 0110 = 230

------------------------ NOT (~)

0001 1001 = 25

 

0011 1000 = 56

------------------------ NOT (~)

1100 0111 = 199

Este es más sencillo de entender, símplemente coje uno de los números y le da la vuelta a todos los bits, de forma que lo que obtienes es el número completamente contrario a nivel de bits. Siguiendo el ejemplo de los estados se podría usar en un caso como el siguiente: un rival tiene una habilidad que "invierte" los estados, si el jugador está envenenado y dormido pasaría a estar paralizado y confuso.

Para que quede algo más claro te voy a dejar un ejemplo para que juegues con el lo que quieras.

#include <stdio.h>
 
#define ESTADO_PARALIZADO	0x01 // 0000 0001
#define ESTADO_CONFUSO		0x02 // 0000 0010
#define ESTADO_ENVENENADO	0x04 // 0000 0100
#define ESTADO_DORMIDO		0x08 // 0000 1000
 
void imprimir_estado(char estado)
{
	printf("El estado del jugador (%d) es: ", estado);
 
	if(estado & ESTADO_PARALIZADO)	printf("PARALIZADO ");
	if(estado & ESTADO_CONFUSO)		printf("CONFUSO ");
	if(estado & ESTADO_ENVENENADO)	printf("ENVENENADO ");
	if(estado & ESTADO_DORMIDO)		printf("DORMIDO ");
 
	printf("\n"); // salto de linea
}
 
int main(int argc, char* argv[])
{
	char estado_jugador = ESTADO_PARALIZADO | ESTADO_CONFUSO; // operando OR, el jugador estara paralizado y confuso actualmente
 
	imprimir_estado(estado_jugador);
 
	// vamos a jugar un poco con el estado, primero vamos a eliminarle el estado confuso
	char complementario_confuso = ~ESTADO_CONFUSO; // operando NOT, invierte los bits
	estado_jugador = estado_jugador & complementario_confuso; // teniendo el inverso de ESTADO_CONFUSO (1111 1101) el AND elimina el segundo bit
 
	imprimir_estado(estado_jugador);
 
	// ahora vamos a envenenar al jugador
	estado_jugador = estado_jugador | ESTADO_ENVENENADO;
 
	imprimir_estado(estado_jugador);
 
	// vamos a dejarlo solo envenenado
	estado_jugador = estado_jugador & ESTADO_ENVENENADO;
 
	imprimir_estado(estado_jugador);
 
	// ahora lo vamos a dormir
	estado_jugador = estado_jugador | ESTADO_DORMIDO;
 
	imprimir_estado(estado_jugador);
 
	while(true);
}

No puedo explicarte lo de los comparadores porque ahora mismo no tengo tiempo. Si tienes alguna duda sobre lo que te he explicado no dudes en preguntar ^^.


Imagen de los2345

Gracias...

Me has ayudado mucho a entenderlo y comprendo algunas cosas. Pero otras aun no las entiendo. Porque en un juego imagínate que han paralizado al jugador pero no entiendo porque para paralizarlo hay que usar numeros, no se si me explico. Y tampoco entiendo que en las constantes define has puesto números hexadecimales que si no me equivoco son el equivalente a los números en binario que pones en los comentarios al lado de las constantes. No se porque has puesto ahi esos numeros, no se que significan. Y otra cosa es que no entiendo como con esto puedes hacer que un jugador se envenene en el juego si son números. Agradecería mucho que me aclarases esas cuestiones.

PD: No se los números binarios, es decir no se como es 52 en binario ni nada de eso. ya que en el insti no lo he aprendido. También te agradecería mucho que me enseñases algo de binario.

De nuevo muchísimas gracias por la explicación, te lo has currao.

Saludos.

Imagen de Almamu

Hmmm si nisiquiera tienes una

Hmmm si nisiquiera tienes una base de binario va a ser muy dificil. Para convertir a binario con la misma calculadora de windows te sobra, sólo ponla en modo programador. Sobre los números hexadecimales es una simple costumbre, nada que no se pueda sustituir por números normales, los comentarios como dices es la forma binaria del número que tiene a la izquierda, símplemente lo he puesto para que lo veas de forma más rápida y te puedas dar cuenta cuando se hace alguna operación con bits a estado_jugador cual puede ser el resultado.

A ver, un ordenador todo lo que ve son 0 y 1, nada más y nada menos. Aqui el problema del que no entiendes porque usar números es simplemente porque aún no piensas como un programador. Con esto me refiero, no eres capaz aun de, queriendo hacer cierta cosa, pensarlo como sería en el código. Para ponerlo sencillo, para el estado se usan números porque el ordenador solo entiende de eso, si un jugador está paralizado se usará un 1 (true en bool) para indicar que sí está paralizado, y un 0 (false en bool) para indicar que no lo está. Como podrás ver todo se reduce a 0 y 1.  Normalmente esto lo harías usando bool paralizado = false; y irías cambiando el valor a tu gusto según la necesidad. Lo que hace que realmente el jugador pueda o no moverse no es la variable en sí, si no el código del juego/programa. Aprovecharé para explicarte lo de los operadores lógicos.

Doy por hecho que has entendido lo básico: ||, &&, ! y supongo que no habrás visto aún las condiciones ni bucles, por lo que seré breve en esto para no liarte.

Los comparadores lógicos se usan básicamente para enlazar condiciones. Las condiciones se pueden usar para muchas cosas, pero todo se reduce a comparar el valor de una variable con otra (o un número). Como habrás podido ver en el ejemplo que te he puesto hay una zona en la que hay 4 líneas casi iguales las cuales todas empiezan por if. El if es una condicion, básicamente vendría a ser el "si..." condicional del español.

En el ejemplo que te he puesto he usado IFs básicos por si no los conocías, pero realmente se pueden complicar bastante. Básicamente los operadores lógicos se usan para dar complejidad a un if:

if(paralizado == true)
{
    // aqui habria codigo
}

Éste sería una comparación simple, si paralizado es verdadero (1, true) el ordenador automáticamente pasaría a ejecutar el código que hay entre las llaves que hay justo después del if.

if(paralizado == true && dormido == true)
{
    // aqui habria codigo
}

Aquí entra el operando lógico AND. A diferencia del if superior, el ordenador primero compararía el valor de paralizado, si éste es verdadero pasaría a comprobar el valor de dormido y si finalmente éste es verdadero ejecutaría el código que el if tiene en el interior de las llaves.

La única excepcion sobre los operandos lógicos es el signo de exclamación (!):

if(!paralizado)
{
    // codigo aqui
}

En este caso el codigo dentro del if sólo se ejecutaría si paralizado es falso (0, false) por lo que el signo de exclamación es equivalente a if(paralizado == false)

En un juego o aplicación necesitas saber el estado del jugador, si está paralizado, congelado, dormido, confuso, etc... la única forma que tienes de almacenar esto es usando variables, las variables se reducen a números, que se pueden dividir en muchos 0 y 1; ya sea de forma compacta (usando operandos de bits) o de forma algo más extendida (usando variables completas para cada estado). Una vez tienes el estado del jugador almacenado en algún lado usando if y si es necesario comparadores lógicos puedes comprobar ese estado y que el programa tome uno u otro rumbo, permitiendo simular al personaje y su estado actual. Recuerda, realmente nada existe en el juego, todo son "simulaciones" (por nombrarlas de alguna forma) que tú mismo escribes a base de código, variables y operaciones.

Espero no haberte líado mas y que te quede algo más claro.


Imagen de los2345

Entiendo...

Vale ahora ya si que los operadores lógicos y lo de los ceros y uno lo he entendido, el if si lo conocía de Lua al igual que los booleanos. Ahora en cuanto a lo de binario un amigo que va a otro insti ha dado el binario y me lo explico casi todo excepto la última parte. Te digo la teoría y si me equivoco me corriges: lo que hay que hacer es hacer la descomposición en factores primos de los números que pasar a binario como por ejemplo 52 y después a cada número primo se le asigna un 1 o un 0 pero no se de que depende eso es lo que no me dijo.

Bueno agradecería que me aclarases eso. Y enserio muchísimas gracias, eres un máquina y te lo curras mucho.
Saludos.

Imagen de Almamu

No estoy muy seguro de haber

No estoy muy seguro de haber entendido la explicación. De todas formas te voy a explicar la forma que yo conozco para pasar de deciaml a binario y binario a decimal:

Decimal a binario

Es el más sencillo de todos, se trata de dividir el número entre 2 hasta que el cociente sea menor que 2. Para que te hagas una idea

Una vez tienes hecha la división hay que empezar a cojer 0 y 1. La forma de hacerlo es empezar por el cociente de la última división y ir cojiendo los restos desde la última división a la primera. El cociente será el bit más significativo (es decir, el bit más a la izquierda) y el primer resto el bit menos significativo (bit a la derecha). De esta forma conviertes de decimal a binario.

Binario a decimal

Este es 100 veces más facil. Supon que tenemos el número 10101 en binario. Convertirlo a decimal sería realmente facil. Primero has de saber que cada posición en binario es una potencia de dos (ya que el binario sólo permite los valores 0 y 1, es decir, 2 valores distintos). Sabiendo esto es tan facil como asignar cada lugar a una potencia de dos (empezando por 2 elevado a 0) empezando desde la derecha.

Es así de facil. Esta si no me equivoco es la forma genérica, es decir, puedes aplicarla a hexadecimal y octal cambiando cada 2 por un 8 o 16.


Opciones de visualización de comentarios

Seleccione la forma que prefiera para mostrar los comentarios y haga clic en «Guardar las opciones» para activar los cambios.