c#使用按位XOR进行交换

时间:2010-10-13 19:58:53

标签: c# algorithm

void swap(ref int x, ref int y)
{       x = x ^ y;   y = y ^ x;   x = x ^ y;  }

我正在学习按位异或。这种交换是如何发生的?这让我大吃一惊。这个方法应该交换X和Y的内容,但我不明白AT ALL会发生什么?

7 个答案:

答案 0 :(得分:7)

当心。这种方法有一个非常讨厌的属性。它被用于其中一项Underhanded C Contest参赛作品。它会愉快地工作......直到有一天有人尝试交换两个数组元素a [i]和[j]之类的东西,而不保证i!= j。

当两个引用都引用相同的变量时,此方法将其归零。

答案 1 :(得分:6)

维基百科对Swap-By-XOR algorithm

有一个很好的解释

该算法有效的形式证据有点涉及,需要使用二进制数的数学属性。

但是在简化形式中,我们可以将二进制值的每个位分开,因为XOR操作独立地作用于每个位。因此,足以证明这适用于1位值,因为通过归纳我们可以证明它适用于任何长度的二进制值。为这些操作构建一个合适的真值表非常简单,所以我把它留下来。

XOR交换不是唯一可能的“创造性”交换算法。使用算术运算可以实现类似的结果:

void Swap( ref int x, ref int y )
{
  x = x + y; 
  y = x - y;
  x = x - y; 
}

从实际角度来看,这是一种在大多数情况下应该避免的技术。正如您自己所认识到的,此方法的逻辑并不是立即明显的,它可能导致可维护性和可扩展性问题......其中最重要的是Swap( ref x, ref x )不会执行方法名称所暗示的事实(实际上它会将值清零)。

答案 2 :(得分:5)

一次只看一点,一步一步。

x|y -> x = x ^ y x|y -> y = y ^ x x|y -> x = x ^ x x|y
0|0              0|0              0|0              0|0
0|1              1|1              1|0              1|0
1|0              1|0              1|1              0|1
1|1              0|1              0|1              1|1

在这里你可以清楚地看到每种情况下的结果都是比特的交换。从这里可以清楚地看出为什么它在一般情况下起作用。可能有更多formal解释。

任何时候你发现自己说“我完全不了解发生的事情”是一个强有力的迹象表明你应该找到一种更清晰的方法来编写与语义等效的代码。

答案 3 :(得分:2)

在大多数现代架构(包括i686和x86_64)上,可以使用单个CPU指令实现

swap()。因此,您最好以编译器可以识别和转换的方式编写它,而不是尝试以实际使代码更慢且可读性更低的方式进行微优化。

答案 4 :(得分:1)

XOR交换很有意思 - 但另一方面 - 它真的比临时成员交换更有效吗?在这种情况下,编译器通常会优化代码。

答案 5 :(得分:1)

首先看看XOR的工作原理:

a | b | a^b
- - - - - -
0 | 0 | 0
1 | 0 | 1
0 | 1 | 1
1 | 1 | 0

因此,如果输入不同,则xor运算的结果为1或为真,如果输入相等,则为0。看待它的另一种方法是将其视为没有进位的加法,我将其表示为(+):

x = x ^ y <=> x = x (+) y;
y = y ^ x <=> y = y (+) x;
x = x ^ y <=> x = x (+) y;

第一步:将x中的0但y中的1的所有位设置为1.现在x中的某些位是错误的,因为如果x中的位为1,则y为'设置为0.其他位是正确的。

第二步:现在将我们在x中设置为1的相同位置设置为y(我们现在用y完成)。这是因为x已经将所有不同的位设置为1,因此与x进行异或现在基本上意味着:切换y中的位,在x中设置为1。我们现在已经完成了:)

第三步:现在我们仍然需要将x中的这些位设置为1,这些位最初已设置为1,并在第一步回到1后重置为0.如何?我们最后一次与X一起XOR x,因为Xor做了什么?如果2个输入不同,它会将位设置为1,这正是我们所需要的。

如果你仍然对它感到困惑,你应该把它画在纸上并播放它以查看它是如何工作的和/或参考Jason在上面所做的表格。

答案 6 :(得分:0)

使用按位运算符交换两个数字: 使用以下 PYTHON 代码:

m,n=map(int,input().split())
m=m^n
n=m^n
m=m^n
print(m,n)

我希望能帮上忙。