4

我正在尝试用 C++ 编写一个函数,该函数采用两个 64 位无符号整数并以有符号 64 位整数返回它们的差异。由于溢出情况,这似乎有点复杂 - 由于输入是两个无符号正整数,如果这两个之间的绝对差大于最大有符号值(INT64_MAX),则该差不能通过有符号整数传输。所以我写了下面的实现,我想知道,首先,这在功能上是否正确,其次,是否有更简单的实现。任何建议将不胜感激。谢谢!(我将用异常替换断言,它现在就在那里!)

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;
}
4

4 回答 4

6

对我来说,这似乎是一个更简单、更易读的实现。

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;
}
于 2012-01-16T20:55:53.217 回答
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是来自先前表达式的进位标志。比较这两个标志是溢出的经典测试。

即使它没有检测到,也需要更少的操作。

但我更喜欢这个的最大原因是没有神奇的数字

于 2012-01-16T20:56:29.537 回答
4

三个挑剔:

  • sizeof(abs_diff)*8 - 1可以用字面量替换而不损失可移植性(实际上,由于 a不是 8 位宽的平台63,它会便携)char
  • & 1不需要,因为移位的结果总是一位
  • 您可以diff从不abs_diff重复减法得出。

否则,这对我来说似乎完全正确。

于 2012-01-16T20:49:03.053 回答
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;
}
于 2012-01-16T21:03:19.040 回答