Operadores con bits - consulta

Iniciado por HRSLASH, 5 Noviembre 2012, 19:14 PM

0 Miembros y 1 Visitante están viendo este tema.

HRSLASH

Hola foreros. Tengo este codigo y lo que quiero es que devuelva 1 si el simbolo pasado a la funcion es alguno de los definidos arriba. Habia pensado en hacerle un corrimiento de bits dependiendo la posicion del bit encendido. por ej >> (int)sqrt(0x3FF % sym + 1) pero el problema es que este metodo no funciona con algunas constantes.. como puedo saber la posicion del bit encendido para moverlo y que si el argumento concuerde con alguna constante devuelva 1?



#define BACKSLASH 0x0001
#define SLASH     0x0002
#define COLON     0x0004
#define ASTERISK  0x0008
#define QUESTION  0x0010
#define QUOTES    0x0020
#define LESS      0x0040
#define GREATER   0x0080
#define PIPE      0x0100

int is_symbol(int sym)
{
    return ((BACKSLASH | SLASH | COLON | ASTERISK | QUESTION | QUOTES | LESS | GREATER | PIPE) & sym);
}



Gracias de antemano!  :D
La televisión es para mi el medio mas instructivo y cultural que conozco, cuando la prenden me voy a leer

naderST

El problema son los valores que puede estar tomando sym, es decir si el valor de sym no es potencia de dos te va a dar problemas

xiruko

#2
return ((BACKSLASH | SLASH | COLON | ASTERISK | QUESTION | QUOTES | LESS | GREATER | PIPE) & sym);

hola, no entiendo muy bien lo que haces pues estas haciendo un OR con todas las constantes. esto se traduce en que las estas sumando a nivel de bit. como ejemplo mas sencillo para que veas lo que pasa, mira esto:

a = 4 = ...0100
b = 6 = ...0110
a | b = 4 | 6 = ...0110 = 6


como veras, no tiene mucho sentido para hacer lo que tu quieres hacer ya que acabas haciendo un AND con algo extraño que no representa nada. ademas, si fuera el caso de que eso fuera correcto, tu funcion seguiria sin devolver 1 o 0, ya que por ejemplo, si el simbolo fuera el QUESTION:

QUESTION=0x10
sym=0x10
QUESTION & sym = 0x10 = 16


asi pues tu funcion devolveria 16. no te olvides que las operaciones a nivel de bit son en paralelo, es decir, el bit 0 de un numero con el bit 0 del otro, el bit 1 con el bit 1, etc.

en lugar de eso, si lo que quieres es que la funcion devuelva 1 cuando coincida con alguna de las constantes, y quieres hacerlo aplicando alguna operacion a nivel de bits, una solucion podria ser esta:

#define BACKSLASH 0x0001
#define SLASH     0x0002
#define COLON     0x0004
#define ASTERISK  0x0008
#define QUESTION  0x0010
#define QUOTES    0x0020
#define LESS      0x0040
#define GREATER   0x0080
#define PIPE      0x0100

#define NUMSYM 9

int is_symbol(int sym) {

int i, symbols[]={BACKSLASH, SLASH, COLON, ASTERISK, QUESTION, QUOTES, LESS, GREATER, PIPE};

for (i=0; i<NUMSYM; i++)
if (symbols[i]^sym == 0) return 1;

return 0;
}


donde uso la operacion XOR que dara 0 si los dos numeros son iguales. como veras es lo mismo que usar en la condicion del if un symbols[ i]==sym, pero lo puse por pedir que fuera con operaciones de bits.

si lo que quieres es que la funcion sea de 1 solo return, esto te podria servir:

int is_symbol(int sym) {

return !(BACKSLASH^sym && SLASH^sym && COLON^sym && ASTERISK^sym && QUESTION^sym && QUOTES^sym && LESS^sym && GREATER^sym && PIPE^sym);
}


aunque sinceramente no se que tan eficiente es respecto a la primera version que es mas facil de entender.

un saludo!

rir3760

Cita de: xiruko en  5 Noviembre 2012, 23:20 PMsi lo que quieres es que la funcion sea de 1 solo return, esto te podria servir:

int is_symbol(int sym) {

return !(BACKSLASH^sym && SLASH^sym && COLON^sym && ASTERISK^sym && QUESTION^sym && QUOTES^sym && LESS^sym && GREATER^sym && PIPE^sym);
}


aunque sinceramente no se que tan eficiente es respecto a la primera version que es mas facil de entender.
Tiene la misma eficiencia. Ello porque en el caso de operador lógico AND si el operando a la izquierda es falso el derecho no se evalúa, en otras palabras la evaluación termina en cuanto uno de los operando en tu expresión sea cero (indicando que coincidió con alguna de las macros).

Cita de: HRSLASH en  5 Noviembre 2012, 19:14 PM
Hola foreros. Tengo este codigo y lo que quiero es que devuelva 1 si el simbolo pasado a la funcion es alguno de los definidos arriba.
Eso implica que se deben cumplir tres condiciones:
1) Ser mayor o igual que 1.
2) Ser menor o igual que 256.
3) Ser una potencia de dos (en binario el numero tiene solo un bit a uno).

Combinando los tres tenemos:
int is_symbol(int x)
{
   return x >= 1 && x <= 256 && (x & x - 1) == 0;
}


Un saludo
C retains the basic philosophy that programmers know what they are doing; it only requires that they state their intentions explicitly.
--
Kernighan & Ritchie, The C programming language

HRSLASH

Muchas gracias a todos por las respuestas! Finalmente me he quedado con la que propuso rir3760 funciona perfecto!!  :D
La televisión es para mi el medio mas instructivo y cultural que conozco, cuando la prenden me voy a leer