2009-09-22 23 views
6
for (unsigned int i = 1; i <= 100; i++) { 
    if (i & 0x00000001) { 
     std::cout << i<<","; 
    } 
} 

¿por qué (y cómo): if(i & 0x00000001) averiguar el número impar?¿por qué funciona esto? (encontrar el número impar en C++)

+0

Por lo general, está escrito 'I & 0x00000001', con un espacio entre bit a bit y (' 'Y) y el operando. – xtofl

+15

ya sabes, i & 1 también lo hace ... – ypnos

+0

¿hace la diferencia? si hay un espacio o no? (solo pregunta) – Tom

Respuesta

22

0x00000001 es 1 en binario, aunque está escrito en notación hexadecimal (base 16). Esa es la parte 0x.

& es el operador bit 'sabio', que se utiliza para hacer manipulaciones de dígitos binarios (bit).

i & 1 convierte todos los dígitos binarios de i en cero, excepto en el último.

Es fácil convertir el número resultante de 1 bit en booleano, para la evaluación mediante la instrucción if.

El siguiente cuadro muestra los últimos 16 dígitos binarios de i, y lo que les sucede.

i: i in binary:  i & 1 in binary: convert to boolean 
---- ------------------- ------------------- --------------------- 
1 0000000000000001 0000000000000001 true 
2 0000000000000010 0000000000000000 false 
3 0000000000000011 0000000000000001 true 
4 0000000000000100 0000000000000000 false 
5 0000000000000101 0000000000000001 true 
6 0000000000000110 0000000000000000 false 
7 0000000000000111 0000000000000001 true 
8 0000000000001000 0000000000000000 false 
... ...     ...     ... 
99 0000000001100011 0000000000000001 true 
100 0000000001100100 0000000000000000 false 
+0

¿funciona solo para enteros, o esto también funciona para flotadores? Me puse a pensar, porque los flotadores se almacenan de forma diferente en la memoria, pero usando el operador de módulo son convertidos en ints, con '' y 'bit' no hay conversión. – knittl

+0

No puede aplicar operadores bit a bit a números de punto flotante, ya que están representados en un formato específico de plataforma y el formato más comúnmente utilizado no se presta bien a las operaciones en modo bit. – coppro

+0

no puedes? ¿Esto dará como resultado un error de compilación? o simplemente en un comportamiento no especificado? – knittl

21

Está utilizando un operador de bits "y" para enmascarar todo menos el último bit. Si el último bit es un 1, el número es impar. ¿Es eso suficiente explicación?

+4

1, yo personalmente también me encantaría escuchar alguna explicación para el uso de la notación sesquipedalian en lugar de '1' ;-) –

+0

dijo que estaba bien. –

+6

(al póster original) Si no entiende esta respuesta, que es correcta, intente cambiar 5 números pares y 5 números impares a binario. Observe lo que sucede en el último bit y cómo se relaciona con el número que transformó. (Más específicamente, observe lo que sucede cuando el número es par y cuando el número es impar). leer sobre AND bit a bit, así – Malaxeur

13

Cuando vemos los números en la base 10, es fácil decir si un número es divisible entre 10: tiene un 0 en la última posición. El código anterior también ve el dígito en la última posición, pero en la base 2. Si no es cero, el número es no divisible por 2.

+0

+1 por no recomendar intentar y verificar algunos números. –

10

Enmascara el último bit. Si observa cada lugar en la representación binaria de un número (..., 256, 128, 64, 32, 16, 8, 4, 2 y 1), notará que solo el lugar de uno es impar. Todos los demás lugares tienen un valor par, ya sea que los bits estén configurados o eliminados (el cero es par). Y agregar números pares siempre dará un número par. Solo el lugar de ese último determina la paridad del número. La parte i & &0x00000001 solo aísla el lugar de la última.

3

Está haciendo una comparación bit a bit. El bit 0 si Y bit 0 se encuentran a 1, entonces bit 0 de la respuesta = 1.

Viendo que & 0x00000001 es 1, los números con este bit son impares.

0x00000001 = 1 
0x00000010 = 2 
0x00000011 = 3 
etc. 

Así que, si lo hace un AND bit a bit

00000001 AND 
00000001 = 
00000001 (same as true) 

00000010 AND 
00000001 = 
00000000 (same as false) 

00000011 AND 
00000001 = 
00000001 (same as true) 

