2011-01-21 23 views
11

~ &^| + << >> son las únicas operaciones que puedo utilizarnegación lógica con sólo operadores de bits (excepto!)

Antes de continuar, esta es una pregunta tarea, he estado atrapado en esto durante un tiempo muy largo.

Mi enfoque original: pensé que! X se podía hacer con el complemento de dos y hacer algo con su inversión aditiva. Sé que probablemente haya un xor aquí, pero realmente no sé cómo abordar esto.

Para el registro: También no puedo usar condicionales, bucles, ==, etc., solo las funciones (bitwise) que mencioné anteriormente.

Por ejemplo:

!0 = 1 
!1 = 0 
!anything besides 0 = 0 
+2

Está seguro de querer que ellos evalúen directamente a 1 y 0, o simplemente lógico verdadero y falso? es decir, ¿es '~ 0' aceptable como verdadero lógico? –

+1

Nota: '+' no es un operador bit a bit. –

+2

Este tipo de ejercicio no tiene sentido porque cualquier * uso * del resultado requiere un condicional que es esencialmente una comparación contra cero. Mi respuesta sería 'if (var); else {/ * su código aquí * /} ' –

Respuesta

0

Suponiendo, por ejemplo, un tipo de 8 bits sin signo:

~(((x >> 0) & 1) 
| ((x >> 1) & 1) 
| ((x >> 2) & 1) 
... 
| ((x >> 7) & 1)) & 1 
+0

Tenemos que trabajar con enteros con signo. – Jay

+0

@Jay - Haz un molde como '* (unsigned *) & i' –

1

el siguiente código de copias cualquier 1 bits a todas las posiciones. Esto mapea todos los no-ceros a 0xFFFFFFFF == -1, dejando 0 en 0. Luego agrega 1, mapeando -1 a 0 y 0 a 1.

x = x | x << 1 | x >> 1 
x = x | x << 2 | x >> 2 
x = x | x << 4 | x >> 4 
x = x | x << 8 | x >> 8 
x = x | x << 16 | x >> 16 

x = x + 1 
+1

En lugar de' x + 1' puedes hacer '~ x'. –

+1

@Chris Lutz: Eso asigna 0 a -1, en lugar de lo requerido 1. – wnoise

-3

Usted sólo puede hacer ~ x & 1 porque produce 1 a 0 y 0 para todo lo demás

+3

~ 2 & 1 == 1 ... –

7

Suponiendo un 32 bits sin signo int:

(((x>>1) | (x&1)) + ~0U) >> 31 

debe hacer el truco

+2

Agradable. Convierte todos los números excepto 0 en "positivo", y luego resta 1, lo que hace que solo 0 sea negativo, y luego extrae el bit de signo. – wnoise

+0

@wnoise: gracias. No pude entender su punto :) – BlackBear

1

Para entero de 32 bits con signo x

// Set the bottom bit if any bit set. 
x |= x >> 1; 
x |= x >> 2; 
x |= x >> 4; 
x |= x >> 8; 
x |= x >> 16; 

x ^= 1; // Toggle the bottom bit - now 0 if any bit set. 
x &= 1; // Clear the unwanted bits to leave 0 or 1. 
2

Suponiendo que x está firmado, debe devolver 0 para cualquier número que no sea cero, y 1 para cero.

Un desplazamiento a la derecha en un entero con signo suele ser un cambio aritmético en la mayoría de las implementaciones (por ejemplo, se copia el bit de signo). Por lo tanto, cambie a la derecha x por 31 y su negación por 31. Uno de esos dos será un número negativo y así desplazado a la derecha por 31 será 0xFFFFFFFF (por supuesto si x = 0 entonces el cambio a la derecha producirá 0x0 que es lo que quiere) . No sabes si x o su negación es el número negativo, simplemente 'o' ellos juntos y obtendrás lo que deseas. Luego agrega 1 y tu bien.

aplicación:

int bang(int x) { 
    return ((x >> 31) | ((~x + 1) >> 31)) + 1; 
} 
+0

Creo que deberías negar en lugar de agregar uno. A saber, '~ ((x >> 31) | ((~ x + 1) >> 31))'. –

+0

En realidad, no. Agregar 1 es correcto. Olvidé que '>>' los cambios son aritméticos en C, no lógicos. Por lo tanto, '>> 31'-ing' 10 ... 00' producirá '11 ... 11', no' 00 ... 01'. –

Cuestiones relacionadas