I know the working of XOR,
Console.WriteLine(1^1); // returns 0
results to
00000001
00000001
--------
00000000
but how does this return 2?
Console.WriteLine(-(-1^1)); // returns 2
I know the working of XOR,
Console.WriteLine(1^1); // returns 0
results to
00000001
00000001
--------
00000000
but how does this return 2?
Console.WriteLine(-(-1^1)); // returns 2
-1 is stored as a value with all bits set to 1. If we are staying on your 8 bits example, -1 would then be equal to 11111111. So -1^1
gives the following:
11111111
00000001
--------
11111110
Which is equal to -2. When you invert it with another minus, you get 2.
Negative numbers are stored in a way we call two's complement of the number. If you want to compute it quickly in your head, you can just flip all the bits of the positive equivalent of your number, and add one to it. So for -1:
1: 00000001
--------
11111110
+ 1
--------
-1: 11111111
Explaining why -1 is stored as 11111111.
If you want to understand two's complement a bit more, this question may also help you.
This expression is interpreted by the compiler as:
-((-1)^1)
which is: - ((11111111) XOR (00000001)) = -(11111110) = - (-2) = 2
To understand why the compiler chooses -((-1)^1)
instead of -(-(1^1))
, take a look at this article about C# operators precedence. The most relevant piece is that the unary -
operator (the bolded one: -( - 1^1) ) has a higer precedence than the XOR operator ^
. Therefore the negation happens before XOR, and we end up with -((-1)^1)
.
I am using 8 bits per integer here. Normally you should expect 32 or 64 bits per number, but in this case it is irrelevant;
To better understand why 11111111 is -1, and 11111110 is -2, read more about two's complement - https://en.wikipedia.org/wiki/Two%27s_complement. In short, you treat all the bits apart from the left-most, as consecutive powers of 2. The leftmost bit is treated as the next-power, but negative.
Example:
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
Negative numbers are represented as a binary complement, i.e.
-x == ~x + 1
So we have
-(-1 ^ 1) ==
-(0b11111...1111 ^ 1) ==
-(0b11111...1110) ==
2
I'm assuming signed Int32
s.
-1 11111111111111111111111111111111 (two's complement)
1 00000000000000000000000000000001
-----------------------------------------
-1^1 11111111111111111111111111111110
-(-1^1) 00000000000000000000000000000010 --> 2
See C# operator precedence and two's complement.
In binary using two's complement;
11111111^00000001=11111110
.
Binary two's complement 11111110
is decimal -2
.
-1
is 11111111
(check two's complement for that)
when you make a xor with 1
which is 00000001
you have :
11111110
which is -2
(again two's complement)
To well understand two's complement (mathematics can be quite abstract), here is what I keep in mind :
0
= 00...00
1
= 00...001
...
max - 1
= 011...110
max
= 011...11
min
= 100...00
min + 1
= 100...001
...
-1
= 11...11
Obviously, min
and max
depend on the number of bits you use to represent your integers
int has 32 bits.
-1 is equals to 1111 1111 1111 1111 1111 1111 1111 1111
1 is equals to 0000 0000 0000 0000 0000 0000 0000 0001
so -1 ^ 1 equals to 1111 1111 1111 1111 1111 1111 1111 1110
which is equals to -2
so (-(-1^1)) = 2
look at bit representations for integers and floating points numbers for more information.