2012-01-16 62 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; 
} 
相关问题