etc 
2

Los números impares son todos los números de la forma (2 * n + 1) donde n es cualquier número entero (-2, -1,0,1 ....). Entonces, para encontrar un número impar, debe ver si el número entero con el que trabaja tiene ese '+1' en él. Cuando se almacena como un entero sin signo, un número se puede expresar como la suma de potencias de 2: 2^0 + 2^1 + 2^2 + 2^4, etc. La versión binaria del entero sin signo parece un mapa de verdad de tipo: para cada lugar hay un '1' en el número binario, agrega esa potencia de dos al número. Entonces, si comienza en el dígito más a la derecha en la representación binaria del entero sin signo y se mueve hacia la izquierda, cada dígito representa una potencia de dos. Si el dígito es 1, usted agrega esa potencia de dos a la suma corriente y cuando alcanza el final del número binario.

Así: 10001110b se puede convertir en un entero sumando las potencias de dos:

más a la derecha: 2^1 + 2^2 + 2^3 + 2^7: más a la izquierda = 141

El El truco es que el dígito más a la derecha representa 2^0. Esto siempre es 1. Todos los demás dígitos representan números pares. Entonces, en términos de números impares debes encontrar el '+1'. Eso corresponde al dígito más a la derecha. Todos los demás dígitos representan números de la forma '2 * n'. Por lo tanto, para determinar si el número de este formato (entero sin signo) es impar, solo necesita ver si el bit que está más a la derecha es '1'.

La operación realizada en el entero sin signo es una operación AND lógica. Cualquier cosa AND'd con 0 es 0, y 1 AND'd con 1 es 1. Entonces la operación hará que todos los dígitos binarios en la representación entera sin signo sean 0, excepto el dígito binario que representa 2^0 (que es 1). Entonces, la representación binaria de enteros sin signo se reducirá a 0x00000001 si es impar y 0x00000000 si es par.

Nota: Cuando escribo 0x00000000, '0x' significa que es formato hexadecimal. Cada '0' representa cuatro bits. Así es 0x00 hexadecimal para 00000000b escrito en binario, las posibles representaciones binarias entero sin signo resultante después de la AND'ing entero sin signo son:

00000000000000000000000000000000b == 0 y 00000000000000000000000000000001b == 1

2

Antes de decir lo siguiente, primero diré que casi siempre uso la prueba de bits para determinar si un int es impar o par.

Pero, estrictamente hablando, debe usar (i % 2) o ((i % 2) != 0) para determinar es i es impar. Esto funcionará independientemente de la representación de números negativos, mientras que en la máquina de un complemento (-3 & 0x01) devolverá cero (un resultado falso) aunque claramente es impar.

Me doy cuenta de que los machiens que utilizan algo más que dos complementos para representar números negativos son muy, muy raros hoy en día, pero también es cierto que los compiladores compilan universalmente (i % 2) a prueba de todos modos. Y recuerde, generalmente no sigo mis propios consejos aquí, así que eso podría ser una indicación del verdadero valor de esta sugerencia.

0

El operador AND sigue esta tabla de verdad para cada bit:
0 = 0
1 = 0
0 = 0
1 = 1

Dado que los ordenadores trabajar con números en la base 2 y cada bit representa una potencia de dos valores (1,2,4,8,16 ..),
, el bit menos significativo representa el único número impar, independientemente de cuán grande o pequeño sea el valor, y independientemente de si está firmado o no. Dado que el bit resultante solo se establece si ambos operandos tienen ese bit establecido, el resultado es verdadero si y solo si el número es impar.

Ejemplo: 0b1110101 =
(1 * 2^0) + (1 * 2^1) + (0 * 2^2) + (1 * 2^3) +
(0 * 2^4) + (1 * 2^5) + (1 * 2^6) + (1 * 2^7) =
+ 2 + 0 + 8 + 0 + 32 + 64 + 128 = 235
Sin el conjunto de bits menos significativo, el valor sería 234 y, por lo tanto, un número par.

0

por ejemplo, cómo hacemos una Binary Equivalente

0 0 0 0 = 0

0 0 0 1 = 1

0 0 1 0 = 2

0 0 1 1 = 3

para que pueda ver para cualquier ningún extraño. LSB se establece siempre, el mismo que comprobar :)

espero que mi respuesta es clara

Cuestiones relacionadas