使用異或運算交換兩個變數位置的演算法非常低!
阿新 • • 發佈:2018-12-03
看了很多程式設計方面的知識,在慕課網上的一個關於二進位制的視訊中,偶然聽見老師說採用異或運算的方法交換兩個數字的順序可以提高效率,原因是位運算是直接對二進位制位進行運算,而二進位制位更接近底層。
因此,我一直信誓旦旦的給朋友們普及異或運算的高效率,直到被別人反駁之後,我去網上搜了很多相關的文章。然後發現很多地方都說異或運算效率很低。於是我測試了一下,為了測試更精確,讓交換位置的操作迴圈執行一定次數,然後再把兩個數字復原之後用第二種交換方法繼續執行。
首先我用的是Java進行測試:
public class ss { public static void main(String[] args) { int a = Integer.MAX_VALUE; int b = Integer.MIN_VALUE; int temp; long num = 909999999; long time1 = System.currentTimeMillis(); for (long j = 0; j < num; j++) { a = a ^ b; b = a ^ b; a = a ^ b; } long time2 = System.currentTimeMillis(); a = Integer.MAX_VALUE; b = Integer.MIN_VALUE; long time3 = System.currentTimeMillis(); for (long i = 0; i < num; i++) { temp = a; a = b; b = temp; } long time4 = System.currentTimeMillis(); System.out.println(time2 - time1); System.out.println(time4 - time3); } }
執行結果是:
採用異或運算交換位置所花的時間比直接用中間變數賦值慢了一半。雖然我也不想相信,可惜事實如此。某天偶然看見某篇文章上寫的兩種方法交換時的彙編指令條數。採用異或指令所用指令條數遠遠多於直接用三個變數交換的方法。
然後我採用C語言再次測試了一下兩種方法所花時間,程式碼如下:
#include <time.h> #include <stdio.h> int main() { long start1, finish1; long start2, finish2; long time1, time2; int a = 12345678; int b = 87654321; int temp; long num = 99999999999999999; start1 = clock(); for (long j = 0; j < num; j++) { a = a ^ b; b = a ^ b; a = a ^ b; } finish1 = clock(); a = 12345678; b = 87654321; start2 = clock(); for (long i = 0; i < num; i++) { temp = a; a = b; b = temp; } finish2 = clock(); time1 = finish1 - start1; time2 = finish2 - start2; printf("%ld\n", time1); printf("%ld\n", time2); return 0; }
執行結果如下:
然後我交換了兩個迴圈的位置,再次執行,結果如下:
採用異或運算交換兩個變數位置的耗時幾乎是“土方法”的兩倍。
徹底絕望了,寫這篇文章,就是為了澄清這個很多人都不知道的事實。程式碼可能寫的不夠嚴謹,結果可以有誤差,但是至少證明異或運算效率並不高,不要被所謂的位運算遮蔽了雙眼。