三种方式交换两数值
交换两个数的值有三种方式:
- 使用临时变量‘寄存’
- 不使用临时变量,原地加减:缺点是可能存在溢出
- 使用异或
int x = 100;
int y = 200;
//方式1:临时变量
int z= x;
x = y;
y =z;
//方式2:不用临时变量
x = x+y;
y = x-y;
x = x-y;
//方式3:异或。原理:a^b^b = a, 即b^b=0,a^0=a;
x^=y;
y^=x;
x^=y;
比较了下速度,比较让人吃惊的是位运行的速度不是最快的,反而极慢。
int x = 100;
int y = 200;
//方式1:临时变量
int size = Integer.MAX_VALUE;
long s = System.currentTimeMillis();
for (int i = 0; i < size; i++) {
int z= x;
x = y;
y =z;
}
System.out.println(System.currentTimeMillis()-s);
//方式2:不用临时变量
s = System.currentTimeMillis();
for (int i = 0; i < size; i++) {
x = x+y;
y = x-y;
x = x-y;
}
System.out.println(System.currentTimeMillis()-s);
//方式3:异或。原理:a^b^b = a, 即b^b=0,a^0=a;
s = System.currentTimeMillis();
for (int i = 0; i < size; i++) {
x^=y;
y^=x;
x^=y;
}
System.out.println(System.currentTimeMillis()-s);
/*
output:
2
2
2915
*/
可见异或比前两者时间多了近3个数量级
我分别使用三种方式,反编译后如下:
//方式1
public static void main(java.lang.String[]);
Code:
0: bipush 100
2: istore_1
3: sipush 200
6: istore_2
7: iload_1
8: istore_3
9: iload_2
10: istore_1
11: iload_3
12: istore_2
13: return
//方式2:
public static void main(java.lang.String[]);
Code:
0: bipush 100
2: istore_1
3: sipush 200
6: istore_2
7: iload_1
8: iload_2
9: iadd
10: istore_1
11: iload_1
12: iload_2
13: isub
14: istore_2
15: iload_1
16: iload_2
17: isub
18: istore_1
19: return
//方式3:
public static void main(java.lang.String[]);
Code:
0: bipush 100
2: istore_1
3: sipush 200
6: istore_2
7: iload_1
8: iload_2
9: ixor
10: istore_1
11: iload_2
12: iload_1
13: ixor
14: istore_2
15: iload_1
16: iload_2
17: ixor
18: istore_1
19: return:
可见,方式1最简单,只涉及简单的load、store操作
方式2、3的唯一不同在于一个是加减(iadd、isub),一个是异或,异或不是基本的位运算,它是通过与或非三个基本位运算实现的,故执行相对耗时。
总结
我们在使用中应该尽量用临时变量的方式,方式2存在溢出情况,方式3速度跟不上。
不管是从性能上,还是从易读性上方式1都更好些。另外两种都是奇淫技巧,知道就行了。