// Author:shizhixin
// Email:szhixin@gmail.com
// Blog:http://blog.csdn.net/shizhixin
// Date:2012-06-06
// Note:关于两数交换三种方法的思考
#include <iostream>
using namespace std;
//最简单的两个数交换操作
void swap1(int& a, int& b)
{
int tmp;
tmp = a;
a = b;
b = tmp;
}
//利用了一个数与另外一个数两次异或等于原来的数的原理,
//或者可以理解为b^b肯定是等于零
//比如a = a^b^b
void swap2(int& a, int& b)
{
a = a^b;
b = a^b;
a = a^b;
//开始不改变ab的值,分开写可能更容易理解
//int c = a^b;
//d = c^b;//右边相当于a^b^b,这等于原来的d = a
//e = (a^b)^(a^b^b)//右边相当于a^b^a,也就是e=b了
}
/*关于存不存在溢出问题,个人理解应该不存在溢出造成的交换错误问题,
因为a+b如果溢出的话,a就是一个负数,但从二进制的角度上考虑,
在计算机存的二进制还是正常加操作,只是表示出来是用负数的补码表示。
所以a-b的操作对于二进制方面没有影响。
比如:为了便于计算,我们用四位表示一个数(第1位为符号位),超出算溢出。
a =7=0111 b=6=0110,则a+b表示为:
0111
+0110
————
1101 ----- -5,即6+7本来应该是等于13,但是因为只有四位表示,输出为-5
下面做a-b,即1101 - 6,相当于加上-6,补码表示为1010,即:
1101
+1010
————
10111 ----- 最高位1溢出,则0111表示7,也就是a的值了。同样能正确得到b的值
*/
void swap3(int& a, int& b)
{
a = a+b;
b = a-b;
a = a-b;
//这个应该比较容易理解,分开写如下
//int c = a+b;
//int d = c-b = a+b-b,也就是原来的a了
//int e = c-d = a+b-d = (a+b)-(a+b-b)其实也就是b
}
void main()
{
int a = 11;
int b = 21;
cout<<"a="<<a<<" b="<<b<<endl;
swap1(a,b);
cout<<"swap1:"<<a<<" "<<b<<endl;
swap2(a,b);
cout<<"swap2:"<<a<<" "<<b<<endl;
swap3(a,b);
cout<<"swap3:"<<a<<" "<<b<<endl;
int c = 0x7fffffff;//0111 1111 ....能表示的最大正数
int d = 0x7ffffff0;//0111 .... 0000比较大正数
cout<<"c="<<c<<" d="<<d<<endl;
swap3(c,d);
cout<<"swap3:"<<c<<" "<<d<<endl;
}
关于两数交换三种方法的思考
最新推荐文章于 2023-02-07 18:06:11 发布