求交換兩個整數最簡單的寫法?

網上有很多極客的寫法,自己寫了一種比較簡單的,請問還有更高效簡潔的嗎?!

int a = 119, b = 256;

a ^= b ^ (b = a)

-----------------------補充------------------

提出這個問題之前,確實經過實測,「a ^= b ^ (b = a)」在js、java、c#下確實得到正確的結果,但是在c++下,出現問題。

我不太懂彙編。

個人覺得上面的表達式在編譯器編譯的時候,首先應該轉化成後綴表達式的,然後進入寄存器的。c++出問題,估計是編譯時有優化吧!求懂c++、java、c#、js具體編譯過程的大神講解!


a,b = b,a

(Python)


這樣用XOR做,其實未必更快。因為它需要兩次真實的運算操作。

用一個額外的臨時變數做交換,實際編譯的時候八成會被優化掉,因為CPU有寄存器。


你這段代碼寫得不對啊,反正貼著聲明,你應該寫成這樣:

int a = 256;
int b = 119;


人家說簡潔沒說少用變數啊

c:

int temp=b;

b=a;

a=temp;

go:

a,b=b,a;

其他寫法都是耍流氓…


悲報

經實測,題主的代碼用gcc開-O3編譯之後,被優化成了彙編寫的臨時變數法,三條mov,木有xor……

恭喜做無用功……

然後我覺得用彙編寫的臨時變數法已經是最快的了,一共只有三行

不是很懂彙編,求彙編高手打臉……


之前面試一家公司的C#,筆試里有道題就是交換兩個變數,但不許引入第三個變數。

已經習慣了

temp=b;
b=a;
a=temp;

現場靈機一動想了這麼個法子:

b=a+b;
a=b-a;
b=b-a;


std::swap


其實啊,騷年你這麼寫有點問題

當a==b時 你這代碼會得出不正確的結果

所以還是用臨時變數來交換,或者用Python吧


要相信編譯器


臨時變數法最保險

與其糾結在這種地方優化速度不如優化你的演算法

如果你要交換a[i]和a[j]的值的話如果i==j,那麼不用臨時變數有可能出現很大問題


腦內交換最簡單,都不用重寫代碼:反正名字已經是a、b這類臨時無意義的了,交換一下又何妨?


inline void swapInt(int a, int b)
{
// 聲明在別的地方
int tmp = a;
a = b;
b = tmp;
}

int a = 119, b = 256;
swapInt(a, b);

可讀性高,效率在編譯器優化下估計並不比網上那些看著蛋疼的寫法低。


list($a, $b) = [$b, $a]

(PHP)


a=a^b;

b=a^b;

a=a^b;

利用位運算進行換值操作。


int b = 119, a = 256;


題主的解決思路是能過運算符的優先順序來解決的。

a ^= b ^ (b = a) 等價於 a=a^b^(b=a);

等於右邊是:a^b^(b=a)

執行順序是:a異或b,再異或(b=a)

括弧優先等高於異或,先把a賦值b,相當於直接與a進行異或,這時的值就變成了b.

如果知道這個道理了,就可以展開很多種做法了。

再來兩個例子是通過運算符優先順序來解決兩個數交換。

先在Java上面親測!其他語言估計一樣!

// =====================代碼開始分隔線===========================

public class TestChange {

/**

* @param args

*/

public static void main(String[] args) {

int a = 119;

int b = 256;

if (a != b) {

// 1.主要根據運算符的優先順序來做的.

change001(a, b);

// 2.主要根據運算符的優先順序來做的.

change002(a, b);

// 3.運用異或

change003(a, b);

// 4.運用異或

change004(a, b);

}

}

/**

* 1.主要根據運算符的優先順序來做的.

*/

public static void change001(int a, int b) {

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

print(a, b);

}

/**

* 2.主要根據運算符的優先順序來做的.

*/

public static void change002(int a, int b) {

b = a + (a = b) * 0;

print(a, b);

}

/**

* 3.運用異或

*/

public static void change003(int a, int b) {

a ^= b;

b ^= a;

a ^= b;

print(a, b);

}

/**

* 4.運用異或

*/

public static void change004(int a, int b) {

// a ^= b ^ (b = a)

a = a ^ b ^ (b = a);

print(a, b);

}

/**

* 列印

*/

public static void print(int a, int b) {

System.out.println(a);

System.out.println(b);

}

}

// =====================代碼結束分隔線===========================

其實,兩個數交換也能考出很多點,

比如:

1.內存溢出

a=a+b;可能會內存溢出?

(C,int的最大值是2147483647,加b的話,就會變成負值了)

2. 變數釋放

如果採用中間變數,是不是把中間變數釋放掉?


C++ 接近 Python 的一種玩法:隨意交換(不限於兩個,不限於整數)

tie(a, b, c) = make_tuple(b, c, a);


不算+-,*/的話:

1、幾次異或;

2、臨時變數;

3、asm的壓棧出棧。

個人推薦用異或法或者臨時變數法。


c=b

b=a

a=c


printf (「a=%d,b=%d",b,a)


推薦閱讀:

高維空間點的旋轉問題?
matlab中for循環為什麼會慢?
奇數階幻方構造方法的原理是什麼?
這是用什麼演算法實現的?
遞歸有什麼意義?

TAG:演算法 | 數學 | 數論 |