敢不敢说你全部能看懂?

时间:2022-06-25 04:43:15
关于整形(int)不使用中间变量相信大家有常用的算法,比如
1最常用的:
public static void main(String[] args) {
int a = 5;
int b = 4;
a = a^b;
b = b^a;
a = a^b;
System.out.print(a + ":" + b);
}
这个是最快的

其次不是很好但是可行的
public static void main(String[] args) {
int a = 5;
int b = 4;
a = a+b;
b = a-b;
a = a-b;
System.out.print(a + ":" + b);
}和
public static void main(String[] args) {
int a = 5;
int b = 4;
a = a * b;
b = a / b;
a = a / b;
System.out.print(a + ":" + b);
}
这2种可能会内存溢出,不建议使用

最后一种,可能大家没看过的,可能是最难理解的:
public static void main(String[] args) {
int a = 5;
int b = 4;
b = a + 0 * (a = b);
System.out.print(a + ":" + b);
}

87 个解决方案

#1


才学,真心不懂求解释

#2


引用 1 楼  的回复:
才学,真心不懂求解释

相信下面会有人解释的

#3


除了最后一种不怎么懂-。-但在以前的帖子里找到了
http://topic.csdn.net/u/20070929/13/97529154-be2f-431e-a2bd-d7ccd048cf77.html
差不多吧?

#4


引用 3 楼  的回复:
除了最后一种不怎么懂-。-但在以前的帖子里找到了
http://topic.csdn.net/u/20070929/13/97529154-be2f-431e-a2bd-d7ccd048cf77.html
差不多吧?

前面的网上很多讲解,而且比较好,没有在说的意思了,最后一个估计比较难找,不过相信会有许多人能解释的

#5


引用 4 楼  的回复:
引用 3 楼  的回复:

除了最后一种不怎么懂-。-但在以前的帖子里找到了
http://topic.csdn.net/u/20070929/13/97529154-be2f-431e-a2bd-d7ccd048cf77.html
差不多吧?

前面的网上很多讲解,而且比较好,没有在说的意思了,最后一个估计比较难找,不过相信会有许多人能解释的
最后一种貌似实际上并不好?底层还是用了个中间变量?

#6


第一种( 按位异或 )我写了这么久代码  基本没这么用过

#7


该回复于2012-08-02 08:32:04被版主删除

#8


算法是好,但是这样是吧自己弄晕。

#9


交换 ab 第一种效率最高了

#10


第三种很难理解吗?只不过用了下赋值,然后又要把赋值后的a去掉就乘0,然后b = a(原值)。话说有点像孔乙己的做法。

#11


最后一种比较有意思,利用编译所生成计算过程的临时变量 和 加法从左到右的结合顺序,来实现了交换。

不过效率未必有第一个高,楼主有时间可以测试看看。

#12


回字的八种写法么

#13


引用 11 楼  的回复:
最后一种比较有意思,利用编译所生成计算过程的临时变量 和 加法从左到右的结合顺序,来实现了交换。

不过效率未必有第一个高,楼主有时间可以测试看看。

这个我知道,第一种最高,只是最后一种特有意思,网上好难看到哦

#14


引用 10 楼  的回复:
第三种很难理解吗?只不过用了下赋值,然后又要把赋值后的a去掉就乘0,然后b = a(原值)。话说有点像孔乙己的做法。

那就请你详细解释给大家听听,不要这么笼统

#15


引用 6 楼  的回复:
第一种( 按位异或 )我写了这么久代码  基本没这么用过

第一种在C/C++用的比较多,java应该少见,我的个人认为,我只是说 出有这种方法而已

#16


额,最后一种有点小难啊,前两种都用过,最后一种压根就没想过

#17


我觉得第二种的第二个方法出了内存溢出外,还有其他的bug,就是他交换的2个值中是不能有0的存在。

#18


引用 17 楼  的回复:
我觉得第二种的第二个方法出了内存溢出外,还有其他的bug,就是他交换的2个值中是不能有0的存在。

对的,我已经说过了,不推荐大家使用,原因就是内存溢出

#19


呵呵,楼主说话有误,什么叫很难理解,是很难理解别人想到这种解法,还是理解原理?假如你已经理解了原理,就应该把问题说清楚一点。而且楼主的问题在java解惑中有。

