python中的XOR交换算法?

时间:2010-03-16 05:40:42

标签: python algorithm tuples

我尝试在python中实现XOR swap

x,y= 10,20

x,y,x = x^y,x^y,x^y

print('%s , %s'%(x,y))

输出:

30 , 30

我不是python的新手,但我无法解释这个输出。应该是20,10

引擎盖下发生了什么?

6 个答案:

答案 0 :(得分:15)

首先,创建一个由x^yx^yx^y组成的元组。然后将元组解压缩到xyx,导致两者都绑定到x^y的结果。

让自己避免头痛,并采用Pythonic方式:

x, y = y, x

答案 1 :(得分:10)

正如其他答案所说,对于x, y = y, x而言,如果你对创建和解包元组过敏,那么它可以连续x-oring ...它只需要连续,而不是同时就像你正在做的那样!

>>> x = 1234
>>> y = 3421
>>> x ^= y
>>> y ^= x
>>> x ^= y
>>> print x
3421
>>> print y
1234

xor-swap技巧的关键是三个连续 xors,即在之后一个 - 这个片段中的三个单独的^=语句。当然,它没有任何实际意义,但是,如果你真的热衷于它,它 工作,在Python中像其他地方一样工作; - )。

答案 2 :(得分:3)

您需要转录行的“算法”行。

>>> x, y = 10, 20
>>> x = x ^ y; print x, y
30 20
>>> y = x ^ y; print x, y
30 10
>>> x = x ^ y; print x, y
20 10
>>>

您需要阅读维基百科文章的其余部分,该文章解释了正确的实现阻止了并行操作,并且整个想法几乎没用(至少在现代计算机体系结构上)。

答案 3 :(得分:2)

当你有两个指向可变对象的指针时,XOR交换算法才有意义。 a和b是对不可变整数的两个引用。

编辑(根据请求移动评论并扩展):

Python整数是不可变的。因此,每次使用XOR“修改”一个时,新的存储将被分配(或重新使用,例如用于实习)。这基本上与(例如C)不同,其中swap在不分配新内存的情况下更改值。换句话说,XOR交换不会在C99意义上创建新对象(“执行环境中的数据存储区域,其内容可以表示值”)或Python意义。如上所述here,真正的XOR交换可以“交换变量a和b的值,而不需要为临时变量使用额外的空间。”

或凭经验:

>>> x = 3
>>> y = 5
>>> print "x: ", x, ", id(x): ", id(x), "y: ", y, ", id(y): ", id(y)
x:  3 , id(x):  137452872 y:  5 , id(y):  137452848
>>> x ^= y
>>> print "x: ", x, ", id(x): ", id(x), "y: ", y, ", id(y): ", id(y)
x:  6 , id(x):  137452836 y:  5 , id(y):  137452848
>>> y ^= x
>>> print "x: ", x, ", id(x): ", id(x), "y: ", y, ", id(y): ", id(y)
x:  6 , id(x):  137452836 y:  3 , id(y):  137452872
>>> x ^= y
>>> print "x: ", x, ", id(x): ", id(x), "y: ", y, ", id(y): ", id(y)
x:  5 , id(x):  137452848 y:  3 , id(y):  137452872

在这种情况下,我们看到解释器(2.6.4)似乎是interning the integers,所以x最终得到了原来的内存地址。但重点是交换需要至少一个分配(137452836),并且x和y在整个过程中不保留相同的内存地址。

在C:

int x = 3;
int y = 5;
printf("x: %d, &x: %p, y: %d, &y: %p\n", x, &x, y, &y);
x ^= y;
printf("x: %d, &x: %p, y: %d, &y: %p\n", x, &x, y, &y);
y ^= x;
printf("x: %d, &x: %p, y: %d, &y: %p\n", x, &x, y, &y);
x ^= y;
printf("x: %d, &x: %p, y: %d, &y: %p\n", x, &x, y, &y);

给出:

x: 3, &x: 0xbfd433ec, y: 5, &y: 0xbfd433e8
x: 6, &x: 0xbfd433ec, y: 5, &y: 0xbfd433e8
x: 6, &x: 0xbfd433ec, y: 3, &y: 0xbfd433e8
x: 5, &x: 0xbfd433ec, y: 3, &y: 0xbfd433e8

这是一个真正的XOR交换,因此x和y始终保持相同的内存位置,并且没有临时的。

答案 4 :(得分:1)

您可以使用以下方法轻松完成此交换:

x, y = 10, 20
x, y = y, x
print((x,y))

至于你所看到的行为,我很确定这是因为整个RHS被评估,然后同时被分配到LHS,在这种情况下x^y总是30。

答案 5 :(得分:0)

您可以组合使用-“元组交换”和“ XOR swap”: x,y = x ^ x ^ y,x ^ y ^ y

Python:

x, y = 10, 20
print('Before swapping: x = %s, y = %s '%(x,y))

x, y = x ^ x ^ y, x ^ y ^ y
print('After swapping: x = %s, y = %s '%(x,y))

x, y = 10, 20

print('Before swapping: x = %s, y = %s '%(x,y))
print('After swapping: x = %s, y = %s '%(x ^ x ^ y, x ^ y ^ y))

输出:

Before swapping: x =  10 , y =  20
After swapping: x =  20 , y =  10