简体   繁体   English

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

[英]What does bitwise XOR (exclusive OR) mean?

I'm trying to understand the binary operators in C# or in general, in particular ^ - exclusive or .我试图了解 C# 中的二元运算符或一般情况下的二元运算符,特别是^ - exclusive or

For example:例如:

Given an array of positive integers.给定一个正整数数组。 All numbers occur even number of times except one number which occurs odd number of times.除一个数字出现奇数次外,所有数字都出现偶数次。 Find the number in O(n) time and constant space.在 O(n) 时间和常数空间中找到数字。

This can be done with ^ as follows: Do bitwise XOR of all the elements.这可以用 ^ 完成,如下所示:对所有元素进行按位异或。 Finally we get the number which has odd occurrences.最后我们得到出现奇数的数字。

How does it work?它是如何工作的?

When I do:当我做:

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

What's actually happening?到底发生了什么? What are the other bit magics?其他位魔术是什么? Any reference I can look up and learn more about them?我可以查找并了解有关它们的任何参考资料吗?

I know this is a rather old post but I wanted simplify the answer since I stumbled upon it while looking for something else.我知道这是一篇相当古老的帖子,但我想简化答案,因为我在寻找其他东西时偶然发现了它。
XOR (eXclusive OR/either or), can be translated simply as toggle on/off. XOR (eXclusive OR/either or),可以简单翻译为切换开/关。
Which will either exclude (if exists) or include (if nonexistent) the specified bits.这将排除(如果存在)或包括(如果不存在)指定的位。

Using 4 bits (1111) we get 16 possible results from 0-15:使用 4 位 (1111),我们从 0-15 得到 16 种可能的结果:

 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)

The decimal value to the left of the binary value, is the numeric value used in XOR and other bitwise operations, that represents the total value of associated bits.二进制值左边的十进制值是 XOR 和其他按位运算中使用的数值,表示相关位的总值。 See Computer Number Format and Binary Number - Decimal for more details.有关详细信息,请参阅计算机编号格式二进制数 - 十进制

For example: 0011 are bits 1 and 2 as on, leaving bits 4 and 8 as off.例如: 0011是第 1 位和第 2 位打开,第 4 位和第 8 位关闭。 Which is represented as the decimal value of 3 to signify the bits that are on, and displayed in an expanded form as 1+2 .它表示为十进制值3以表示打开的位,并以扩展形式显示为1+2


As for what's going on with the logic behind XOR here are some examples至于 XOR 背后的逻辑是怎么回事,这里有一些例子
From the original post从原来的帖子

2^3 = 1 2^3 = 1

  • 2 is a member of 1+2 (3) remove 2 = 1 2 是1+2的成员(3)删除 2 = 1

2^5 = 7 2^5 = 7

  • 2 is not a member of 1+4 (5) add 2 = 1+2+4 (7) 2 不是1+4的成员(5)加 2 = 1+2+4 (7)

2^10 = 8 2^10 = 8

  • 2 is a member of 2+8 (10) remove 2 = 8 2 是2+8 (10)的成员 删除 2 = 8

Further examples更多示例

1^3 = 2 1^3 = 2

  • 1 is a member of 1+2 (3) remove 1 = 2 1 是1+2的成员(3)删除 1 = 2

4^5 = 1 4^5 = 1

  • 4 is a member of 1+4 (5) remove 4 = 1 4 是1+4的成员(5)删除 4 = 1

4^4 = 0 4^4 = 0

  • 4 is a member of itself remove 4 = 0 4是自己的成员 remove 4 = 0

1^2^3 = 0 1^2^3 = 0
Logic: ((1^2)^(1+2))逻辑:((1^2)^(1+2))

  • (1^2) 1 is not a member of 2 add 2 = 1+2 (3) (1^2) 1 不是 2 的成员 add 2 = 1+2 (3)
  • (3^3) 1 and 2 are members of 1+2 (3) remove 1+2 (3) = 0 (3^3) 1 和 2 是1+2的成员(3)删除1+2 (3) = 0

1^1^0^1 = 1 1^1^0^1 = 1
Logic: (((1^1)^0)^1)逻辑:(((1^1)^0)^1)

  • (1^1) 1 is a member of 1 remove 1 = 0 (1^1) 1 是 1 的成员 remove 1 = 0
  • (0^0) 0 is a member of 0 remove 0 = 0 (0^0) 0 是 0 的成员 删除 0 = 0
  • (0^1) 0 is not a member of 1 add 1 = 1 (0^1) 0 不是 1 的成员 add 1 = 1