#20


引用 19 楼  的回复:
呵呵,楼主说话有误,什么叫很难理解,是很难理解别人想到这种解法,还是理解原理?假如你已经理解了原理,就应该把问题说清楚一点。而且楼主的问题在java解惑中有。

我只是说可能,不是一定,至少我第一次看的时候没能理解,我相信肯定有人能理解,我问题别人都清楚,为什么你就不清楚?原因我就不知道了。

#21


第3种第一次见,不太好理解. 感觉有点象 i=i++,学习了!

#22


本来不想制造不和谐气氛,楼主的意思的说你敢不敢全部能看懂?我(们)只能说,真心看不懂,楼主你发现一个奇迹。

#23


该回复于2012-08-02 10:07:54被版主删除

#24


學習

对于a=(b=a)*0+b这个式子,本没什么好说的,按逻辑上来说肯定a跟b没有实现交换啦..
但是用C#试了一下,结果大吃一惊,交换了.奇怪,又用C++试了一下,没有交换..
毕竟对错不能按编译器说的算吧,逻辑上应该没交换就是没交换,你交换了,不管你是谁都是错的....




#25


引用 21 楼  的回复:
第3种第一次见,不太好理解. 感觉有点象 i=i++,学习了!


有这种语法????????

#26


喵...
真心不明白最后一种做法的原因,之前关于两个数交换值的方法见过很多,最后一种还是第一次见,LZ你解释解释呗

#27


敢不敢说你全部能看懂?研究一下,有挺有意思的。

#28


引用 25 楼  的回复:
引用 21 楼 的回复:
第3种第一次见,不太好理解. 感觉有点象 i=i++,学习了!


有这种语法????????
结果不变呢!?

#29


a ,b 互换.最后一种同时赋值a ,b,很强大的想法.崇拜lz.

#30



public class Test {
    public static void main(String[] args) {
        int a = 5;
        int b = 4;
        b = a - b + (a=b);
        System.out.println(a + ":" + b);//4:5
        int c = 5;
        int d = 4;
        d = (c=d) + c - d;
        System.out.println(c + ":" + d);//4:4   
    }
}

运行顺序,从左到右先赋值计算。

#31


第一种常见,第二种偶尔见,第三种和最后一种没见过
最后一种依赖于编译器,不同编译器结果未必一样(当然java里可能都一样),其实相当于内部使用了临时变量

#32


在vs2010下 ,a,b都是4.第三种算法应该是基于某些特殊的编译器才能实现的,不过也有一定的参考价值.

#33


引用 32 楼  的回复:
在vs2010下 ,a,b都是4.第三种算法应该是基于某些特殊的编译器才能实现的,不过也有一定的参考价值.


第四种算法,a, b都是4.手误.

#34


public static void main(String[] args) {
int a = 5;
int b = 4;
b = a + 0 * (a = b);
System.out.print(a + ":" + b);
}

这种算法很犀利啊  
4 = 5 + 0 *(5 = 4); 结果为5  小括号内地结果为4
b = a + 0 * (a = b) ; b=5       a=b即a=4

#35


a = a^b;
^这个符号是干吗的?

#36


编译成机器码还是要用中间“变量”的

#37


引用 32 楼  的回复:
在vs2010下 ,a,b都是4.第三种算法应该是基于某些特殊的编译器才能实现的,不过也有一定的参考价值.

对的,这个写法必须依赖编译器,不同的编译器结果不同

#38


引用 35 楼  的回复:
a = a^b;
^这个符号是干吗的?

位运算符而已C语言中太常见了

#39


敢不敢说你全部能看懂?

我看过的一种方法

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

#40


这个都看不懂,靠,还是程序猿么?

#41


我的帖子呢?

#42


我真心表示有压力啊!!!

#43


首先,Lz这个方法真的很巧妙,以前没用过。我试了几次,然后谈谈我的理解。

1、根据运算的优先级首先运行到括号里的表达式(a=b),此时已经把栈中的b的值赋给了a,得到了一个新的a,所以此时完成了第一步.

