1 介绍
交换两个变量的值除了引入临时变量,还有通过加减或异或等奇淫技巧来完成,现在来介绍其原理并且推广它们。
2 交换的原理
加减、异或都是可逆运算,现在定义一种可逆运算规则
f
f
f,它的逆运算是
f
−
1
f^{-1}
f−1,不妨设
f
(
a
,
b
)
=
c
f(a,b)=c
f(a,b)=c,则有
f
−
1
(
c
,
a
)
=
b
f^{-1}(c,a)=b
f−1(c,a)=b,则有如下推导,注意我用:=
来表示赋值:
a
:
=
f
(
a
,
b
)
b
:
=
f
−
1
(
a
,
b
)
=
f
−
1
(
f
(
a
,
b
)
,
b
)
=
a
a
:
=
f
−
1
(
a
,
b
)
=
f
−
1
(
f
(
a
,
b
)
,
a
)
=
b
(1)
\begin{aligned} a& :=f(a,b) \\ b& :=f^{-1}(a,b)=f^{-1}(f(a,b),b)=a \\ a& :=f^{-1}(a,b)=f^{-1}(f(a,b),a)=b \end{aligned}\tag{1}
aba:=f(a,b):=f−1(a,b)=f−1(f(a,b),b)=a:=f−1(a,b)=f−1(f(a,b),a)=b(1)
可以看到,最终 a , b a,b a,b交换了两者的值,因此可见只要是逆运算就可以满足要求,比如使用乘除:
a=a*b;
b=a/b;
a=a/b;
我们可以代入数字验证一下,可以发现它也是正确的。
3 交换律的影响
但是,如果你细心点,你会发现既然乘除可以,那为什么要先乘后除,或者干脆使用乘方与开方,因为它们也是一组逆运算,可是当我们这样操作会发现答案是与预期不符的。因为问题出在交换律上。
3.1 f f f与 f − 1 f^{-1} f−1只有一者满足交换律
如果 f ( a , b ) ≠ f ( b , a ) f(a,b)\not= f(b,a) f(a,b)=f(b,a),我们也就能得出 f − 1 ( c , a ) ≠ f − 1 ( c , b ) f^{-1}(c,a)\not=f^{-1}(c,b) f−1(c,a)=f−1(c,b),而公式 ( 1 ) (1) (1) 正是依赖于此的。也可这样想,不妨设 f ( a , b ) = c 1 , f ( b , a ) = c 2 f(a,b)=c_1,f(b,a)=c_2 f(a,b)=c1,f(b,a)=c2,则正确的应该是 f − 1 ( c 1 , a ) = b , f − 1 ( c 2 , b ) = a f^{-1}(c_1,a)=b,f^{-1}(c_2,b)=a f−1(c1,a)=b,f−1(c2,b)=a。所以运算规则 f f f应满足交换律,其逆运算则无要求。
那么,如果 f f f不满足交换律,可以实现交换变量而不引入临时变量吗?答案当然是可以的,不过这就对不同的 f f f就有不同的方法了,因为我们要知道 c 1 c_1 c1与 c 2 c_2 c2的关系,如果 f f f是减法,则 c 1 = − c 2 c_1=-c_2 c1=−c2;如果是除法,则 c 1 = c 2 − 1 c_1=c_2^{-1} c1=c2−1。
3.2 f f f与 f − 1 f^{-1} f−1都不满足交换律
这个条件下很好的例子就是矩阵和幂两种。矩阵涉及左乘、右乘、逆;幂涉及乘方、开方、对数。它们的运算时涉及到三种运算规则的。
以矩阵为例:
A
:
=
A
B
B
:
=
A
B
−
1
=
A
B
B
−
1
=
A
A
:
=
B
−
1
A
=
A
−
1
A
B
=
B
\begin{aligned} A&:=AB\\B&:=AB^{-1}=ABB^{-1}=A\\ A&:=B^{-1}A=A^{-1}AB=B\\ \end{aligned}
ABA:=AB:=AB−1=ABB−1=A:=B−1A=A−1AB=B
幂运算:
a
:
=
a
b
b
:
=
a
b
=
a
b
b
=
a
a
:
=
log
a
a
=
log
a
a
b
=
b
\begin{aligned}a&:=a^b\\b&:=\sqrt[b]{a}=\sqrt[b]{a^b}=a\\a&:=\log_{a}{a}=\log_{a}{a^b}=b\end{aligned}
aba:=ab:=ba=bab=a:=logaa=logaab=b
这种情况下是每种运算规则都是需要用到才能完成交换的。
3.3 f f f与 f − 1 f^{-1} f−1都满足交换律
这个的最好的例子就是异或运算 ⊕ \oplus ⊕,因为它除了自身就满足交换,同时它的逆运算就是自身 f = f − 1 f=f^{-1} f=f−1
a : = a ⊕ b b : = a ⊕ b = a ⊕ b ⊕ b = a a : = a ⊕ b = a ⊕ b ⊕ a = b \begin{aligned}a&:=a\oplus b\\b&:=a\oplus b=a\oplus b\oplus b =a\\a&:=a\oplus b=a\oplus b\oplus a =b\end{aligned} aba:=a⊕b:=a⊕b=a⊕b⊕b=a:=a⊕b=a⊕b⊕a=b
4 总结
主要讲了讲这种变量交换操作的背后原理即推广,但是需要提醒的是在实际应用中,我还是建议通过临时变量来进行交换,上面的操作虽然给人眼前一亮,同时也有理论支持,可应用在实际中还是可能会出现错误,比如溢出,甚至交换变量类型根本就不是数字。我的建议是虽然这很有趣但请不要用。