服務端接收到客戶端的請求,有時候須要對低於控制版本的客戶端返回不一樣的結果。版本號通常是三段式的 "xx.xx.xx",一般會將版本號解析成整數數字保存在 int arr[3] 數組中,而後逐個檢查數組中的數字;最常規的作法以下:c++
int compare_version(int client_version[3], int base_version[3]) { if (client_version[0] > base_version[0]) { return 1; } else if (client_version[0] == base_version[0]) { if (client_version[1] > base_version[1]) { return 1; } else if (client_version[1] == client_version[1]) { if (client_version[2] > base_version[2]) { return 1; } else if (client_version[2] == client_version[2]) { return 0; } else { return -1; } } else { return -1; } } else { return -1; } }
上面的代碼可以正常運行,且沒有冗餘的步驟;可是比較步驟較多,if 語句層層嵌套,代碼結構較爲複雜。
本着「更短、更快、更強」的原則,開始思考能不能將代碼優化一下。
正常狀況下,咱們比較字符串「123」與「124」,都是從百位、十位、個位依次進行比價,就像上面的函數所作的那樣。而對於 int a = 123, int b = 124, 咱們能夠直接用 a > b、 a == b、a < b 來進行比較;因此,若是可以把版本號的三個部分合併成一個更大的變量來進行比較,那麼一步就能夠比較出版本大小了。如何把三個 int 變量合併成一個更大的整形變量呢?
一個 int 變量佔用4個字節,32個bit;若是可以有一個 int96 的基本類型,那麼能夠這樣作:數組
int96 a,b; a = *(int96*)client_version; //假設系統是 big-edian b = *(int96*)base_version; if (a > b) { return 1; } else if (a == b) { return 0; } else { return -1; }
可是C++中沒有佔用96個bit的整數類型。
那麼能不能將三個int放在一個int中呢?函數
考慮到市場上能夠看到的各類軟件的版本號,對於主版本號.次版本號.編譯版本號,沒見過哪一個版本號是超過100的;那麼,用10個bit(最大值1023)來表示一個版本號是足夠的;因此,三段版本號能夠分別用10個bit來表示,而後壓縮進一個32bit的int中。對於有符號的10個bit,其能表示的數字範圍爲 -1024 ~ 1023,足夠咱們使用的了。
以下兩個方法都可:優化
方法一code
int compare_version(int client_version[3], int base_version[3]) { int client = (client_version[0] << 20) | (client_version[1] << 10) | clien_version[2]; int base = (base_version[0] << 20) | (base_version[1] << 10) | base_version[2]; if (client > base) { return 1; } else if (client == base) { return 0; } else { return -1; } }
方法二字符串
int compare_version(int client_version[3], int base_version[3]) { int diff = 0; diff += (client_version[0] - base_version[0]) << 20; diff += (client_version[1] - base_version[1]) << 10; diff += (client_version[2] - base_version[2]); if (diff > 0) { return 1; } else if (diff == 0) { return 0; } else { return -1; } }