我知道 XOR 的工作原理,
Console.WriteLine(1^1); // returns 0
结果到
00000001
00000001
--------
00000000
但这如何返回 2?
Console.WriteLine(-(-1^1)); // returns 2
我知道 XOR 的工作原理,
Console.WriteLine(1^1); // returns 0
结果到
00000001
00000001
--------
00000000
但这如何返回 2?
Console.WriteLine(-(-1^1)); // returns 2
-1 存储为所有位设置为 1 的值。如果我们继续使用 8 位示例,则 -1 将等于 11111111。所以-1^1
给出以下内容:
11111111
00000001
--------
11111110
等于-2。当你用另一个减号反转它时,你得到 2。
负数以我们称之为数字补码的方式存储。如果你想在脑海中快速计算它,你可以翻转你的数字的正等值的所有位,然后加一。所以对于-1:
1: 00000001
--------
11111110
+ 1
--------
-1: 11111111
解释为什么 -1 存储为 11111111。
如果您想更多地了解二进制补码,这个问题也可能对您有所帮助。
这个表达式被编译器解释为:
-((-1)^1)
即: - ((11111111) XOR (00000001)) = -(11111110) = - (-2) = 2
要了解编译器选择-((-1)^1)
而不是 的原因-(-(1^1))
,请查看这篇关于 C# 运算符优先级的文章。最相关的部分是一元运算-
符(粗体: -( - 1^1) )比 XOR 运算符具有更高的优先级^
。因此,否定发生在 XOR 之前,我们最终得到-((-1)^1)
.
我在这里使用每个整数 8 位。通常你应该期望每个数字有 32 或 64 位,但在这种情况下它是无关紧要的;
为了更好地理解为什么 11111111 是 -1,而 11111110 是 -2,请阅读有关二进制补码的更多信息 - https://en.wikipedia.org/wiki/Two%27s_complement。简而言之,您将除最左侧之外的所有位视为 2 的连续幂。最左侧的位被视为下一个幂,但为负数。
例子:
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
在二进制中使用二进制补码;
11111111^00000001=11111110
. 二进制二进制补码11111110
是十进制-2
。
-1
是11111111
(检查二进制补码)当你用1
它做一个异或时00000001
你有:
11111110
这是-2
(再次是二进制补码)
为了很好地理解二进制补码(数学可以很抽象),这是我牢记的:
0
=00...00
1
=00...001
...
max - 1
=011...110
max
=011...11
min
=100...00
min + 1
=100...001
...
-1
=11...11
显然,min
并且max
取决于您用来表示整数的位数
int 有 32 位。
-1 等于1111 1111 1111 1111 1111 1111 1111 1111
1 等于 0000 0000 0000 0000 0000 0000 0000 0001
所以 -1 ^ 1 等于1111 1111 1111 1111 1111 1111 1111 1110
等于 -2
所以 (-(-1^1)) = 2
查看整数和浮点数的位表示以获取更多信息。