1^8^4 = 13 1^8^4 = 13
Logic: ((1^8)^4)逻辑:((1^8)^4)

  • (1^8) 1 is not a member of 8 add 1 = 1+8 (9) (1^8) 1 不是 8 的成员 add 1 = 1+8 (9)
  • (9^4) 1 and 8 are not members of 4 add 1+8 = 1+4+8 (13) (9^4) 1 和 8 不是 4 的成员 add 1+8 = 1+4+8 (13)

4^13^10 = 3 4^13^10 = 3
Logic: ((4^(1+4+8))^(2+8))逻辑:((4^(1+4+8))^(2+8))

  • (4^13) 4 is a member of 1+4+8 (13) remove 4 = 1+8 (9) (4^13) 4 是1+4+8的成员(13)删除 4 = 1+8 (9)
  • (9^10) 8 is a member of 2+8 (10) remove 8 = 2 (9^10) 8 是2+8的成员(10)删除 8 = 2
  • 1 is not a member of 2 +8 (10) add 1 = 1+2 (3) 1 不是2的成员 +8 (10)加 1 = 1+2 (3)

4^10^13 = 3 4^10^13 = 3
Logic: ((4^(2+8))^(1+4+8))逻辑:((4^(2+8))^(1+4+8))

  • (4^10) 4 is not a member of 2+8 (10) add 4 = 2+4+8 (14) (4^10) 4 不是2+8 (10)的成员 add 4 = 2+4+8 (14)
  • (14^13) 4 and 8 are members of 1+4+8 (13) remove 4+8 = 1 (14^13) 4 和 8 是1+4+8的成员(13)删除4+8 = 1
  • 2 is not a member of 1 +4+8 (13) add 2 = 1+2 (3) 2 不是1 +4+8 (13)的成员 add 2 = 1+2 (3)

To see how it works, first you need to write both operands in binary, because bitwise operations work on individual bits.要了解它是如何工作的,首先您需要将两个操作数都写成二进制,因为按位运算对单个位起作用。

Then you can apply the truth table for your particular operator.然后您可以为您的特定运算符应用真值表 It acts on each pair of bits having the same position in the two operands (the same place value).它作用于两个操作数中具有相同position(相同位值)的每一对位。 So the leftmost bit (MSB) of A is combined with the MSB of B to produce the MSB of the result.因此, A的最左边位 (MSB) 与B的 MSB 相结合,产生结果的 MSB。

Example: 2^10 :示例: 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

And the result is 8.结果是8。

The other way to show this is to use the algebra of XOR;证明这一点的另一种方法是使用 XOR 的代数; you do not need to know anything about individual bits.您不需要了解任何有关单个位的信息。

For any numbers x, y, z:对于任何数字 x、y、z:

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

XOR is associative: x ^ (y ^ z) == (x ^ y) ^ z XOR 是关联的: x ^ (y ^ z) == (x ^ y) ^ z

The identity is 0: x ^ 0 == x恒等式为 0: x ^ 0 == x

Every element is its own inverse: x ^ x == 0每个元素都是它自己的逆: x ^ x == 0

Given this, it is easy to prove the result stated.鉴于此,很容易证明所陈述的结果。 Consider a sequence:考虑一个序列:

a ^ b ^ c ^ d...

Since XOR is commutative and associative, the order does not matter.由于 XOR 是可交换和结合的,因此顺序无关紧要。 So sort the elements.所以对元素进行排序。

Now any adjacent identical elements x ^ x can be replaced with 0 (self-inverse property).现在任何相邻的相同元素x ^ x都可以替换为0 (自逆属性)。 And any 0 can be removed (because it is the identity).并且可以删除任何0 (因为它是标识)。

Repeat as long as possible.尽可能重复。 Any number that appears an even number of times has an integral number of pairs, so they all become 0 and disappear.任何出现偶数次的数都有整数对,所以都变成0消失。

Eventually you are left with just one element, which is the one appearing an odd number of times.最终你只剩下一个元素,也就是出现奇数次的元素。 Every time it appears twice, those two disappear.每次它出现两次,那两个就消失了。 Eventually you are left with one occurrence.最终你只剩下一次。

[update] [更新]

Note that this proof only requires certain assumptions about the operation.请注意,此证明仅需要对操作进行某些假设。 Specifically, suppose a set S with an operator .具体来说,假设一个集合 S 带有一个运算符. has the following properties:具有以下属性:

Assocativity: x. (y. z) = (x. y). z结合性: x. (y. z) = (x. y). z x. (y. z) = (x. y). z x. (y. z) = (x. y). z for any x , y , and z in S. x. (y. z) = (x. y). z对于 S 中的任何xyz

