从一个面试题说起...
一个很经典的答案是通过异或来解决
a=a^b;
b=a^b;
a=a^b;
关键字
[
"异或",
"逻辑运算符",
"乔治·布尔",
"香农"
]
先决条件
0为假,1为真
插曲>>>如果读到"0为假,1为真",心底肯定略过了,这谁都知道的啊...
但是如果是写出来,但是找不到出处.即使常识也不太肯定了...
"^":对应逻辑运算异或(XOR)。
重点在"异",只有[1]XOR[0]或[0]XOR[1]才为1;一真一假即真;
a ^ a = 0 ;
a ^ 0 = a ;
先决条件.出处和推导
0为假,1为真
香农已经知道,数学上有一种逻辑代数系统,叫做布尔逻辑,它得名于英国数学家乔治·布尔(George Boole)。在布尔逻辑中,任何逻辑表达式的计算结果都不是数值,而是“真”、“假”这两种真值。你只需要使用逻辑运算符“与”、“或”、“非”,就可以表达任何你想表达的逻辑语句。
在逻辑中,真值或逻辑值是指示一个陈述在什么程度上是真的。在计算机编程上多称作布尔值。在经典逻辑中,唯一可能的真值是真和假。但在其他逻辑中其他真值也是可能的。
强行补充一波,如果你非要想让"1为假,0为真",请搜索:"负逻辑".
关于真假由来,我只能找这么多了...
a ^ a = 0 ;a ^ 0 = a ;
二进制的运算
0110
^ 0000
------------
= 0110
再来谈下两个变量的交换.
其实虽然变量值还是[a,b]
但是值可能会出现3个的.
举个栗子↓
|a的值|b的值|出现的值|
|:--:|:--:|:--:|
|0|0|[0]|
|0|1|[0,1]|
|9|5|[9,5,12]|
|...|...|...|
第一步a=a^b;此时,相当于将a和b绑定一下关系.
只有两个变量,没有第三者插足,要交换两个变量的值,不绑定关系,不可能凭空交换吧...
数据库角度考虑的话,类似,表A和表B本来是没有关系的,
但是又想交换两个表之间的数据,还不允许有第三张表的出现,
这个时候,更改了表A的结构.增加了一列.(插入这段话,希望不会让不懂的人更晕了...)
从关系角度来看:
1.建立关系a,此时的a已经变了...
2.根据关系,给b赋值为a,b←a,工作完成了50%
3.根据关系,给a赋值为b,a←b.
从更改状态来看:
1.a进化为a(状态1);b保持原状态;
2.b进化成最终状态b(状态1),即:a;
3.a再次进化成最终状态a(状态2),即:b;
从刚开始用3个变量,再用公式推导消除一个变量来看:
此时共有变量[a,b,c]
1.c=a^b;
2.b=a;
//其实到第3步运行之前,a的值是一直没有改变过的,
//所以c^a,可以推导出:(a^b)^a,这个时候要注意了,
//此时的b还是在c中的b,而不是第2步已经改变了值得b.(这不是引用类型...不是第2步b的值改了,c的值也跟着改)
//这个地方不太好理解,中心思想就是:先把a和b的关系放兜里,这个兜就是c,并且能通过一种运算,和未改变的a值,
//来反求出b的值;
3.a=c^a;
先将第2步"b=a;",修改一下
因为a^0 = a;可以写为:b=a^0;
因为b^b = 0;可以写为:b = a^b^b;
再加上括弧;
1.c0=a0^b0;
2.b1=(a0^b0)^b0;
3.a1=(a0^b0)^b1;
其实这个时候,将c替换成a,是完全可以的,
因为c除了第1步被赋值之后,就没有再改过值.
//a0和a1都是变量a,只是为了区分a值改变了一次,就会将a0写为a1
1.a1=a0^b0;
2.b1=a1^b0;
3.a1=a1^b1;
一共3个赋值动作,第1个赋值为了建立关系,剩下2个,就是赤裸裸的交换数据了.
感受一下,a和b,在这个过程中一共值发生了几次变化.
感觉最后两步讲的还是有点模糊,希望哪位大虾给完善下...
GG ... 晚安...
扩展
- 逻辑运算["~","&","|","^"]
编辑时间列表
[1].二〇一六年十一月十五日 18:17:41
[2].贰零贰零年-一月十五号 晚
原文地址:https://www.cnblogs.com/love-zf/p/12199326.html