版本號大小比較算法


版本號之間比較大小,本質上是比較字符串之間的關系。這里給定兩個版本號,你一定能迅速地區分出大小:

0.0.2 0.0.3

想要讓計算機程序分辨她們的關系,可以直接使用strcmp()函數獲取返回值,如果你在 iOS 系統下編程,也可以使用 NSString 類提供的- (NSComparisonResult)compare:(NSNumber *)decimalNumber方法。

但如果版本進化成下面這樣,上面所說的 API 一定會產生錯誤的結果。

2.7.14.2345 2.12.8.1234

因為單純的字符串比較大小的依據是每個字符的 ASCII 碼。程序會認為字符7比字符1大,結果就是第一個版本號大於第二個版本號,這是錯誤的。

因此在識別之前,有必要了解一下版本號的組成部分,以及每一個數字的意義,這里已 GUN 風格的版本號作為說明。

版本號大致以下幾個部分組成:

  • 主版本號
  • 次版本號
  • 修正版本號
  • 編譯版本號

示例: 3.5.20.9527

在比較版本號時,正確的做法應該是,主版本號和主版本號比較,次版本號和次版本號比較等等。所以算法的核心應該是分離出版本號的各個組成部分。由此產生的算法會有多種。這里列舉一個方式最簡單粗暴的 C 語言代碼:

/** * 比較版本號 * * @param v1 第一個版本號 * @param v2 第二個版本號 * * @return 如果版本號相等,返回 0, * 如果第一個版本號低於第二個,返回 -1,否則返回 1. */ int compareVersion(const char *v1, const char *v2) { assert(v1); assert(v2); const char *p_v1 = v1; const char *p_v2 = v2; while (*p_v1 && *p_v2) { char buf_v1[32] = {0}; char buf_v2[32] = {0}; char *i_v1 = strchr(p_v1, '.'); char *i_v2 = strchr(p_v2, '.'); if (!i_v1 || !i_v2) break; if (i_v1 != p_v1) { strncpy(buf_v1, p_v1, i_v1 - p_v1); p_v1 = i_v1; } else p_v1++; if (i_v2 != p_v2) { strncpy(buf_v2, p_v2, i_v2 - p_v2); p_v2 = i_v2; } else p_v2++; int order = atoi(buf_v1) - atoi(buf_v2); if (order != 0) return order < 0 ? -1 : 1; } double res = atof(p_v1) - atof(p_v2); if (res < 0) return -1; if (res > 0) return 1; return 0; }

Test case:

int main(int argc, char *argv[]) { assert(compare_version("2.2.1", "2.2.0") > 0); assert(compare_version("2.2.1", "2.1.9") > 0); assert(compare_version("2.2.1", "2.2.01") == 0); assert(compare_version("2.2.1", "2.2.1") == 0); assert(compare_version("2.2", "2.1.1") > 0); assert(compare_version("2.2", "2.2.1") < 0); assert(compare_version("2.2.3.1", "2.2.3.5") < 0); assert(compare_version("2.2.3.1", "2.2.3.0") > 0); assert(compare_version("2.2", "2.2.1.4.5") < 0); assert(compare_version("2.2.3.4", "2.2.4.4.5") < 0); assert(compare_version("2.2.3.4.5.6", "2.2.3.4.5.12") < 0); assert(compare_version("2.2.3.4.5.6", "2.2.2.4.5.12") > 0); assert(compare_version("3.0.0.1", "3.0.0.0.1") > 0); assert(compare_version("3.1", "3.1.") == 0); puts("test pass."); }



文/waylen(簡書作者)
原文鏈接:http://www.jianshu.com/p/071c55963738
著作權歸作者所有,轉載請聯系作者獲得授權,並標注“簡書作者”。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM