版本號大小比較算法

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

0.0.2
0.0.3

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

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

2.7.14.2345
2.12.8.1234

因為單純的字符串比較大小的依據(jù)是每個字符的 ASCII 碼拢肆。程序會認為字符7比字符1大减响,結果就是第一個版本號大于第二個版本號靖诗,這是錯誤的。

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

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

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

示例: 3.5.20.9527

在比較版本號時伤为,正確的做法應該是,主版本號和主版本號比較据途,次版本號和次版本號比較等等绞愚。所以算法的核心應該是分離出版本號的各個組成部分。這個檢測算法用 Swift 來做非常簡單颖医,只需要利用數(shù)組的 lexicographicallyPrecedes 方法即可實現(xiàn)位衩。相關代碼可查閱該項目OhMyVersion

當然 Objective-C 語言里并沒有 Array 的這個方法熔萧,那我們就自己動手實現(xiàn)一個糖驴。以下是一個簡單的實現(xiàn):

@implementation NSArray (Compare)

- (BOOL)lexicographicallyPrecedesWithOther:(NSArray *)array areInIncreasingOrder:(BOOL (^)(id, id))block
{
    NSParameterAssert(array);
    NSParameterAssert(block);
    NSUInteger idx = 0;
    
    for (id obj in self) {
        if (idx == array.count) { break; }
        
        if ([obj isEqual:array[idx]]) { ++idx; continue; }
        
        return block(obj, array[idx]);
    }
    
    return self.count > array.count;
}

@end

下面我也列舉了粗暴的 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.");
}
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市俺榆,隨后出現(xiàn)的幾起案子感昼,更是在濱河造成了極大的恐慌,老刑警劉巖罐脊,帶你破解...
    沈念sama閱讀 211,639評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件定嗓,死亡現(xiàn)場離奇詭異,居然都是意外死亡萍桌,警方通過查閱死者的電腦和手機宵溅,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,277評論 3 385
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來上炎,“玉大人恃逻,你說我怎么就攤上這事∨菏” “怎么了寇损?”我有些...
    開封第一講書人閱讀 157,221評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長铅碍。 經(jīng)常有香客問我润绵,道長,這世上最難降的妖魔是什么胞谈? 我笑而不...
    開封第一講書人閱讀 56,474評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上烦绳,老公的妹妹穿的比我還像新娘卿捎。我一直安慰自己,他們只是感情好径密,可當我...
    茶點故事閱讀 65,570評論 6 386
  • 文/花漫 我一把揭開白布午阵。 她就那樣靜靜地躺著,像睡著了一般享扔。 火紅的嫁衣襯著肌膚如雪底桂。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,816評論 1 290
  • 那天惧眠,我揣著相機與錄音籽懦,去河邊找鬼。 笑死氛魁,一個胖子當著我的面吹牛暮顺,可吹牛的內容都是我干的。 我是一名探鬼主播秀存,決...
    沈念sama閱讀 38,957評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼捶码,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了或链?” 一聲冷哼從身側響起惫恼,我...
    開封第一講書人閱讀 37,718評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎澳盐,沒想到半個月后尤筐,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體矩欠,經(jīng)...
    沈念sama閱讀 44,176評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡病梢,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,511評論 2 327
  • 正文 我和宋清朗相戀三年猛计,在試婚紗的時候發(fā)現(xiàn)自己被綠了义图。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片几颜。...
    茶點故事閱讀 38,646評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡陋守,死狀恐怖殴玛,靈堂內的尸體忽然破棺而出毕荐,到底是詐尸還是另有隱情倾贰,我是刑警寧澤冕碟,帶...
    沈念sama閱讀 34,322評論 4 330
  • 正文 年R本政府宣布,位于F島的核電站匆浙,受9級特大地震影響安寺,放射性物質發(fā)生泄漏。R本人自食惡果不足惜首尼,卻給世界環(huán)境...
    茶點故事閱讀 39,934評論 3 313
  • 文/蒙蒙 一挑庶、第九天 我趴在偏房一處隱蔽的房頂上張望言秸。 院中可真熱鬧,春花似錦迎捺、人聲如沸举畸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,755評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽抄沮。三九已至,卻和暖如春岖瑰,著一層夾襖步出監(jiān)牢的瞬間叛买,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,987評論 1 266
  • 我被黑心中介騙來泰國打工蹋订, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留率挣,地道東北人。 一個月前我還...
    沈念sama閱讀 46,358評論 2 360
  • 正文 我出身青樓辅辩,卻偏偏與公主長得像难礼,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子玫锋,可洞房花燭夜當晚...
    茶點故事閱讀 43,514評論 2 348

推薦閱讀更多精彩內容

  • 第5章 引用類型(返回首頁) 本章內容 使用對象 創(chuàng)建并操作數(shù)組 理解基本的JavaScript類型 使用基本類型...
    大學一百閱讀 3,216評論 0 4
  • Spring Cloud為開發(fā)人員提供了快速構建分布式系統(tǒng)中一些常見模式的工具(例如配置管理蛾茉,服務發(fā)現(xiàn),斷路器撩鹿,智...
    卡卡羅2017閱讀 134,633評論 18 139
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 171,773評論 25 707
  • 嗨AV8D吼鳞,我又回來了。 你們過得怎么樣敖懈椤赔桌?昨天我小正經(jīng)了一把,說實話還挺懷念這個不正經(jīng)的自己渴逻。 (www.jia...
    格斯墨閱讀 906評論 45 40
  • Selector參數(shù) Swift3.0版本 #selector 事件監(jiān)聽本質: 將方法包裝成@SEL -> 類中查...
    Gary_fei閱讀 194評論 0 1