如何检查A + B是否超长? (A和B都很长)

时间:2013-04-10 08:26:06

标签: c++ long-long

我有两个号码:AB。我需要在代码中的某处计算A+BAB都是long long,它们可以是正面或负面

我的代码运行错误,我怀疑在计算A+B时会出现问题。我只是想检查A+B是否超过long long范围。所以,任何方法都是可以接受的,因为我只将它用于调试。

4 个答案:

答案 0 :(得分:31)

仅当两个数字具有相同符号时才可能溢出。如果两者都是正数,那么如果数学A + B > LLONG_MAX或等效B > LLONG_MAX - A,则会出现溢出。由于右侧是非负的,后一种情况已经暗示B > 0。类似的论点表明,对于否定的情况,我们也不需要检查B的符号(感谢Ben Voigt指出B上的符号检查是不必要的)。然后你可以检查

if (A > 0) {
    return B > (LLONG_MAX - A);
}
if (A < 0) {
    return B < (LLONG_MIN - A);
}
return false;

检测溢出。由于初始检查,这些计算不会溢出。

检查A + B结果的符号将有效保证溢出整数计算的环绕语义。但是有符号整数的溢出是未定义的行为,即使在环绕是实现行为的CPU上,编译器也可能认为没有发生未定义的行为,因此在实现时完全删除溢出检查。因此,对问题的评论中建议的检查非常不可靠。

答案 1 :(得分:7)

如下所示:

long long max = std::numeric_limits<long long>::max();
long long min = std::numeric_limits<long long>::min();

if(A < 0 && B < 0) 
    return B < min - A;
if(A > 0 && B > 0)
    return B > max - A;

return false;

我们可以解释如下:

  • 如果AB符号相反,则它们不会溢出 - 大于零的那个需要大于max或者小于零的那个需要溢出小于min

  • 在其他情况下,简单的代数就足够了。 A + B > max => B > max - A如果两者都是正面的话会溢出。否则,如果它们都是否定的,A + B < min => B < min - A

答案 2 :(得分:2)

此外,如果您仅将其用于调试,则可以使用以下“黑客”功能。直接读取上一个操作的溢出位(假设你的编译器/ cpu支持这个):

int flags;
_asm {
    pushf       // push flag register on the stack
    pop flags   // read the value from the stack
}
if (flags & 0x0800) // bit 11 - overflow
    ...

答案 3 :(得分:2)

屏蔽符号,转换为无符号值,然后执行添加。如果它高于1 << (sizeof(int) * 8 - 1)那么你就会溢出。

int x, y;
if (sign(x) == sign(y)){
    unsigned int ux = abs(x), uy = abs(y);    
    overflow = ux + uy >= (1 << (sizeof(int) * 8 - 1));
}

更好的是,让我们写一个模板:

template <typename T> 
bool overflow(signed T x, signed T y){
    unsigned T ux = x, uy = y;
    return ( sign(x) == sign(y) && (ux + uy >= (1 << (sizeof(T) * 8 - 1)));
}