笔记一 2.1.8异或交换产生的问题

Posted 王玉成的博客

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了笔记一 2.1.8异或交换产生的问题相关的知识,希望对你有一定的参考价值。

博客一放,又是好久没有写了。。。。

前两天买了两本砖头书回来。一本是《深入理解计算机系统》第二版的的中文版,另一本便是《算法导论》第三版的中文版。打算花时间认认真真消化完这两本书。再结合自己几年的工作经验,根据理论,做一些分析,力争找到问题的本源,以及解决办法,多写几句没事,争取把问题讲透。另外一点,便是想把不扎实的知识点,通过阅读这本书,把东西吃透。需要整理的代码,自己扔在csdn的git托管中。今天分析的这个代码的源文件是2.1.8-swap.c,可以参考一下。

今天主要是看到书的2.1.8节,C语言的位运算中。聊到了用异或实现a和b数据交换的问题。实际上这个函数在实际应用上,并没有多少价值,但最主要的是加深原理性的理解。

void swap(int *x, int *y)
    *y = *x ^ *y; 
    *x = *x ^ *y; 
    *y = *x ^ *y; 


说实话,单看这段代码,也不会出现问题。我原来印象出,一直觉得是溢出会产生的问题。但是自己写代码验证过,溢出并没有产生问题。读了文章中,才反应过来这个函数真的会出现问题。但是如果不是看到练习题2-11,我真的还想不到哪儿出了问题。。。。

异或交换的依据是a^b^a = b,然后有一个加法逆元的结论,a^a= 0。我联想起来,用加减去做swap的一个例子。

void swap2(int *x, int *y)
    *x = *x + *y;
    *y = *x - *y;
    *x = *x - *y;

实现原理也跟加法逆元的概念有关。a+b-a = b,同异或a-a = 0 那么,如果不用第三个数,做数据交换,只要他有加法逆元,即这个数与它本身的运算,结果为0。就可以用做数据交换来使用。
看到还有一句话的实现

a = b+a - ( b=a );

实际上也是用了加法逆元的特性,写法不一样,原理是一样的。

也是正因为这一个特性,导致数组逆序时,产生了问题。在逆序的数组为奇数时,最后变成了自己交换。然后a^a=0的副作用这时候就显现出来了。a-a=0的副作用也同样。。。
书中的要求修改的代码,我也改过,仍然放在2.1.8-swap.c这个文件中,可以做参考。规避掉奇数个的数组逆序时产生的问题。

这个问题就分析到这里,后面力争在每一个问题上,都挖出源头。

以上是关于笔记一 2.1.8异或交换产生的问题的主要内容,如果未能解决你的问题,请参考以下文章

算法笔记异或运算的奇妙之处

异或交换两个变量值

leetcode每日一题---面试题 16.01. 交换数字(妙用异或关键字)

C#中通过逻辑^(异或)运算交换两个值隐藏的巨坑!!!

异或问题

为什么三次异或操作可以交换两个数