Identity: There exists a single element e such that e. x = x. e = x同一性:存在一个元素e使得e. x = x. e = x e. x = x. e = x e. x = x. e = x for all x in S.对于 S 中的所有xe. x = x. e = x

Closure: For any x and y in S, x. y闭包:对于 S 中的任意xyx. y x. y is also in S. x. y也在 S 中。

Self-inverse: For any x in S, x. x = e自逆:对于 S 中的任意xx. x = e x. x = e

As it turns out, we need not assume commutativity;事实证明,我们不需要假设交换性; we can prove it:我们可以证明:

(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)

Now, I said that "you do not need to know anything about individual bits".现在,我说“你不需要了解任何关于单个位的信息”。 I was thinking that any group satisfying these properties would be enough, and that such a group need not necessarily be isomorphic to the integers under XOR.我在想任何满足这些性质的群就足够了,而且这样的群不一定与 XOR 下的整数同构。

But @Steve Jessup proved me wrong in the comments.但是@Steve Jessup 在评论中证明我错了。 If you define scalar multiplication by {0,1} as:如果将 {0,1} 的标量乘法定义为:

0 * x = 0
1 * x = x

...then this structure satisfies all of the axioms of a vector space over the integers mod 2. ...那么这个结构满足整数 mod 2上向量空间的所有公理

Thus any such structure is isomorphic to a set of vectors of bits under component-wise XOR.因此,任何此类结构在分量异或下都同构于一组位向量。

This is based on the simple fact that XOR of a number with itself results Zero.这是基于一个简单的事实,即数字与自身的异或结果为零。

and XOR of a number with 0 results the number itself.和一个数字与 0 的 XOR 结果是数字本身。

So, if we have an array = {5,8,12,5,12}.所以,如果我们有一个数组 = {5,8,12,5,12}。

5 is occurring 2 times. 5 出现 2 次。 8 is occurring 1 times. 8 出现 1 次。 12 is occurring 2 times. 12 出现了 2 次。

We have to find the number occurring odd number of times.我们必须找到出现奇数次的数字。 Clearly, 8 is the number.显然,8 是数字。

We start with res=0 and XOR with all the elements of the array.我们从 res=0 开始,并对数组的所有元素进行 XOR。

int res=0; for(int i:array) res = res ^ i;

    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

The bitwise operators treat the bits inside an integer value as a tiny array of bits .按位运算符将 integer 值中的位视为一个微小的位数组 Each of those bits is like a tiny bool value .这些位中的每一个都像一个微小的bool When you use the bitwise exclusive or operator, one interpretation of what the operator does is:当您使用按位异或运算符时,对该运算符作用的一种解释是:

  • for each bit in the first value, toggle the bit if the corresponding bit in the second value is set对于第一个值中的每一位,如果设置了第二个值中的相应位,则切换该位

The.net effect is that a single bit starts out false and if the total number of "toggles" is even, it will still be false at the end. .net 效果是单个位开始时为false ,如果“切换”的总数是偶数,最后它仍然为false If the total number of "toggles" is odd, it will be true at the end.如果“切换”的总数是奇数,则最后为true

Just think "tiny array of boolean values" and it will start to make sense.想想“boolean 值的微小数组”,它就会开始有意义。

The definition of the XOR (exclusive OR) operator, over bits, is that: XOR(异或)运算符在位上的定义是:

0 XOR 0 = 0
0 XOR 1 = 1
1 XOR 0 = 1
1 XOR 1 = 0

One of the ways to imagine it, is to say that the "1" on the right side changes the bit from the left side, and 0 on the right side doesn't change the bit on the left side.一种想象方式是,右侧的“1”改变左侧的位,右侧的 0 不改变左侧的位。 However, XOR is commutative, so the same is true if the sides are reversed.然而,XOR 是可交换的,所以如果双方颠倒也是如此。 As any number can be represented in binary form, any two numbers can be XOR-ed together.由于任何数字都可以用二进制形式表示,因此任何两个数字都可以异或在一起。

To prove it being commutative, you can simply look at its definition, and see that for every combination of bits on either side, the result is the same if the sides are changed.要证明它是可交换的,您可以简单地查看它的定义,并看到对于任一侧的位的每种组合,如果两侧发生变化,结果都是相同的。 To prove it being associative, you can simply run through all possible combinations of having 3 bits being XOR-ed to each other, and the result will stay the same no matter what the order is.为了证明它是关联的,您可以简单地遍历所有可能的组合,将 3 个位相互异或,无论顺序如何,结果都将保持不变。

