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