int abs(int n)實現對比
abs()函式對比
在C\C++的<math.h
>和<cmath
>中均有abs的實現,而今天心血來潮,另外手動實現了兩個abs()函式,用來做一下對比,一種是通過關係運算符判斷正負求解,一種是通過位運算求解,仔細看哦,很值得回味的測試……(PS:為了增大區別,每個函式的運算次數為MAXN
次)。
#include <cstdio>
#include <iostream>
#include <ctime>
#include <cmath>
using namespace std;
const int MAXN = 1000000 ;
int abs_1(int n)
{
if (n < 0)
{
return -n;
}
else
{
return n;
}
}
int abs_2(int n)
{
return (n ^ (n >> 31)) - (n >> 31);
}
int main()
{
int a, b = 0;
while (cin >> a)
{
// 系統abs()函式測試
long long start = clock();
for (int i = 0; i < MAXN; i++)
{
b = abs(a);
}
long long end = clock();
cout << "abs() : " << a << ' ' << b << ' ' << end - start << '\n';
// 判斷正負abs()函式實現
start = clock();
for (int i = 0; i < MAXN; i++)
{
b = abs_1(a);
}
end = clock();
cout << "abs_1() : " << a << ' ' << b << ' ' << end - start << '\n';
// 位運算abs()函式實現
start = clock();
for (int i = 0; i < MAXN; i++)
{
b = abs_2(a);
}
end = clock();
cout << "abs_2() : " << a << ' ' << b << ' ' << end - start << '\n';
}
return 0;
}
經過多次測試,發現時間差距還是挺明顯的,當然對於一次abs()而言,差距可以視為沒有吧,當然這麼說不太嚴謹。
根據資料我們不難發現,abs_1()
和abs_2()
對於正負數的處理時間差別還是挺大的,但是令人好奇的是<cmath
>中abs()
對於正負數的處理時間卻幾乎相等,至於為什麼,就麻煩好奇心比我強的人去挖掘原始碼吧,然後告訴我怎麼實現的。
接著呢,我想abs_1()
不用分析了,有腦子的都看得懂,而對於位運算搞定的abs_2()
來說,可讀性真的不算高,對於不經常和位運算打交道的人而言,挺繞的。首先我們定義的是4個位元組的32位2進位制有符號整形,也就是int
型,原諒我把一個整形形容的那麼複雜,好了,言歸正傳,因為有符號,所以我們知道第32位是符號位,所以n>>31
最後得到的就是符號位的值,如果是負數,結果為-1,反之則為0。那麼如果n為正數,n^0-0=n
,而如果為負數,n^(-1)
的結果也就是|n|-1
,所以最後再-(-1)
也就是n的絕對值了,我想這裡不用過多解釋,直接用一組資料寫寫畫畫就知道了,真的不知道,那就麻煩你去看看位運算了,因為今天關鍵不是要搞位運算,所以,我還是不會解釋,畢竟我是一個懶人。
由於閒著也是數星星、數羊,於是我又進行了一個測試,測試<cmath
>與<math.h
>中abs()
的區別,上面的資料已經有了前者的測試結果,所以鑑於我懶,我只再給出<math.h
>的測試資料。
雖然和前邊的資料對比感覺不明顯,但是還是有些許區別的,我認為<math.h
>的要比<cmath
>的abs()
穩定性差些。大概這就是為什麼C++推薦使用的標頭檔案是<cmath
>,而<math.h
>只是為了相容。
當然,以上所有測試資料都是基於我的機子,我的測試樣本,也許有的地方不夠準確,那麼我只能將其歸咎於我的失責,但是一貫喜歡找客觀原因的我會告訴你:測試樣本不夠大,測試樣本分佈不夠均勻。但是,懶惰的我,從不會因為知道這些就去重測,因為,現在都三點了,我還有線代沒看/(ㄒoㄒ)/~~,看過線代後還要看會兒程式碼大全……如果非要說我不夠嚴謹,沒有治學精神,那麼我也不得不承認,畢竟這種放大了一百萬倍後產生的差別還如此甚微的,真的沒有太大錙銖必較的價值。
測試了這麼大會兒,雖然測試資料上有些不夠嚴謹,但是我們基本上可以得出,位運算是最牛逼的!!!對於某種特定的需求,這裡的確可以產生可見的優化。
最後,跟上一句,倒數第三段是在浪費你們時間,我只是給自己找一個隨性一些的藉口,當然,這一段也是廢話。