2、然后就是b = a + 0*(a=b);不过就是为了实现交换而编写的一个算法而已,实际上就是b = a +0 ;此时的老a的值赋给了b.这样就完成了交换了。

最后,第一次看到这种办法,很巧妙。基础很扎实。

#44


引用 43 楼  的回复:
首先,Lz这个方法真的很巧妙,以前没用过。我试了几次,然后谈谈我的理解。

1、根据运算的优先级首先运行到括号里的表达式(a=b),此时已经把栈中的b的值赋给了a,得到了一个新的a,所以此时完成了第一步.

2、然后就是b = a + 0*(a=b);不过就是为了实现交换而编写的一个算法而已,实际上就是b = a +0 ;此时的老a的值赋给了b.这样就完成了交换了。

最后,第一次看……

就该像这样说说自己的想法,这个也是我发帖的目的哇,大家交流交流,但是你怎么解释:
b =  0 * (a = b) + a;
按照你的写法这个就等于
b = 0 + a;但是结果却会大不相同。
底层的编译不是这么简单的(针对java,C有些编译这个算法失败)

#45


看懂了,然后呢

#46


前面两种都很常见,第一种是最好的速度快而且不会内存溢出,第二种有内存溢出的危险,至于第三种实质就是第二中的模仿,而且做乘除法没有加减法的效率高,没什么用。至于最有一种大概和是java的编译器在实现的特殊之处,b = a + 0 * (a = b)这个明显在c++的就不可以,c++在计算a+0*(a = b)中的加的时候就将a = b这条语句同步到内存里面,所以在a 加0的时候a就等于b了,而java里面可能实现的时候并没有将在a被赋值后同步到内存里面。

#47


引用 44 楼  的回复:
引用 43 楼  的回复:

首先,Lz这个方法真的很巧妙,以前没用过。我试了几次,然后谈谈我的理解。

1、根据运算的优先级首先运行到括号里的表达式(a=b),此时已经把栈中的b的值赋给了a,得到了一个新的a,所以此时完成了第一步.

2、然后就是b = a + 0*(a=b);不过就是为了实现交换而编写的一个算法而已,实际上就是b = a +0 ;此时的老a的值赋给了b.这样就完……


我只能这样理解了,不管怎样按照优先级,肯定是先运行(a=b),所以说如果a在前,那么a还是老a,如果a在后的话,那就是新赋值后的a。至于你说的底层是如何编译的,不得而知了,期待大牛通过内存分析的办法来解释下这个编译过程了。

#48


头一回见,学习了!

#49


第一种异或好玩,最后一种总感觉先算括号的。。难道是把这个解析成语法树的形状去处理的?

#50


这些东西,见多了

#1


才学,真心不懂求解释

#2


引用 1 楼  的回复:
才学,真心不懂求解释

相信下面会有人解释的

#3


除了最后一种不怎么懂-。-但在以前的帖子里找到了
http://topic.csdn.net/u/20070929/13/97529154-be2f-431e-a2bd-d7ccd048cf77.html
差不多吧?

#4


引用 3 楼  的回复:
除了最后一种不怎么懂-。-但在以前的帖子里找到了
http://topic.csdn.net/u/20070929/13/97529154-be2f-431e-a2bd-d7ccd048cf77.html
差不多吧?

前面的网上很多讲解,而且比较好,没有在说的意思了,最后一个估计比较难找,不过相信会有许多人能解释的

#5


引用 4 楼  的回复:
引用 3 楼  的回复:

除了最后一种不怎么懂-。-但在以前的帖子里找到了
http://topic.csdn.net/u/20070929/13/97529154-be2f-431e-a2bd-d7ccd048cf77.html
差不多吧?

前面的网上很多讲解,而且比较好,没有在说的意思了,最后一个估计比较难找,不过相信会有许多人能解释的
最后一种貌似实际上并不好?底层还是用了个中间变量?

#6


第一种( 按位异或 )我写了这么久代码  基本没这么用过

#7


该回复于2012-08-02 08:32:04被版主删除

#8


算法是好,但是这样是吧自己弄晕。

#9


交换 ab 第一种效率最高了

#10


第三种很难理解吗?只不过用了下赋值,然后又要把赋值后的a去掉就乘0,然后b = a(原值)。话说有点像孔乙己的做法。

