我正在尝试用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;
}
答案 0 :(得分: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;
}
答案 1 :(得分:4)
三个挑剔:
sizeof(abs_diff)*8 - 1
可以替换为文字63
而不会丢失可移植性(事实上,由于char
是& 1
的平台,因此更多可移植不是8位宽)diff
不需要,因为移位的结果总是一位abs_diff
派生{{1}}而不重复减法。否则,这对我来说似乎完全正确。
答案 2 :(得分: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
是前一个表达式的进位标志。比较这两个标志是溢出的经典测试。
即使没有检测到,也需要更少的操作。
但我更喜欢这个的最大原因是没有神奇的数字。
答案 3 :(得分: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;
}