2012-01-16 64 views
3

我想在C++中編寫一個函數,它使用兩個64位無符號整數並返回它們在有符號64位整數中的差異。這似乎有點複雜,因爲溢出情況 - 由於輸入是兩個無符號正整數,如果這兩者之間的絕對差值大於最大有符號值(INT64_MAX),則差值不能通過有符號整數傳輸。所以我寫了下面的實現,我想知道,首先,如果這在功能上是正確的,其次,是否有更簡單的實現。任何建議將不勝感激。謝謝! (我會用一個異常來代替斷言,它只是在那裏吧!)C++:在一個有符號的64位整數中的兩個無符號64位整數的差異

int64_t GetDifference(uint64_t first, uint64_t second) { 
    uint64_t abs_diff = (first > second) ? (first - second): (second - first);  
    uint64_t msb_abs_diff = (abs_diff >> (sizeof(abs_diff)*8 - 1)) & 1; 
    assert(msb_abs_diff == 0); 
    int64_t diff = first - second; 
    return diff; 
} 
+0

好了,感謝所有的答案!我更擔心功能的正確性,這是可以的,我猜...這些改進都是有效的,雖然沒有根本的不同,但我會把它們合併。 – Abhi 2012-01-16 21:02:02

+0

任何體面的編譯器應該能夠優化這樣的代碼,但請確保它是正確的。 – 2012-01-16 21:22:01

回答

5

對我來說,這似乎是一個更簡單,更具可讀性的實現。

int64_t GetDifference(uint64_t first, uint64_t second) { 
    uint64_t abs_diff = (first > second) ? (first - second): (second - first); 
    assert(abs_diff<=INT64_MAX); 
    return (first > second) ? (int64_t)abs_diff : -(int64_t)abs_diff; 
} 
4

三個挑剔:

  • sizeof(abs_diff)*8 - 1可以通過字面63不會損失可移植性的替代(在事實上,這將是因爲平臺便攜式其中char不是8比特寬)
  • & 1是不需要的,由於移位的結果始終是一個比特
  • 您可以從abs_diff派生diff而不用重複減法。

否則,這對我來說似乎是完全正確的。

+0

'sizeof(abs_diff)* CHAR_BIT - 1'會更便攜 – 2015-08-06 05:35:44

4

這更短,可能更快。

int64_t GetDifference(uint64_t first, uint64_t second) 
{ 
    int64_t diff = first - second; 
    bool overflowed = (diff < 0)^(first < second); 
    assert(!overflowed); 
    return diff; 
} 

良好優化編譯器應該注意到diff < 0是負數標記和first < second是從現有表達進位標誌。比較這兩個標誌是溢出的經典測試。

即使沒有檢測到,也需要更少的操作。

但我更喜歡這個的最大原因是沒有幻數

+0

謝謝..我明白了你的觀點......如果有int/uint而不是int64_t/uint64_t,這將是一個可以工作的... – Abhi 2012-01-17 03:07:19

+0

There沒有神奇的數字,但你依賴於「未定義的行爲」,那就是投射一個無符號的整數表達式溢出的事實包含在 – Triskeldeian 2015-11-29 19:44:17

+0

@Triskeldeian:它是「實現定義的」,而不是「未定義的」。 – 2015-11-29 19:53:54

2

如何:

int64_t GetDifference(uint64_t first, uint64_t second) { 
    int64_t diff = (int64_t)(first - second); 
    assert first >= second && diff >= 0 || first < second && diff < 0; 
    return diff; 
} 
相關問題