#11


最后一种比较有意思,利用编译所生成计算过程的临时变量 和 加法从左到右的结合顺序,来实现了交换。

不过效率未必有第一个高,楼主有时间可以测试看看。

#12


回字的八种写法么

#13


引用 11 楼  的回复:
最后一种比较有意思,利用编译所生成计算过程的临时变量 和 加法从左到右的结合顺序,来实现了交换。

不过效率未必有第一个高,楼主有时间可以测试看看。

这个我知道,第一种最高,只是最后一种特有意思,网上好难看到哦

#14


引用 10 楼  的回复:
第三种很难理解吗?只不过用了下赋值,然后又要把赋值后的a去掉就乘0,然后b = a(原值)。话说有点像孔乙己的做法。

那就请你详细解释给大家听听,不要这么笼统

#15


引用 6 楼  的回复:
第一种( 按位异或 )我写了这么久代码  基本没这么用过

第一种在C/C++用的比较多,java应该少见,我的个人认为,我只是说 出有这种方法而已

#16


额,最后一种有点小难啊,前两种都用过,最后一种压根就没想过

#17


我觉得第二种的第二个方法出了内存溢出外,还有其他的bug,就是他交换的2个值中是不能有0的存在。

#18


引用 17 楼  的回复:
我觉得第二种的第二个方法出了内存溢出外,还有其他的bug,就是他交换的2个值中是不能有0的存在。

对的,我已经说过了,不推荐大家使用,原因就是内存溢出

#19


呵呵,楼主说话有误,什么叫很难理解,是很难理解别人想到这种解法,还是理解原理?假如你已经理解了原理,就应该把问题说清楚一点。而且楼主的问题在java解惑中有。

#20


引用 19 楼  的回复:
呵呵,楼主说话有误,什么叫很难理解,是很难理解别人想到这种解法,还是理解原理?假如你已经理解了原理,就应该把问题说清楚一点。而且楼主的问题在java解惑中有。

我只是说可能,不是一定,至少我第一次看的时候没能理解,我相信肯定有人能理解,我问题别人都清楚,为什么你就不清楚?原因我就不知道了。

#21


第3种第一次见,不太好理解. 感觉有点象 i=i++,学习了!

#22


本来不想制造不和谐气氛,楼主的意思的说你敢不敢全部能看懂?我(们)只能说,真心看不懂,楼主你发现一个奇迹。

#23


该回复于2012-08-02 10:07:54被版主删除

#24


學習

对于a=(b=a)*0+b这个式子,本没什么好说的,按逻辑上来说肯定a跟b没有实现交换啦..
但是用C#试了一下,结果大吃一惊,交换了.奇怪,又用C++试了一下,没有交换..
毕竟对错不能按编译器说的算吧,逻辑上应该没交换就是没交换,你交换了,不管你是谁都是错的....




#25


引用 21 楼  的回复:
第3种第一次见,不太好理解. 感觉有点象 i=i++,学习了!


有这种语法????????

#26


喵...
真心不明白最后一种做法的原因,之前关于两个数交换值的方法见过很多,最后一种还是第一次见,LZ你解释解释呗

#27


敢不敢说你全部能看懂?研究一下,有挺有意思的。

#28


引用 25 楼  的回复:
引用 21 楼 的回复:
第3种第一次见,不太好理解. 感觉有点象 i=i++,学习了!


有这种语法????????
结果不变呢!?

#29


a ,b 互换.最后一种同时赋值a ,b,很强大的想法.崇拜lz.

#30



public class Test {
    public static void main(String[] args) {
        int a = 5;
        int b = 4;
        b = a - b + (a=b);
        System.out.println(a + ":" + b);//4:5
        int c = 5;
        int d = 4;
        d = (c=d) + c - d;
        System.out.println(c + ":" + d);//4:4   
    }
}

运行顺序,从左到右先赋值计算。

#31


第一种常见,第二种偶尔见,第三种和最后一种没见过
最后一种依赖于编译器,不同编译器结果未必一样(当然java里可能都一样),其实相当于内部使用了临时变量

#32


在vs2010下 ,a,b都是4.第三种算法应该是基于某些特殊的编译器才能实现的,不过也有一定的参考价值.

#33


引用 32 楼  的回复:
在vs2010下 ,a,b都是4.第三种算法应该是基于某些特殊的编译器才能实现的,不过也有一定的参考价值.


第四种算法,a, b都是4.手误.

#34


public static void main(String[] args) {
int a = 5;
int b = 4;
b = a + 0 * (a = b);
System.out.print(a + ":" + b);
}

这种算法很犀利啊  
4 = 5 + 0 *(5 = 4); 结果为5  小括号内地结果为4
b = a + 0 * (a = b) ; b=5       a=b即a=4

#35


a = a^b;
^这个符号是干吗的?

#36


编译成机器码还是要用中间“变量”的

#37


引用 32 楼  的回复:
在vs2010下 ,a,b都是4.第三种算法应该是基于某些特殊的编译器才能实现的,不过也有一定的参考价值.

对的,这个写法必须依赖编译器,不同的编译器结果不同

#38


引用 35 楼  的回复:
a = a^b;
^这个符号是干吗的?

位运算符而已C语言中太常见了

#39


敢不敢说你全部能看懂?

我看过的一种方法

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

#40


这个都看不懂,靠,还是程序猿么?

#41


我的帖子呢?

#42


我真心表示有压力啊!!!

#43


首先,Lz这个方法真的很巧妙,以前没用过。我试了几次,然后谈谈我的理解。

1、根据运算的优先级首先运行到括号里的表达式(a=b),此时已经把栈中的b的值赋给了a,得到了一个新的a,所以此时完成了第一步.

2、然后就是b = a + 0*(a=b);不过就是为了实现交换而编写的一个算法而已,实际上就是b = a +0 ;此时的老a的值赋给了b.这样就完成了交换了。

最后,第一次看到这种办法,很巧妙。基础很扎实。

#44


引用 43 楼  的回复:
首先,Lz这个方法真的很巧妙,以前没用过。我试了几次,然后谈谈我的理解。

1、根据运算的优先级首先运行到括号里的表达式(a=b),此时已经把栈中的b的值赋给了a,得到了一个新的a,所以此时完成了第一步.

2、然后就是b = a + 0*(a=b);不过就是为了实现交换而编写的一个算法而已,实际上就是b = a +0 ;此时的老a的值赋给了b.这样就完成了交换了。

最后,第一次看……

就该像这样说说自己的想法,这个也是我发帖的目的哇,大家交流交流,但是你怎么解释:
b =  0 * (a = b) + a;
按照你的写法这个就等于
b = 0 + a;但是结果却会大不相同。
底层的编译不是这么简单的(针对java,C有些编译这个算法失败)

#45


看懂了,然后呢

#46


前面两种都很常见,第一种是最好的速度快而且不会内存溢出,第二种有内存溢出的危险,至于第三种实质就是第二中的模仿,而且做乘除法没有加减法的效率高,没什么用。至于最有一种大概和是java的编译器在实现的特殊之处,b = a + 0 * (a = b)这个明显在c++的就不可以,c++在计算a+0*(a = b)中的加的时候就将a = b这条语句同步到内存里面,所以在a 加0的时候a就等于b了,而java里面可能实现的时候并没有将在a被赋值后同步到内存里面。

#47


引用 44 楼  的回复:
引用 43 楼  的回复:

首先,Lz这个方法真的很巧妙,以前没用过。我试了几次,然后谈谈我的理解。

1、根据运算的优先级首先运行到括号里的表达式(a=b),此时已经把栈中的b的值赋给了a,得到了一个新的a,所以此时完成了第一步.

2、然后就是b = a + 0*(a=b);不过就是为了实现交换而编写的一个算法而已,实际上就是b = a +0 ;此时的老a的值赋给了b.这样就完……


我只能这样理解了,不管怎样按照优先级,肯定是先运行(a=b),所以说如果a在前,那么a还是老a,如果a在后的话,那就是新赋值后的a。至于你说的底层是如何编译的,不得而知了,期待大牛通过内存分析的办法来解释下这个编译过程了。

#48


头一回见,学习了!

#49


第一种异或好玩,最后一种总感觉先算括号的。。难道是把这个解析成语法树的形状去处理的?

#50


这些东西,见多了