que - operadores relacionales c#
¿Por qué negar un valor cambia el resultado cuando se XOR lo hace con 1? (7)
Esta pregunta ya tiene una respuesta aquí:
- ¿Qué es el "Complemento 2"? 20 respuestas
Conozco el trabajo de XOR,
Console.WriteLine(1^1); // returns 0
resultados a
00000001
00000001
--------
00000000
¿Pero cómo vuelve esto 2?
Console.WriteLine(-(-1^1)); // returns 2
-1 se almacena como un valor con todos los bits establecidos en 1. Si continuamos con su ejemplo de 8 bits, -1 sería igual a 11111111. Por lo tanto, -1^1
ofrece lo siguiente:
11111111
00000001
--------
11111110
Que es igual a -2. Cuando lo inviertes con otro menos, obtienes 2.
Los números negativos se almacenan de una manera que llamamos complemento de dos del número. Si desea calcularlo rápidamente en su cabeza, simplemente puede voltear todos los bits del equivalente positivo de su número y agregar uno. Así que para -1:
1: 00000001
--------
11111110
+ 1
--------
-1: 11111111
Explicando por qué -1 se almacena como 11111111.
Si desea comprender un poco más el complemento de dos, esta pregunta también puede ayudarlo.
En binario utilizando el complemento de dos; 11111111^00000001=11111110
. El complemento de dos binarios 11111110
es decimal -2
.
Esta expresión es interpretada por el compilador como:
-((-1)^1)
que es: - ((11111111) XOR (00000001)) = - (11111110) = - (-2) = 2
Para comprender por qué el compilador elige -((-1)^1)
lugar de -(-(1^1))
, eche un vistazo a this artículo sobre la prioridad de los operadores de C #. La pieza más relevante es que el operador unario (el en negrita: - ( - 1 ^ 1)) tiene una prioridad más alta que el operador XOR ^
. Por lo tanto, la negación ocurre antes de XOR, y terminamos con -((-1)^1)
.
Estoy usando 8 bits por entero aquí. Normalmente, debe esperar 32 o 64 bits por número, pero en este caso es irrelevante;
Para comprender mejor por qué 11111111 es -1, y 11111110 es -2, lea más sobre el complemento de dos: https://en.wikipedia.org/wiki/Two%27s_complement . En resumen, se tratan todos los bits separados del extremo izquierdo, como potencias consecutivas de 2. El bit del extremo izquierdo se trata como el siguiente poder, pero negativo.
Ejemplo:
10001100 = 1 * (-(2^7)) + 0 * 2^6 + 0 * 2^5 + 0 * 2^4 + 1*2^3 + 1*2^2 + 1*2^1 + 1*2^0
Estoy asumiendo firmado Int32
s.
-1 11111111111111111111111111111111 (two''s complement)
1 00000000000000000000000000000001
-----------------------------------------
-1^1 11111111111111111111111111111110
-(-1^1) 00000000000000000000000000000010 --> 2
Int tiene 32 bits.
-1 es igual a 1111 1111 1111 1111 1111 1111 1111 1111
1 es igual a 0000 0000 0000 0000 0000 0000 0000 0001
entonces -1 ^ 1 es igual a 1111 1111 1111 1111 1111 1111 1111 1110
que es igual a -2
entonces (- (- 1 ^ 1)) = 2
mire las representaciones de bits para números enteros y puntos flotantes para obtener más información.
Los números negativos se representan como un complemento binario , es decir,
-x == ~x + 1
Entonces tenemos
-(-1 ^ 1) ==
-(0b11111...1111 ^ 1) ==
-(0b11111...1110) ==
2
-1
es 11111111
(marca el complemento de dos para eso) cuando haces un xor con 1
que es 00000001
tienes: 11111110
que es -2
(de nuevo el complemento de dos)
Para entender bien el complemento de dos (las matemáticas pueden ser bastante abstractas), esto es lo que tengo en mente:
0
= 00...00
1
= 00...001
...
max - 1
= 011...110
max
= 011...11
min
= 100...00
min + 1
= 100...001
...
-1
= 11...11
Obviamente, min
y max
dependen de la cantidad de bits que utilice para representar sus números enteros