Math 按位异或(异或)是什么意思?

Math 按位异或(异或)是什么意思?,math,language-agnostic,bit-manipulation,operators,xor,Math,Language Agnostic,Bit Manipulation,Operators,Xor,我试图理解C#中的二进制运算符,或者特别是一般的二进制运算符 例如: 给定一个正整数数组。除一个数字出现奇数次外,所有数字都出现偶数次。求O(n)时间和常数空间中的数字 这可以通过使用^完成,如下所示:对所有元素执行按位异或。最后我们得到出现奇数的数字 它是如何工作的 当我这样做时: int res=2^3; res=1; int res=2^5; res=7; int res=2^10; res=8; 到底发生了什么?其他的魔法是什么?我可以查找并了解更多有关它们的参考资料吗?要了解其工作原

我试图理解C#中的二进制运算符,或者特别是一般的二进制运算符

例如:

给定一个正整数数组。除一个数字出现奇数次外,所有数字都出现偶数次。求O(n)时间和常数空间中的数字

这可以通过使用^完成,如下所示:对所有元素执行按位异或。最后我们得到出现奇数的数字

它是如何工作的

当我这样做时:

int res=2^3;
res=1;
int res=2^5;
res=7;
int res=2^10;
res=8;

到底发生了什么?其他的魔法是什么?我可以查找并了解更多有关它们的参考资料吗?

要了解其工作原理,首先需要以二进制形式写入两个操作数,因为逐位操作对单个位起作用

然后,您可以为您的特定操作员申请。它作用于两个操作数中具有相同位置(相同位值)的每对位。因此,
A
的最左边位(MSB)与
B
的MSB组合以生成结果的MSB

示例:
2^10

    0010 2
XOR 1010 8 + 2
    ----
    1    xor(0, 1)
     0   xor(0, 0)
      0  xor(1, 1)
       0 xor(0, 0)
    ----
 =  1000 8

结果是8。

按位运算符将整数值内的位视为微小的位数组。这些位中的每一位都像一个微小的
bool
值。使用逐位异或运算符时,对运算符作用的一种解释是:

  • 对于第一个值中的每个位,如果设置了第二个值中的对应位,则切换该位
净效果是一个位开始时为
false
,如果“切换”的总数为偶数,则最后仍为
false
。如果“切换”的总数为奇数,则最后将为
true


只要想想“布尔值的微小数组”,它就开始有意义了。

另一种方法是使用异或代数;您不需要知道任何关于单个位的信息

对于任意数字x、y、z:

XOR是可交换的:
x^y==y^x

异或是关联的:
x^(y^z)==(x^y)^z

标识为0:
x^0==x

每个元素都是它自己的倒数:
x^x==0

鉴于此,很容易证明所述结果。考虑一个序列:

a^b^c^d…

因为XOR是可交换的和结合的,所以顺序并不重要。因此,对元素进行排序

现在,任何相邻的相同元素
x^x
都可以替换为
0
(自反转属性)。任何
0
都可以删除(因为它是标识)

尽可能长地重复。任何出现偶数次的数字都有整数对,因此它们都变为0并消失

最终,只剩下一个元素,即出现奇数次的元素。每次它出现两次,那两个就消失了。最终,你只剩下一件事

[更新]

请注意,此证明仅要求对操作进行某些假设。具体地说,假设具有运算符
的集合S具有以下属性:

关联性:
x。(y.z)=(x.y)。z
用于S中的任何
x
y
z

标识:存在单个元素
e
,因此
e。x=x。e=x
表示S中的所有
x

闭包:对于S中的任何
x
y
x。y
也在S中

自逆:对于S中的任何
x
x。x=e

事实证明,我们不需要假设交换性;我们可以证明:

(x . y) . (x . y) = e  (by self-inverse)
x . (y . x) . y = e (by associativity)
x . x . (y . x) . y . y = x . e . y  (multiply both sides by x on the left and y on the right)
y . x = x . y  (because x . x = y . y = e and the e's go away)
现在,我说“你不需要知道任何关于单个比特的事情”。我认为任何满足这些性质的群就足够了,这样的群不一定与XOR下的整数同构

但是@Steve Jessup在评论中证明了我错了。如果将{0,1}的标量乘法定义为:

0 * x = 0
1 * x = x
…那么这个结构满足mod 2上的所有整数

因此,任何这样的结构都同构于组件式异或下的一组位向量。

异或(异或)运算符在位上的定义是:

0 XOR 0 = 0
0 XOR 1 = 1
1 XOR 0 = 1
1 XOR 1 = 0
想象一下,右边的“1”会改变左边的位,右边的0不会改变左边的位。然而,XOR是可交换的,因此如果边是相反的,则情况也是如此。 因为任何数字都可以用二进制形式表示,所以任何两个数字都可以异或运算在一起

为了证明它是可交换的,您可以简单地查看它的定义,并看到对于任意一侧的每一个位组合,如果两侧发生变化,结果是相同的。为了证明它是关联的,您可以简单地运行所有可能的组合,让3位彼此异或,结果将保持不变,无论顺序是什么

现在,正如我们证明的那样,让我们看看如果我们对同一个数本身进行异或会发生什么。由于该操作在单个位上工作,因此我们可以在两个数字上测试它:0和1

0 XOR 0 = 0
1 XOR 1 = 0
因此,如果你将一个数字XOR到它本身,你总是得到0(信不信由你,但是当需要将0加载到CPU寄存器时,编译器已经使用了XOR的属性。执行位操作比显式地将0推入寄存器要快。编译器只会生成汇编代码将寄存器XOR到它本身)

现在,如果X或X是0,并且XOR是关联的,那么您需要找出在一个数字序列中哪些数字没有重复,而所有其他数字都重复了两次(或任何其他奇数次)。如果我们把重复的数字放在一起,它们将异或为0。任何与0异或的内容都将保留其自身。所以,通过XOR来实现这样一个序列
1^1 = 0
1^0 = 1
0^1 = 1
0^0 = 0
 decimal | binary | bits (expanded)
       0 | 0000   | 0
       1 | 0001   | 1
       2 | 0010   | 2
       3 | 0011   | (1+2)
       4 | 0100   | 4
       5 | 0101   | (1+4)
       6 | 0110   | (2+4) 
       7 | 0111   | (1+2+4)
       8 | 1000   | 8
       9 | 1001   | (1+8)
      10 | 1010   | (2+8)
      11 | 1011   | (1+2+8)
      12 | 1100   | (4+8)
      13 | 1101   | (1+4+8)
      14 | 1110   | (2+4+8)
      15 | 1111   | (1+2+4+8)
    1st Iteration: res = 0^5 = 5
    2nd Iteration: res = 5^8 
    3rd Iteration: res = 5^8^12
    4th Iteration: res = 5^8^12^5 = 0^8^12 = 8^12
    5th Iteration: res = 8^12^12 = 8^0 = 8