Now, as we proved the above, let's see what happens if we XOR the same number at itself.现在,正如我们上面证明的那样,让我们看看如果我们对相同的数字本身进行 XOR 会发生什么。 Since the operation works on individual bits, we can test it on just two numbers: 0 and 1.由于该操作适用于单个位,我们可以仅对两个数字进行测试:0 和 1。

0 XOR 0 = 0
1 XOR 1 = 0

So, if you XOR a number onto itself, you always get 0 (believe it or not, but that property of XOR has been used by compilers, when a 0 needs to be loaded into a CPU register. It's faster to perform a bit operation than to explicitly push 0 into a register. The compiler will just produce assembly code to XOR a register onto itself).所以,如果你对一个数字本身进行 XOR,你总是得到 0(信不信由你,但是 XOR 的这个属性已经被编译器使用,当 0 需要加载到 CPU 寄存器时。执行位操作更快而不是显式地将 0 压入寄存器。编译器只会生成汇编代码以将寄存器异或到自身)。

Now, if X XOR X is 0, and XOR is associative, and you need to find out what number hasn't repeated in a sequence of numbers where all other numbers have been repeated two (or any other odd number of times).现在,如果 X XOR X 为 0,并且 XOR 是关联的,您需要找出在所有其他数字都已重复两次(或任何其他奇数次)的数字序列中没有重复的数字。 If we had the repeating numbers together, they will XOR to 0. Anything that is XOR-ed with 0 will remain itself.如果我们将重复数字放在一起,它们将异或为 0。任何与 0 异或的东西都将保留其自身。 So, out of XOR-ing such a sequence, you will end up being left with a number that doesn't repeat (or repeats an even number of times).因此,在对这样的序列进行异或运算后,您最终会得到一个不重复(或重复偶数次)的数字。

This has a lot of samples of various functionalities done by bit fiddling.有很多通过位摆弄完成的各种功能的示例。 Some of can be quite complex so beware.有些可能非常复杂,所以要小心。

What you need to do to understand the bit operations is, at least, this:要了解位操作,您需要做的至少是:

  • the input data, in binary form输入数据,二进制形式
  • a truth table that tells you how to "mix" the inputs to form the result告诉您如何“混合”输入以形成结果的真值表

For XOR, the truth table is simple:对于 XOR,真值表很简单:

1^1 = 0
1^0 = 1
0^1 = 1
0^0 = 0

To obtain bit n in the result you apply the rule to bits n in the first and second inputs.要获得结果中的第n位,请将规则应用于第一个和第二个输入中的第n个位。

If you try to calculate 1^1^0^1 or any other combination, you will discover that the result is 1 if there is an odd number of 1's and 0 otherwise.如果您尝试计算1^1^0^1或任何其他组合,您会发现如果 1 的个数为奇数,则结果为 1,否则为 0。 You will also discover that any number XOR'ed with itself is 0 and that is doesn't matter in what order you do the calculations, eg 1^1^(0^1) = 1^(1^0)^1 .您还会发现任何与自身异或的数字都是 0,这与您计算的顺序无关,例如1^1^(0^1) = 1^(1^0)^1

This means that when you XOR all the numbers in your list, the ones which are duplicates (or present an even number of times) will XOR to 0 and you will be left with just the one which is present an odd number of times.这意味着当您对列表中的所有数字进行异或时,重复的(或出现偶数次的)将异或为 0,您将只剩下出现奇数次的数字。

As it is obvious from the name(bitwise), it operates between bits.顾名思义(bitwise),它在位之间运行。 Let's see how it works, for example, we have two numbers a=3 and b=4, the binary representation of 3 is 011 and of 4 is 100, so basically xor of the same bits is 0 and for opposite bits, it is 1. In the given example 3^4, where "^" is a xor symbol, will give us 111 whose decimal value will be 7. for another example, if you've given an array in which every element occurs twice except one element & you've to find that element.让我们看看它是如何工作的,例如,我们有两个数字 a=3 和 b=4,3 的二进制表示是 011,4 的二进制表示是 100,所以基本上相同位的 xor 是 0,对于相反的位,它是1. 在给定的示例 3^4 中,其中“^”是一个异或符号,将得到 111,其十进制值为 7。再举一个例子,如果您给出一个数组,其中每个元素都出现两次,除了一个元素&你必须找到那个元素。 How can you do that?你怎么能那样做? simple xor of the same numbers will always be 0 and the number which occur exactly once will be your output. because the output of any one number with 0 will be the same name number because the number will have set bits which zero don't have.相同数字的简单异或将始终为 0,恰好出现一次的数字将是您的 output。因为任何一个数字的 output 与 0 将是相同的名称数字,因为该数字将设置零没有的位.

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM