萧红 电影:不用临时变量交换两个数的值
来源:百度文库 编辑:九乡新闻网 时间:2024/04/30 09:16:07
不用临时变量交换两个数的值
当要交换两个数的值时,通常的做法是定义一个临时变量,然后再进行交换。那么能不能不用临时变量而交换两个数的值呢?可以的!C语言提供的异或运算就可以实现这样的操作。
异或运算符^也称XOR运算符,它的规则是若参加运算的两个二进位同号,则结果为0(假);异号为1(真)。即0 ^ 0 = 0, 0 ^ 1 = 1, 1 ^ 0 = 1, 1 ^ 1 = 0。
例:
#includeint main(int argc, char *argv[])
{
int a = 2, b = 6; a = a ^ b;
b = b ^ a;
a = a ^ b; printf("a = %d b = %d\n", a, b); return 0;
}
结果如下:a = 6 b = 2
分析:前两个赋值语句:“a = a ^ b;”和“b = b ^ a;”相当于b = b ^ (a ^ b),而b ^ a ^ b等于a ^ b ^ b。b ^ b的结果为0,因为同一个数与相向相^,结果必为0。因此b的值等于a ^ 0,即a,其值为2。再执行第三个赋值语句:“a = a ^ b”。由于a的值等于(a ^ b),b的值等于(b ^ a ^ b),因此,相当于a = a ^ b ^ b ^ a ^ b,即a的值等于a ^ a ^ b ^ b ^ b,等于b。2007.06.02
今天又发现另外两种方法,特补上。
方法一
void swap(int *p, int *q)
{
*p = *p + *q;
*q = *p - *q;
*p = *p - *q;
}
方法二void swap(int *p, int *q)
{
*p = *p + *q - (*q = *p);
}
原理为算术运算符的结合顺序为自左至右。2007.06.18
可以把异或的三条语句压缩为一条:
a ^= b ^= a ^= b;
要交换三个变量的值,可以用以下语句:c = a + c - (a = b, b = c);
2007.09.11谢谢网友cool8jay指出上面红色部分的错误,下面来分析一下,先看一个示例程序,如下:#includeint main(int argc, char *argv[])
{
int a = 1;
int b = 2;
int c = 3; c = a + c - (a = b, b = c); printf("a = %d\n", a);
printf("b = %d\n", b);
printf("c = %d\n", c); return 0;
}
编译运行,结果如下:a = 2 b = 3 c = 2
可见,最初目标中的c = 1部分没能实现。于是分析原因:《The C Programming Language·Second Edition》P205介绍说,“The additive operators + and - group left-to-right”,即附加运算符加号和减号的结合顺序是自左向右;P209介绍说,“A pair of expressions separated by a comma is evaluated left-to-right, and the value of the left expression is discarded. The type and value of the result are the type and value of the right operand”,即逗号表达式的计算顺序是从左向右,逗号左边表达式的值被舍弃,表达式结果的类型和数值是逗号右边表达式的类型和数值。既然如此,那结果应该是正确的,为什么还会出错呢?再来看一下VC6.0下编译产生的汇编代码:7: int a = 1;
00401028 mov dword ptr [ebp-4],1
8: int b = 2;
0040102F mov dword ptr [ebp-8],2
9: int c = 3;
00401036 mov dword ptr [ebp-0Ch],3
10:
11: c = a + c - (a = b, b = c);
0040103D mov eax,dword ptr [ebp-8]
00401040 mov dword ptr [ebp-4],eax
00401043 mov ecx,dword ptr [ebp-4]
00401046 add ecx,dword ptr [ebp-0Ch]
00401049 mov edx,dword ptr [ebp-0Ch]
0040104C mov dword ptr [ebp-8],edx
0040104F sub ecx,dword ptr [ebp-8]
00401052 mov dword ptr [ebp-0Ch],ecx 可以看到,第11行代码的执行过程如下:先把b的值赋给a,再把a和c的值相加,结果放在寄存器ecx中,然后把c的值赋给b,最后再把ecx与b的值相减,结果赋给c。分解为C语句为:a = b; /* a = 2, b = 2 */
ecx = a + c; /* ecx = 5, a = 2, c = 3 */
b = c; /* b = 3, c = 3 */
c = ecx - b; /* c = 2, ecx = 5, b = 3 */ 这下就清楚了,原来程序运行时先把逗号左边表达式的值计算出来丢弃掉,然后再做其它的运算,最开始的错误也就错在了这里。好了,既然上面的式子有问题,那有没有其它正确的方法能一条语句实现三个变量的值的交换呢?不用临时变量顺次交换N个变量的值
有N(N>=2)个变量,不使用临时变量,如何顺次交换它们的值?能否只用一条语句实现?如
+---+---+---+---+---+
| a | b | c | d | e |
+---+---+---+---+---+
| 1 | 2 | 3 | 4 | 5 |
+---+---+---+---+---+
要把它变为
+---+---+---+---+---+
| a | b | c | d | e |
+---+---+---+---+---+
| 2 | 3 | 4 | 5 | 1 |
+---+---+---+---+---+
怎样实现?
首先,我们考虑用异或实现两个变量的交换,可参考我的这篇文章《不用临时变量交换两个数的值》。用C++写函数如下:
int &swap(int &a, int &b)
{
b = b ^ a;
a = a ^ b;
b = b ^ a; return b;
}
然后可以把代码优化为:int &swap(int &a, int &b)
{
b ^= a;
a ^= b;
b ^= a; return b;
}
继续优化,把三句压缩为一句,如下:int &swap(int &a, int &b)
{
b ^= a ^= b ^= a;
return b;
}
还可再优化,如下:int &swap(int &a, int &b)
{
return (b ^= a ^= b ^= a);
}
现在来顺次交换5个变量的值,如下:swap(a, b); //返回bswap(b, c); //返回cswap(c, d); //返回dswap(d, e);
既然有返回值,那么可以写成链式的,如下:swap(a, b); //返回bswap(swap(a, b), c); //返回cswap(swap(swap(a, b), c), d); //返回dswap(swap(swap(swap(a, b), c), d), e);
现在,让我们来把swap函数依次用相应的函数体替换掉,如下:e ^= d ^= e ^= swap(swap(swap(a, b), c), d);e ^= d ^= e ^= d ^= c ^= d ^= swap(swap(a, b), c);e ^= d ^= e ^= d ^= c ^= d ^= c ^= b ^= c ^= swap(a, b);e ^= d ^= e ^= d ^= c ^= d ^= c ^= b ^= c ^= b ^= a ^= b ^= a;
好了,最后一个语句就实现了顺次交换五个变量的值,写程序验证如下:/******************************************************************
* Copyright (c) 2005-2007 CUG-CS
* All rights reserved
*
* 文件名称:xor.c
* 简要描述:实现五个变量的顺次交换
*
* 当前版本:1.0
* 作 者:raincatss
* 完成日期:2007-10-18
* 开发环境:Windows XP Sp2 + VC6.0
* 个人博客:http://raincatss.cublog.cn/
******************************************************************/#include#define PRINT(A) do {\
printf("%d\n", A);\
} while (0)int main()
{
int a = 1;
int b = 2;
int c = 3;
int d = 4;
int e = 5;// b ^= a ^= b ^= a; // swap(a, b)// c ^= b ^= c ^= b; // swap(b, c)// d ^= c ^= d ^= c; // swap(c, d)// e ^= d ^= e ^= d; // swap(d, e)
e ^= d ^= e ^= d ^= c ^= d ^= c ^= b ^= c ^= b ^= a ^= b ^= a; PRINT(a);
PRINT(b);
PRINT(c);
PRINT(d);
PRINT(e); return 0;
}
运行结果如下:2 3 4 5 1
测试结果正确,达到预定目标。知道了五个变量的顺次交换,那么任意多个变量的顺次交换就可以依次推导出来,在此我就不多写了。当然,除了本文介绍的方法外,还有其它方法可以实现不用临时变量交换任意多个变量的值,
当要交换两个数的值时,通常的做法是定义一个临时变量,然后再进行交换。那么能不能不用临时变量而交换两个数的值呢?可以的!C语言提供的异或运算就可以实现这样的操作。
异或运算符^也称XOR运算符,它的规则是若参加运算的两个二进位同号,则结果为0(假);异号为1(真)。即0 ^ 0 = 0, 0 ^ 1 = 1, 1 ^ 0 = 1, 1 ^ 1 = 0。
例:
#include
{
int a = 2, b = 6; a = a ^ b;
b = b ^ a;
a = a ^ b; printf("a = %d b = %d\n", a, b); return 0;
}
结果如下:a = 6 b = 2
分析:前两个赋值语句:“a = a ^ b;”和“b = b ^ a;”相当于b = b ^ (a ^ b),而b ^ a ^ b等于a ^ b ^ b。b ^ b的结果为0,因为同一个数与相向相^,结果必为0。因此b的值等于a ^ 0,即a,其值为2。再执行第三个赋值语句:“a = a ^ b”。由于a的值等于(a ^ b),b的值等于(b ^ a ^ b),因此,相当于a = a ^ b ^ b ^ a ^ b,即a的值等于a ^ a ^ b ^ b ^ b,等于b。2007.06.02
今天又发现另外两种方法,特补上。
方法一
void swap(int *p, int *q)
{
*p = *p + *q;
*q = *p - *q;
*p = *p - *q;
}
方法二void swap(int *p, int *q)
{
*p = *p + *q - (*q = *p);
}
原理为算术运算符的结合顺序为自左至右。2007.06.18
可以把异或的三条语句压缩为一条:
a ^= b ^= a ^= b;
要交换三个变量的值,可以用以下语句:c = a + c - (a = b, b = c);
2007.09.11谢谢网友cool8jay指出上面红色部分的错误,下面来分析一下,先看一个示例程序,如下:#include
{
int a = 1;
int b = 2;
int c = 3; c = a + c - (a = b, b = c); printf("a = %d\n", a);
printf("b = %d\n", b);
printf("c = %d\n", c); return 0;
}
编译运行,结果如下:a = 2 b = 3 c = 2
可见,最初目标中的c = 1部分没能实现。于是分析原因:《The C Programming Language·Second Edition》P205介绍说,“The additive operators + and - group left-to-right”,即附加运算符加号和减号的结合顺序是自左向右;P209介绍说,“A pair of expressions separated by a comma is evaluated left-to-right, and the value of the left expression is discarded. The type and value of the result are the type and value of the right operand”,即逗号表达式的计算顺序是从左向右,逗号左边表达式的值被舍弃,表达式结果的类型和数值是逗号右边表达式的类型和数值。既然如此,那结果应该是正确的,为什么还会出错呢?再来看一下VC6.0下编译产生的汇编代码:7: int a = 1;
00401028 mov dword ptr [ebp-4],1
8: int b = 2;
0040102F mov dword ptr [ebp-8],2
9: int c = 3;
00401036 mov dword ptr [ebp-0Ch],3
10:
11: c = a + c - (a = b, b = c);
0040103D mov eax,dword ptr [ebp-8]
00401040 mov dword ptr [ebp-4],eax
00401043 mov ecx,dword ptr [ebp-4]
00401046 add ecx,dword ptr [ebp-0Ch]
00401049 mov edx,dword ptr [ebp-0Ch]
0040104C mov dword ptr [ebp-8],edx
0040104F sub ecx,dword ptr [ebp-8]
00401052 mov dword ptr [ebp-0Ch],ecx 可以看到,第11行代码的执行过程如下:先把b的值赋给a,再把a和c的值相加,结果放在寄存器ecx中,然后把c的值赋给b,最后再把ecx与b的值相减,结果赋给c。分解为C语句为:a = b; /* a = 2, b = 2 */
ecx = a + c; /* ecx = 5, a = 2, c = 3 */
b = c; /* b = 3, c = 3 */
c = ecx - b; /* c = 2, ecx = 5, b = 3 */ 这下就清楚了,原来程序运行时先把逗号左边表达式的值计算出来丢弃掉,然后再做其它的运算,最开始的错误也就错在了这里。好了,既然上面的式子有问题,那有没有其它正确的方法能一条语句实现三个变量的值的交换呢?不用临时变量顺次交换N个变量的值
有N(N>=2)个变量,不使用临时变量,如何顺次交换它们的值?能否只用一条语句实现?如
+---+---+---+---+---+
| a | b | c | d | e |
+---+---+---+---+---+
| 1 | 2 | 3 | 4 | 5 |
+---+---+---+---+---+
要把它变为
+---+---+---+---+---+
| a | b | c | d | e |
+---+---+---+---+---+
| 2 | 3 | 4 | 5 | 1 |
+---+---+---+---+---+
怎样实现?
首先,我们考虑用异或实现两个变量的交换,可参考我的这篇文章《不用临时变量交换两个数的值》。用C++写函数如下:
int &swap(int &a, int &b)
{
b = b ^ a;
a = a ^ b;
b = b ^ a; return b;
}
然后可以把代码优化为:int &swap(int &a, int &b)
{
b ^= a;
a ^= b;
b ^= a; return b;
}
继续优化,把三句压缩为一句,如下:int &swap(int &a, int &b)
{
b ^= a ^= b ^= a;
return b;
}
还可再优化,如下:int &swap(int &a, int &b)
{
return (b ^= a ^= b ^= a);
}
现在来顺次交换5个变量的值,如下:swap(a, b); //返回bswap(b, c); //返回cswap(c, d); //返回dswap(d, e);
既然有返回值,那么可以写成链式的,如下:swap(a, b); //返回bswap(swap(a, b), c); //返回cswap(swap(swap(a, b), c), d); //返回dswap(swap(swap(swap(a, b), c), d), e);
现在,让我们来把swap函数依次用相应的函数体替换掉,如下:e ^= d ^= e ^= swap(swap(swap(a, b), c), d);e ^= d ^= e ^= d ^= c ^= d ^= swap(swap(a, b), c);e ^= d ^= e ^= d ^= c ^= d ^= c ^= b ^= c ^= swap(a, b);e ^= d ^= e ^= d ^= c ^= d ^= c ^= b ^= c ^= b ^= a ^= b ^= a;
好了,最后一个语句就实现了顺次交换五个变量的值,写程序验证如下:/******************************************************************
* Copyright (c) 2005-2007 CUG-CS
* All rights reserved
*
* 文件名称:xor.c
* 简要描述:实现五个变量的顺次交换
*
* 当前版本:1.0
* 作 者:raincatss
* 完成日期:2007-10-18
* 开发环境:Windows XP Sp2 + VC6.0
* 个人博客:http://raincatss.cublog.cn/
******************************************************************/#include
printf("%d\n", A);\
} while (0)int main()
{
int a = 1;
int b = 2;
int c = 3;
int d = 4;
int e = 5;// b ^= a ^= b ^= a; // swap(a, b)// c ^= b ^= c ^= b; // swap(b, c)// d ^= c ^= d ^= c; // swap(c, d)// e ^= d ^= e ^= d; // swap(d, e)
e ^= d ^= e ^= d ^= c ^= d ^= c ^= b ^= c ^= b ^= a ^= b ^= a; PRINT(a);
PRINT(b);
PRINT(c);
PRINT(d);
PRINT(e); return 0;
}
运行结果如下:2 3 4 5 1
测试结果正确,达到预定目标。知道了五个变量的顺次交换,那么任意多个变量的顺次交换就可以依次推导出来,在此我就不多写了。当然,除了本文介绍的方法外,还有其它方法可以实现不用临时变量交换任意多个变量的值,
不用临时变量交换两个数的值
临时表和表变量的区别
任意两个数乘法的速算法
Vector 变量的使用
设置AutoCAD的系统变量
C51变量内存的优化
步步为营 .NET 代码重构学习笔记 四、临时变量(Temporary Variable)
不用计算针数的三种起针方法(钩编小窍门)
爱是心的交换
生活的交换
交换名片的礼仪
真爱来临时的感觉
真爱来临时的感觉
真爱来临时的感觉
真爱来临时的感觉
shell 利用read与键盘进行交互, 来取得变量的值
史海回眸:中国共产党历史上两个"临时中央"始末
关于"准变量思维"的探索
C语言的变量和常量
下半年影响A股的四个变量
对交换生的看法!
交换机构的重要说明
我的交换生经历
可以“交换妻子”的民族